Overview

Emlang is a YAML-based DSL for describing systems with Event Modeling patterns.

  • An Emlang file must be a valid YAML file
  • Each YAML document must contain a slices top-level key
  • slices may be empty
  • A file may contain multiple YAML documents separated by ---
  • The root object must not contain properties other than slices
slices:
  SliceName:
    - t: Swimlane/TriggerName
    - c: DoSomething
    - e: SomethingDone

Elements

Emlang defines 5 element types, each with multiple prefix forms:

Type Short Acronym Long
Trigger t: trg: trigger:
Command c: cmd: command:
Event e: evt: event:
Exception x: err: exception:
View v: view:
  • All prefix forms of a given type are semantically equivalent
  • An element must contain exactly one type key
  • An element may contain a props key
  • An element must not contain keys other than one type key and props
# Valid
- c: RegisterUser
- e: UserRegistered

# Invalid: two type keys in the same item
- c: RegisterUser
  e: UserRegistered

Naming

  • Element names are free-form text
  • Names must not be empty
  • Names must not end with /
  • Names may contain spaces, accents, and special characters

Swimlanes

Swimlanes are optional. A swimlane is specified as a prefix separated by / before the element name.

- t: Customer/RegistrationForm   # Swimlane: Customer
- e: User/UserRegistered         # Swimlane: User
- c: RegisterUser                # No swimlane

Properties

Properties are optional and defined under a props key. The structure of props is free-form — consuming tools decide how to interpret them.

- c: RegisterUser
  props:
    email: string
    password: string

Slices

A slice is a named sequence of elements representing a business scenario. A slice may be empty.

Direct Form

The direct form is a list of elements. It should be used when a slice has no attached tests.

slices:
  UserRegistration:
    - t: Customer/RegistrationForm
    - c: RegisterUser
    - e: User/UserRegistered
    - v: UserProfile

Extended Form

The extended form is an object with steps and optionally tests. Use it when a slice has tests.

  • steps is required but may be empty
  • tests is optional and may be empty
  • The extended form must not contain properties other than steps and tests
slices:
  UserRegistration:
    steps:
      - t: Customer/RegistrationForm
      - c: RegisterUser
      - e: User/UserRegistered
    tests:
      EmailMustBeUnique:
        given:
          - e: User/UserRegistered
            props:
              email: joe@example.com
        when:
          - c: RegisterUser
            props:
              email: joe@example.com
        then:
          - x: EmailAlreadyInUse

Multiple Slices

Multiple slices may be defined in the same document. Both direct and extended forms may coexist.

slices:
  UserRegistration:
    - t: Customer/RegistrationForm
    - c: RegisterUser
    - e: User/UserRegistered

  UserLogin:
    - t: Customer/LoginForm
    - c: AuthenticateUser
    - e: User/UserAuthenticated
    - v: Dashboard

Tests

Tests are defined inside a slice using the extended form. Each test follows a Given-When-Then structure.

Section Required Allowed element types
given No Events (e:), Views (v:)
when No Commands (c:)
then No Events (e:), Views (v:), Exceptions (x:)
  • given, when, and then are all optional and may be empty
  • A test may be empty
  • A test must not contain properties other than given, when, and then
  • A slice may contain multiple named tests
tests:
  EmailMustBeUnique:
    given:
      - e: User/UserRegistered
        props:
          email: joe@example.com
    when:
      - c: RegisterUser
        props:
          email: joe@example.com
    then:
      - x: EmailAlreadyInUse

  PasswordMustBeStrong:
    when:
      - c: RegisterUser
        props:
          password: "123"
    then:
      - x: PasswordTooWeak

  TodoCompleteRegistrationFlow:

Document Structure

A file may contain one or more YAML documents separated by ---. Each document must independently conform to this specification.

---
slices:
  UserRegistration:
    - t: Customer/RegistrationForm
    - c: RegisterUser
    - e: User/UserRegistered

---
slices:
  UserDeletion:
    steps:
      - t: Admin/UserManagement
      - c: DeleteUser
      - e: User/UserDeleted
    tests:
      CannotDeleteActiveUser:
        given:
          - e: User/UserAuthenticated
        when:
          - c: DeleteUser
        then:
          - x: UserCurrentlyActive

Comments

Standard YAML comments (#) may be used anywhere.

slices:
  OrderPlacement:
    - t: Customer/ProductPage    # User clicks "Buy Now"
    - c: PlaceOrder              # Validates inventory
    - e: Order/OrderPlaced       # Core domain event