我来详细介绍一下如何在 Ruby 中应用领域驱动设计(DDD)的核心概念和实践。
# 领域层 (Domain Layer)
module Domain
# Value Object
class Money
attr_reader :amount, :currency
def initialize(amount, currency)
@amount = amount
@currency = currency
end
def ==(other)
amount == other.amount && currency == other.currency
end
end
# Entity
class Order
attr_reader :id, :items, :total_amount
def initialize(id)
@id = id
@items = []
@total_amount = Money.new(0, 'CNY')
end
def add_item(product, quantity)
item = OrderItem.new(product, quantity)
@items << item
recalculate_total
end
private
def recalculate_total
@total_amount = Money.new(
items.sum { |item| item.subtotal.amount },
'CNY'
)
end
end
# Aggregate Root
class OrderItem
attr_reader :product, :quantity
def initialize(product, quantity)
@product = product
@quantity = quantity
end
def subtotal
Money.new(product.price.amount * quantity, product.price.currency)
end
end
# Repository
class OrderRepository
def find(id)
# 从数据库获取订单
end
def save(order)
# 保存订单到数据库
end
end
# Domain Service
class OrderProcessor
def initialize(order_repository)
@order_repository = order_repository
end
def process_order(order)
# 处理订单的业务逻辑
validate_order(order)
apply_discount(order)
@order_repository.save(order)
end
private
def validate_order(order)
raise "Order must have items" if order.items.empty?
end
def apply_discount(order)
# 应用折扣规则
end
end
end
# 应用层 (Application Layer)
module Application
class OrderService
def initialize(order_processor)
@order_processor = order_processor
end
def create_order(order_data)
order = Domain::Order.new(generate_id)
order_data[:items].each do |item_data|
product = find_product(item_data[:product_id])
order.add_item(product, item_data[:quantity])
end
@order_processor.process_order(order)
order
end
private
def generate_id
SecureRandom.uuid
end
def find_product(id)
# 查找商品
end
end
end
让我解释一下在 Ruby 中实现 DDD 的关键概念:
- 领域对象的类型:
- Value Object(值对象):如示例中的 Money 类,是不可变的,通过值而非身份比较相等性
- Entity(实体):如 Order 类,具有唯一标识符和生命周期
- Aggregate(聚合):如 Order 和 OrderItem 的关系,确保业务不变性
- 领域服务:
- OrderProcessor 展示了如何封装跨实体的业务逻辑
- 处理复杂的业务规则和转换
- 仓储模式:
- OrderRepository 负责持久化和检索聚合根
- 封装数据访问细节
- 应用服务:
- OrderService 作为应用层服务,协调领域对象和服务
- 处理事务边界和用例实现
- Ruby 特定实践:
- 使用模块(module)来组织代码
- 利用 Ruby 的封装特性保护领域模型
- 使用 attr_reader 来实现不可变性
你可以根据实际需求调整这个结构。比如:
- 添加更多的领域事件
- 实现更复杂的业务规则
- 添加规范模式(Specification Pattern)
- 增加领域服务的复杂度