Skip to content

Session 5: Review

The final session. The full team joins the video call to review the complete system, validate everything works, and ship.

Setting the Scene

Everyone's back on the video call. Alex shares their screen with the flow file and tests ready.

bash
$ eventflow watch order.flow

  EventFlow v1.0.0

  Editor:   http://localhost:5173/
  Diagram:  http://localhost:5173/diagram
  Tests:    http://localhost:5173/tests

  Watching for changes...
This is our final review before shipping. Let's see everything we've built together.
I'll run the full test suite with coverage so we can see the complete picture.

Running the Final Tests

bash
$ eventflow test order.flow order.test.flow --with-bindings --coverage

Loading bindings... 15 found
Validating all bindings...

@order / checkout

  happy path
 checkout awaiting_payment (18ms)
 payment_success confirmed (21ms)

  :checkout variations
 empty cart rejected (12ms)
 guest user redirected to login (10ms)

  :payment_success variations
 confirmation email is sent (14ms)

  :payment_failed variations
 payment failure notifies customer (11ms)

  :retry_checkout variations
 retry after payment failure (16ms)
 retry limit exceeded (13ms)
 admin can override retry limit (12ms)

9 passing

Coverage:
  States:   5/5   (100%)  #idle, #awaiting_payment, #confirmed, #payment_failed, #cancelled
  Events:   6/6   (100%)  :checkout, :payment_request, :payment_success, :payment_failed, :retry_checkout, :order_confirmed
  Guards:   5/5   (100%)  login, cart, retry_limit, admin, state_check
  Actions:  4/4   (100%)  generate_id, generate_timestamp, increment_retry, send_email
100% coverage! Every state, event, guard, and action is tested.
Can we see the complete diagram one more time? I want to share it with the marketing team.
The diagram is live at localhost:5173/diagram. Let me pull it up.

The Complete Flow Diagram

@customer@order@paymentStates#idle:checkout? @customer is logged in? cart is not empty:login_required:checkout_rejected$order_id becomes uuid()$created_at becomes now():payment_request($order_id, $total)#awaiting_payment(external processing):payment_successsend confirmation email:order_confirmed($order_id)#confirmed:payment_failed$retry_count increases by 1:payment_failed_notification#payment_failed:retry_checkout
This diagram tells the complete story. Anyone can understand our checkout flow.
And it's always accurate because it's generated from the actual flow file.

Reviewing Our Journey

Let me summarize what we've accomplished across all five sessions.

Session Summary

12345DiscoveryHappy PathEdge CasesImplementationReviewActors, EventsBasic flowFull teamContext varsFirst testsFull teamTest fileassume/observeQA + DevGuards, BindingsAll tests greenDev soloFinal checkShip it!Full teamorder.flow v12 tests ✓7 tests (6 fail)9 tests + 15 bindings100% coverage
We started with an idea and ended with production-ready code in five sessions.
And the flow file remains readable by everyone - marketing, support, new developers.

What We Built

The Numbers

MetricCount
States5
Events6
Guards5
Actions4
Tests9
PHP Bindings15
Coverage100%

The Artifacts

Let me list everything we created.
ArtifactPurpose
order.flowThe state machine definition in natural language
order.test.flowTest file with happy path and edge cases
OrderMachine.phpMachine registration with all bindings
5 Guard classesLogin, cart, retry limit, admin, state check
4 Action classesID generation, timestamp, retry count, email
6 Event classesAll events with structured data

Living Documentation

The best part is that this flow file IS our documentation. It can't go stale because the tests enforce it.
If someone changes the code in a way that breaks the flow, the tests fail immediately.
So the diagram always reflects reality?
Exactly. The diagram is generated from the flow, and the flow is tested. It's a single source of truth.

Planning for Changes

What happens when requirements change? Say we want to add inventory checking.
We follow the same process: discuss → write test → update flow → add bindings → run tests.
flow
// Future: Adding inventory check
on> :checkout from @customer
  ? @customer is logged in
    ? cart is not empty
      ? @inventory has stock for cart  // New guard
        $order_id becomes uuid()
        reserve inventory               // New action
        emit :payment_request to @payment
          with $order_id, $total
        order moves to #awaiting_payment
      : else
        emit :out_of_stock to @customer // New event
    : else
      emit :checkout_rejected to @customer
  : else
    emit :login_required to @customer
The existing 9 tests ensure we don't break anything while adding new features.
And the new feature follows the same pattern - guard for the check, action for the side effect, event for communication.

The Final Flow File

Here's our complete, production-ready flow file.
flow
// order.flow - Final Version
machine: @order

scenario: checkout

  given:
    @customer is logged in
    cart has items
    $total: number is calculated
    $retry_count: number is 0

  on> :checkout from @customer
    ? @customer is logged in
      ? cart is not empty
        $order_id: string becomes uuid()
        $created_at: string becomes now()
        emit :payment_request to @payment
          with $order_id, $total
        order moves to #awaiting_payment
      : else
        emit :checkout_rejected to @customer
          with reason: "Please add items to your cart before checking out"
    : else
      emit :login_required to @customer
        with message: "Please log in to complete your purchase"

    expect:
      = order is in #awaiting_payment

  on :payment_success from @payment
    send confirmation email
    emit :order_confirmed to @customer
      with $order_id
    order moves to #confirmed

  on :payment_failed from @payment
    $retry_count increases by 1
    emit :payment_failed_notification to @customer
      with $order_id
      with reason: "Payment could not be processed. Please try again."
    order moves to #payment_failed

  on> :retry_checkout from @customer
    ? order is in #payment_failed
      ? $retry_count is less than 3
      ?? @customer is admin
        emit :payment_request to @payment
          with $order_id, $total
        order moves to #awaiting_payment
      otherwise
        emit :max_retries_exceeded to @customer
          with message: "Maximum payment attempts reached. Please contact support."
        order moves to #cancelled

  expect:
    = order is in #confirmed
    = @customer received :order_confirmed

Closing the Session

This has been a fantastic process. We went from requirements to working code with everyone involved.
I especially liked that I could understand the flow without reading PHP code. When stakeholders ask about the checkout process, I can show them the flow file.
And every edge case we discussed is now a permanent test. No more "did we think about what happens when...?" questions.
The flow file becomes our contract. Marketing, support, and new developers can all read it. The PHP code implements it, but the flow defines the behavior.
Ship it.

Session Outcome

The Event Flowing Process

DiscoveractorsWriteflowThinkdiagramTestfirstBindcodeReviewiterateShipit!Session 1Session 1-2AlwaysSession 3Session 4Session 5Done!

Key Benefits

BenefitDescription
Single source of truthFlow file is documentation, specification, and test
Cross-functional collaborationEveryone can read and contribute to the flow
Automatic diagramsNever out of sync with reality
Test-drivenEdge cases become permanent, executable tests
IncrementalAdd features without breaking existing functionality
Living documentationCan't go stale because tests enforce accuracy

What's Next?

The order flow is ready for production. As the product evolves:

  1. New requirements → New sessions following the same process
  2. Bug reports → New test cases that capture the issue
  3. Refactoring → Existing tests ensure behavior stays consistent
  4. Onboarding → New team members read the flow file to understand the system

The Event Flowing process continues with each new feature, each edge case, each iteration.

Released under the MIT License.