cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 176 of 218
Ideas this builds on
Low-level design176 / 218

Make legal actions visible

Picture

Pushing a locked turnstile does nothing. Payment unlocks it. Pushing while unlocked admits one passage and locks it again. The current state changes what the same action means.

Predict

Why is one state value safer than unrelated paid and open flags?

Walk through the small example

Independent booleans can represent combinations the domain never intended. Named states and checked transitions make the legal combinations and actions explicit.

Mental model and complete Python solution

Use an enum for LOCKED and UNLOCKED. Each operation checks the current state and performs exactly the allowed transition. payment returns False if already unlocked; it is a simulated authorization signal, not an actual money-taking operation. push returns True only when it consumes one unlocked passage. A full State pattern with per-state classes is an optional refactoring when behavior grows; two clear branches do not require that machinery.

What the function promises: A Turnstile starts locked. payment signals one accepted authorization if locked. push attempts one passage. Rejected actions leave state unchanged. Real payment/refund processing is outside this simulation.

from enum import Enum, auto

class GateState(Enum):
    LOCKED = auto()
    UNLOCKED = auto()

class Turnstile:
    def __init__(self):
        self._state = GateState.LOCKED

    @property
    def state(self):
        return self._state

    def payment(self):
        if self._state is GateState.UNLOCKED:
            return False
        self._state = GateState.UNLOCKED
        return True

    def push(self):
        if self._state is GateState.LOCKED:
            return False
        self._state = GateState.LOCKED
        return True

gate = Turnstile()
assert not gate.push()
assert gate.payment()
assert not gate.payment()
assert gate.push()
assert gate.state is GateState.LOCKED
assert not gate.push()

Work and storage: O(1) time and storage for each transition. Clarity comes from the explicit behavior table, not runtime optimization.

When to recognize it: The same action means different things depending on the object’s current state.

Check before applying it: A state diagram does not enforce itself. Route mutations through checked transitions; do not scatter independent boolean flags.

Change one rule

A sensor introduces JAMMED and MAINTENANCE states. What should happen before adding more conditions?

See what changes

Write the legal action/state transitions and failure outcomes first. Then choose whether a transition table or separate State objects makes those rules easier to maintain and test.

Connect

state: State remembers what changes the next legal action.

Design a vending machine: Money, selection, and dispensing need explicit transition rules.