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-001
metadata:
name: sample
The header information is not needed for informal use, but will be useful for tooling.
Aggregates: #
# Aggregates
aggs:
- UserAgg: &User
id: g
firstName: s
lastName: s
age: int
Optionally define a list of aggregates near the top of the document. Each aggregate in the list can be created using the YAML anchor syntax (ie: &User) so it can be referenced later in the document.
Views: #
# Views
views:
- UserView: &UserView
id: g
firstName: s
lastName: s
age: int
Optionally define a list of views near the top of the document. Each document in the list can be created using the YAML anchnor syntax (ie: &UserView) so it can be referenced later in the document.
Slices: #
# A 'Slice' contains a single operation and a single event.
# A command and event and 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: *User
command:
name: AddUser # The command name is optional since by default it will match the name of the Slice
event:
name: AddedUsed # The event name should be the past tense of the command
props:
id: g
firstName: s
lastName: s
age: int
views:
- *UserView
...
Here is an equivelant standard event model:
A list of slices are defined after the optional aggregates and views. We put these after the aggregates and views so we can reference the YAML anchors using YAML aliases such as **User* and **UserView*.
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 atleast one event. Views are updated by handling events.
Properties of slices include:
- agg: 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 imperitive (ie: ‘DoSomething!’)
- event: An event is the result of a command. 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, the views can be listed here. Using the YAML alias syntax allows for linking back to a views that was optionally defined at the top of the document.
- wfes: If the events will trigger a ‘WorkFlowEngine’ (WFE) process, then the WFEs can be listed here.
The full document: #
apiVersion: teml.org/v-alpha-001
metadata:
name: sample
# Aggregates
aggs:
- UserAgg: &User
id: g
firstName: s
lastName: s
age: int
# Views
views:
- UserView: &UserView
id: g
firstName: s
lastName: s
age: int
# A 'Slice' contains a single operation and a single event.
# A command and event and 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: *User
command:
name: AddUser # The command name is optional since by default it will match the name of the Slice
event:
name: AddedUsed # The event name should be the past tense of the command
props:
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: *User
event:
name: RenamedUser
props:
id: g
firstName: s
lastName: s
views:
- <<: *UserView
id: x
firstName: x
- ReAgeUser: # 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)
story: "https://www.example.com/12345"
status: InDev
agg: *User
event:
name: ReAgedUser
props:
id: g
age: int
views:
- <<: *UserView
id: x
age: int
The full version would be good as a final document or if generated by a tool that parses the code to generate documenatation.
Skimmed Down Version: #
# Header left out for brevity
# Aggregates
aggs:
- UserAgg: &User id
firstName
lastName
age
# Views
views:
- UserView: &UserView id
firstName
lastName
age
# Slices
slices:
- AddUser:
event: AddedUser
props
- id
- firstName
- lastName
- age
views:
- *UserView
- RenameUser:
event: RenamedUser
props
- id
- firstName
- lastName
views:
- *UserView
- ReAgeUser:
event: ReAgedUser
props
- age
views:
- *UserView
This version is fairly minimal. Most of the valuable information is still conveyed. We can still see there is one aggregate, two views 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 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 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.