The before code allows direct modification of order items, risking inconsistent states. The after code encapsulates item management inside the Order aggregate root, enforcing rules and preventing invalid updates.
### Before: No aggregate root, direct entity updates
class OrderItem:
def __init__(self, product_id, quantity):
self.product_id = product_id
self.quantity = quantity
class Order:
def __init__(self):
self.items = []
def add_item(self, item):
self.items.append(item)
order = Order()
order.items.append(OrderItem('p1', 2)) # Direct access allows inconsistent state
### After: Aggregate root controls entity updates
class OrderItem:
def __init__(self, product_id, quantity):
self.product_id = product_id
self.quantity = quantity
class Order:
def __init__(self):
self._items = []
def add_item(self, product_id, quantity):
if quantity <= 0:
raise ValueError('Quantity must be positive')
item = OrderItem(product_id, quantity)
self._items.append(item)
@property
def items(self):
return list(self._items) # Read-only access
order = Order()
order.add_item('p1', 2) # Controlled update through aggregate root