Think of your favorite coffee shop. The barista doesn’t start making your drink the moment you walk in – they wait for your order, check if they have the ingredients, then begin brewing. Systems work the same way, using three key decision-makers: guard conditions, events, and actions. Let’s break down how these invisible bouncers, triggers, and workers make systems behave intelligently.
The Bouncer: Guard Conditions
Guard conditions are the velvet ropes of system design. They decide who gets in and who stays out.
Real-world example:
Your car’s push-start system has a simple guard:
[Foot on brake] && [Key fob detected]
No brake? No start. It’s that simple.
Why they matter:
- Prevent impossible situations (like a microwave running with an open door)
- Create dependencies (can’t shift to Drive unless you’re in Park first)
- Handle safety checks (elevator won’t move if doors are ajar)
Pro tip: Good guard conditions read like plain English:
- Bad: [x>y && !z || (a<b)]
- Good: [Battery_Level > 20%] && [Not_Updating]
The Trigger: Events
Events are the “someone poked me” moments that make systems pay attention.
Types you’ll encounter:
- The Doorbell (Signal Events)
- Physical button press
- Text message received
- The Alarm Clock (Time Events)
- “After 30 minutes of inactivity…”
- “Every Friday at 3 PM…”
- The Thermostat (Change Events)
- “When temperature drops below 68°F…”
- “When battery reaches 10%…”
Case study:
Your office printer’s states:
- Sleep → Wake on [Document Received] event
- Printing → Jammed on [Paper_Stuck] event
- Any state → Maintenance on [Toner_Low] event
The Worker: Actions
Actions are what actually gets stuff done – the gears turning behind the scenes.
Three flavors:
- The Greeter (Entry Actions)
- Smart bulb: When entering “Sunset Mode,” gradually dim over 2 minutes
- The Cleanup Crew (Exit Actions)
- Washing machine: On exiting “Spin Cycle,” unlock the door
- The Courier (Transition Actions)
- Tesla: When going from “Parked” to “Driving,” retract side mirrors
Watch out for:
- Overloading actions (one transition shouldn’t do five unrelated things)
- Forgetting cleanup (that’s how you get apps that “forget” settings)
Putting It All Together: A Smart Lock Story
Let’s follow a night in the life of your front door lock:
- State: Locked
- Guard: [Home_Armed == True]
- Waiting for: [Keypad_Code_Entered] event
- Transition:
- Condition: [Code == Correct]
- Action: /RetractDeadbolt() + /LogEntry()
- New State: Unlocked
- Entry Action: Start 30-second countdown
- Exit Action: Flash LED twice
- Auto-Relock:
- Event: [30_seconds_elapsed]
- Guard: [Door_Closed == True]
- Action: /EngageLock()
Why this matters:
When the lock failed to relock last Tuesday, this diagram showed us why – we’d forgotten the [Door_Closed] guard, so it wouldn’t lock if ajar.
Advanced Moves
- The VIP Pass (Priority Events)
- Fire alarms override normal operations
- “Emergency Stop” buttons ignore all guards
- The Memory (State-Specific Guards)
- Your car remembers to turn lights off only if they were manually turned on
- The Silent Partner (Implicit Events)
- Phone switching to landscape when rotated
- Smart vents closing when room reaches temperature
Your Turn
Try mapping:
- Why your air fryer beeps three times when done
- How a parking meter decides when to flag expired time
- What really happens when you “pause” a YouTube video
The magic isn’t in the individual pieces – it’s in how guards, events, and actions work together to create intelligent behavior from simple rules. That’s the art of state machine design.
Remember: Every time a device “just knows” what to do, there’s a carefully crafted set of these rules working behind the scenes. Your job is to make them explicit – before users find the edge cases you didn’t consider.