Drawing a UML statechart, one question at a time
Seven versions of the same statechart for one Order object, each one a question asked of the client — and why the flawed ones are the point.
Statecharts are one of the more interesting UML diagrams, and one of the more misunderstood: they model a single object and the states it can be in. Plenty of resources, including good ones, blur statecharts and activity diagrams together. A statechart is about one thing changing state. An activity diagram is about work flowing.
This is my train of thought while drawing one, in order, including the parts that turn out to be wrong. If you would rather see the finished thing, skip to the last diagram.
The example is an Order object in an e-commerce system, because everyone has met one.
Asking the client is the part of the process people skip. So we ask:
- When a customer places an order, what happens? —
Placed - What if there is nothing in stock? —
Pending
Two questions, two states. Nothing about how the object moves yet.
Now the interesting part: how does the object move from one state to another? Back to the client.
- What moves an order from
placedtopending? Is it automatic, a stock check, or does someone press something? - Does the customer pay before or after it moves?
One of those answers gives us our first transition label.
We are not done, because the answers to the next questions are not states — they are conditions:
- What happens if the payment is never made? Can an order sit in
placedforever? - If there is inventory management, are the products held while the customer decides?
- When exactly is stock deducted — before payment, or after?
- What if the payment fails? Can a customer order more than exists?
Every one of those is a condition on the transition from the start, not a state of its own. So the diagram grows a very long label.
And now the question that undoes it: why does Placed exist at all?
If every one of those conditions has to be true before an order moves on, then Placed is not a state anyone acts on. It is a waiting room nobody waits in. So it goes.
With that settled, the next questions are about what comes after pending:
- Do you want a cap on how many items one customer can buy?
- What is the state after
pending— is itpaid, or does the business call it something else?
The cap is a fourth condition, and the answer to the second question is a new state with conditions of its own.
Paid, which will cause trouble shortly.Two or more states means the next question is always the same: what events move one state back to another? So:
- What if the customer is unhappy after paying?
- What if the stock record was wrong and the item is not actually there?
- Remember that nothing is deducted while an order sits in
pending— can two customers both think they have the last one?
That last one is the bug the diagram was hiding, and it needs a transition the shape does not have yet.
Paid can go back to Pending. A dashed return arrow is the cheapest way to show that the first draft of a statechart usually assumes progress is one-way, and that it is not.The questions keep coming, and they are better questions now:
- When exactly is stock deducted — before payment or after?
- If it is after, then between
pendingand a failed payment the item is not held, so another customer may take it. Is that acceptable? - If it is before, how long do you hold it? What if the customer never pays? Is that good business?
- Does
paidgoing back topendingmake sense at all?
And one state is still missing. What happens to an order that is never paid, or that the customer changes their mind about? Cancelled.
Cancelled, and an end marker for each. Not finished — finished is not a thing a statechart gets to be.What it says
In plain English:
- An order can sit in
pending: the customer has placed it and has not paid. - The system moves
pendingtocancelledon its own if the items are no longer in stock, or if payment has not arrived within a set period. pendingcan also be the last state an order is ever in. It is not an error path.- Stock is only reduced once a customer has paid. Which means two customers can both hold an item in
pendingwhile only one of them can pay for it, and the other order simply stays there. pendingmoves tocancelledeither by that timeout or at the customer's request.
And more questions, because there always are:
- What if a product is withdrawn from sale entirely? Cancel every order automatically, or leave them in
pendingfor a human?
What the exercise is for
Going through this in order — including the two versions that were wrong — is the useful part, not the final diagram. The first version had a state that existed for no reason. The third put four conditions on one transition. The fourth deleted a state AND found where the conditions belonged. The sixth admitted that progress can go backwards.
Two things fall out of that:
- The requirements get understood. Every question asked of the client is a question that would otherwise have been an assumption somebody made in code. The
pending-holds-no-stock problem is a real bug in the system above, and it surfaced because a statechart made the awkward question obvious rather than because anyone thought of it. - The enums write themselves. Once the states and transitions are explicit, an
OrderStatusenum is not a guess: it is the list of states, and the transitions are the only places status can change. That is what I mean when I say the making of the diagram is doing the engineering.
Statecharts model one object, and requirements are about many. It is never complete either — requirements change, so the diagram changes, which is why this one is a first iteration rather than an answer.
Bye.
Written in 2021, ported from the old Hugo site. The seven diagrams were mermaid state diagrams there and are hand-authored SVG here, one per version, so the post no longer depends on a diagramming library. The prose is lightly edited; the iteration order and every note are as written.
Comments
Discussion lives on GitHub — you'll need a GitHub account to post.