In this article, we’ll specify the behavior of a mechanical egg timer and we’ll have to consider two distinct perspectives:
- That of the user, who interacts with the egg timer by turning the dial forward or backward
- That of the timer’s mechanical logic, which must keep track of time and, somehow, decide when to “ding”
Meet the egg timer
Lets start with the “happy path” flow for a mechanical egg timer:
- User turns the dial forward to set a time
- Timer begins ticking
- User waits for time to elapse
- Timer dings and stops ticking
A first pass might look like this:
wind forward event is caused by the user, and the states (
Ticking) belong to the timer.
time elapsed event is rather mysterious, though.
How does the egg timer know that the time set by the user has elapsed?
The spec needs to sufficiently explain the behavior so that our collaborators can implement it.
Assuming a magic
time elapsed event doesn’t seem much more helpful than saying “build something that works”.
Lets try clarifying the spec so it explains how timer knows that the time has elapsed.
An explosion of states
We can specify the timer’s behavior in more detail by modeling the remaining time using states:
Here we’ve modeled the system in more detail: Instead of thinking of the user winding the timer forward an arbitrary amount, we consider each incremental turn as a separate
wind forward one second event.
And we’ve replaced the “timer magically knows when the time has elapsed” event with a more specific
tick event that occurs every second (and is, presumably, easier for the mechanical engineers to implement).
While this model unambiguously defines the behavior we want, it isn’t great at concisely capturing that behavior. Specifying that the user should be able to wind the dial backward takes quite a bit of typing:
What’s worse, this verbose explosion of states does a poor job of communicating the essential behavior (which is the entire point of specification!)
Good luck convincing an engineer or other busy stakeholder at Egg Timers Incorporated to stay awake while you walk through every state of this spec.
The reason it’s boring is because the essential behavior of all the
N Seconds Left states is identical: The timer is ticking and the user can move the dial forward or backward.
Having so many nearly identical states distracts from the states where the behavior truly is different (that is, the
Stopped state, where the timer is silent and the user cannot turn the dial backward).
So how else can we precisely — but concisely — describe the egg timer’s behavior?
A useful trick we can use here is to introduce a transient state. Unlike a regular state (where our system actually spends time), a transient state is purely notational — it lets us define our system’s internal logic, but without the hassle of dropping all the way down into code. (Think of it like a flowchart.)
We can capture the essence of the egg timer’s behavior by adding a single transient state,
By convention, transient states and the pseudo-events that lead out of them end with a question mark.
We can read this spec as: “If the user moves the dial forward or backward, or if the timer emits a
tick event, the timer should move to either the
Stopped state based on whether or not there is time remaining”.
It’s worth nothing that the timer is never in the
Done? state — it is always either
But when you simulate the behavior by clicking on the diagram, it will end up waiting in the
Done? transient state for you to choose one of the paths out.
That said, if your system does spend some time waiting for logic to run, you might want to model that explicitly with a regular state. A good example is when you send input to a remote server:
There’s a transient state that models the local validation (
Okay To Send?) and a regular state (
Loading) where the system waits for a response.
All interesting systems consist of multiple actors — people, machines, acts of God, etc. — and the art of designing the whole system’s behavior is knowing how to model these actors and their interactions with states, events, and transitions.
From the perspective of someone using the egg timer, there are only two things they can do: wind the timer forward or wind it backward.
But there is a third event in our spec,
tick, which is emitted by a mechanism within the timer itself.
Furthermore, there are two “pseudo-events”:
time remaining? and
no time remaining?, that correspond to instantaneous decisions made by the timer’s mechanical mechanism.
As you interactively sketch and model systems with Sketch.systems, you’ll need to jump between perspectives.
Sometimes you’ll wear the hat of the user, emitting events by interacting with a prototype UI.
But other times you’ll need to emit events via the diagram, pretending to be a mechanical timer emitting
tick events or a database backend accepting or rejecting inputs.
- A mechanical engineer informs you that the egg timer’s internal mechanism needs the user turn the dial past the 10 second mark so that it has enough energy to begin ticking. Fork the egg timer spec and model this new change.