A Simple Example

A Simple Example #

First we will view the sections and then at the end we can see the whole document.

Document Header: #

apiVersion: teml.org/v-alpha-003
metadata:
  name: sample

The header information is not needed for informal use, but will be useful for tooling.

Aggregates: #

# Aggregates
aggs:
  - UserAgg:
      id: g
      firstName: s
      lastName: s
      age: int

Optionally define a list of aggregates. Slices refer to an aggregate by its name, for example agg: UserAgg.

Views: #

# Views
views:
  - UserView:
      id: g
      firstName: s
      lastName: s
      age: int

Optionally define a list of views. Slices refer to a view by its name, for example views: [UserView].

Slices: #

# A 'Slice' usually contains a single command and a single event.
# A command and event are tightly coupled. They operate together and the event will never exist without the command. The command will never exist in a slice without the event.

# Slices
slices:
  - AddUser:
      agg: UserAgg
      command:
        name: AddUser # The command name is optional since by default it will match the name of the Slice
      events:
        - AddedUser: # The event name should be the past tense of the command
            id: g
            firstName: s
            lastName: s
            age: int
      views:
        - UserView
   ...

To see a model like this drawn as an Event Modeling board, visit the demos.


A list of slices makes up the timeline, read from left to right. Sections can appear in any order, because everything is referred to by name.

A slice defines a unit of work in an application. The unit of work is triggered by some external force that calls a command. Every command results in at least one event. Views are updated by handling events.

Properties of slices include:

  • agg: The name of the aggregate that is affected by the slice.
  • command: If not defined, a command is inferred and will have the same name as the slice. A command name should be imperative (ie: ‘DoSomething!’)
  • events: The events that result from the command, usually just one. The name of an event must be in the past-tense. An event name should be declarative (ie: ‘ItWasDone’)
  • views: If the events will affect any views, list the views’ names here. To say which properties the slice touches, write - UserView: [id, age].

A slice can also have a trigger for the command (a screen, an automation or an external system) and Given/When/Then specs, and there are view slices that show where a view is read. See the Introduction and the Specification.

The full document: #

apiVersion: teml.org/v-alpha-003
metadata:
  name: sample
# Aggregates
aggs:
  - UserAgg:
      id: g
      firstName: s
      lastName: s
      age: int

# Views
views:
  - UserView:
      id: g
      firstName: s
      lastName: s
      age: int

# A 'Slice' usually contains a single command and a single event.
# A command and event are tightly coupled. They operate together and the event will never exist without the command. The command will never exist in a slice without the event.

# Slices
slices:
  - AddUser:
      agg: UserAgg
      command:
        name: AddUser # The command name is optional since by default it will match the name of the Slice
      events:
        - AddedUser: # The event name should be the past tense of the command
            id: g
            firstName: s
            lastName: s
            age: int
      views:
        - UserView

  - RenameUser: # In this slice we don't have a command specified. The command is inferred and will be named after the slice ('RenameUser' in this case)
      agg: UserAgg
      events:
        - RenamedUser:
            id: g
            firstName: s
            lastName: s
      views:
        - UserView: [id, firstName, lastName]

  - ReAgeUser: # In this slice we don't have a command specified. The command is inferred and will be named after the slice ('ReAgeUser' in this case)
      story: "https://www.example.com/12345"
      status: InDev
      agg: UserAgg
      events:
        - ReAgedUser:
            id: g
            age: int
      views:
        - UserView: [id, age]

The full version would be good as a final document or if generated by a tool that parses the code to generate documentation.

Skimmed Down Version: #

# Header left out for brevity
# Aggregates
aggs:
  - UserAgg: [id, firstName, lastName, age]

# Views
views:
  - UserView: [id, firstName, lastName, age]

# Slices
slices:
  - AddUser:
      events:
        - AddedUser: [id, firstName, lastName, age]
      views: [UserView]

  - RenameUser:
      events:
        - RenamedUser: [id, firstName, lastName]
      views: [UserView]

  - ReAgeUser:
      events:
        - ReAgedUser: [age]
      views: [UserView]

The property lists use YAML’s [a, b, c] form. Listing names on separate lines without the brackets would turn them into a single string.

This version is fairly minimal. Most of the valuable information is still conveyed. We can still see there is one aggregate, one view and 3 slices. We have shortened the slices by leaving out the command. The command and command-name can be inferred from the slice and slice name. The events are defined because they are the critical piece of information that we need to capture in our system. The event carries the data that will be used by the views and/or processors that handle events. The view that is being updated is defined, but the properties are not listed. This amount of brevity assumes your team would understand which properties would get updated so you only point them to the fact that the view will be updated. You can adjust your level as needed for you and your collaborators.

Once teams become familiar with Event Modeling and with each other, the notation required to communicate can be more and more condensed. This notation allows us to be very brief when needed. It also allows us to add more details if we would like to feed the model into tooling that could help generate code or documentation.