The before code allows any status update, risking invalid states. The after code defines allowed transitions and raises an error if an invalid move is attempted, enforcing correct order state flow.
### Before: No state machine, just free status updates
class Order:
def __init__(self):
self.status = 'placed'
def update_status(self, new_status):
self.status = new_status
### After: Using a state machine to enforce valid transitions
class OrderStateMachine:
allowed_transitions = {
'placed': ['paid', 'cancelled'],
'paid': ['shipped', 'cancelled'],
'shipped': ['delivered'],
'delivered': [],
'cancelled': []
}
def __init__(self):
self.state = 'placed'
def transition(self, new_state):
if new_state in self.allowed_transitions[self.state]:
self.state = new_state
else:
raise ValueError(f"Invalid transition from {self.state} to {new_state}")
# Usage
order = OrderStateMachine()
order.transition('paid') # valid
order.transition('shipped') # valid
# order.transition('placed') # raises error