State
A customer cancelled an order while the rider was standing at their door. The app gave a full refund. The customer also took the food.
cancel() checked if (status !== 'delivered'). That was correct when there were two
statuses. By now there were five, and "out for delivery" had been added to assignRider,
to markDelivered and to the tracking screen, but nobody had gone back to cancel. Five
methods, five statuses, 25 combinations, and the rules for them were spread across if
statements in every method.
An order moves through placed, cooking, out for delivery and delivered. cancel() and next() should behave differently at each stage. Where would you put the rule for what cancel() does while the order is cooking, so that adding a new stage cannot leave it forgotten?
The idea#
Same junction, same cars, same drivers. What you are allowed to do depends on which light is on. And each light knows its successor: green hands over to amber, amber to red. Nobody at the junction holds a rulebook with every case in it. The light that is on right now is the rule.