The before code mixes validation, calculation, and data saving in one method, making it hard to maintain. The after code separates concerns: Order and OrderItem represent the domain model with business logic, OrderRepository handles data persistence, and OrderService coordinates actions. This clear separation follows DDD principles.
### Before applying DDD - tangled business logic mixed with data access
class OrderService:
def create_order(self, user_id, items):
# Validate items
if not items:
raise ValueError("No items")
# Calculate total
total = sum(item['price'] * item['qty'] for item in items)
# Save order directly
order = {'user_id': user_id, 'items': items, 'total': total}
database.save(order)
return order
### After applying DDD - clear domain model and separation
class OrderItem:
def __init__(self, product_id, price, quantity):
self.product_id = product_id
self.price = price
self.quantity = quantity
def total_price(self):
return self.price * self.quantity
class Order:
def __init__(self, user_id):
self.user_id = user_id
self.items = []
def add_item(self, item: OrderItem):
self.items.append(item)
def total(self):
return sum(item.total_price() for item in self.items)
class OrderRepository:
def save(self, order: Order):
# Persist order to database
pass
class OrderService:
def __init__(self, repository: OrderRepository):
self.repository = repository
def create_order(self, user_id, items_data):
if not items_data:
raise ValueError("No items")
order = Order(user_id)
for data in items_data:
item = OrderItem(data['product_id'], data['price'], data['quantity'])
order.add_item(item)
self.repository.save(order)
return order