面试题答案
一键面试聚合根的职责
- 封装业务规则:聚合根负责封装与其相关的业务规则。例如,在一个电商系统中,订单作为聚合根,它包含了下单、支付、发货等一系列业务规则,确保这些操作符合业务逻辑。
- 管理聚合内实体:聚合根管理聚合内的其他实体。以订单为例,订单明细是订单聚合内的实体,订单聚合根负责维护订单明细的状态和关联关系,如添加、删除订单明细等操作。
- 确保数据一致性:在聚合范围内,聚合根确保数据的一致性。比如订单的总金额必须等于所有订单明细金额之和,聚合根在相关操作时要保证这种一致性。
代码实现要点
- 数据一致性
- 属性验证:在聚合根的属性设置方法中进行验证。例如订单的下单时间必须晚于创建时间,在设置下单时间属性时添加验证逻辑。
public class Order { private DateTime _creationTime; private DateTime _orderTime; public DateTime OrderTime { set { if (value <= _creationTime) { throw new ArgumentException("下单时间必须晚于创建时间"); } _orderTime = value; } } }
- 操作后数据同步:当聚合根执行某些操作后,要确保聚合内相关数据同步更新。如订单支付成功后,要更新订单状态以及相关支付记录。
- 事务处理
- 使用事务范围:在对聚合根进行复杂操作时,使用
TransactionScope
确保数据的原子性。例如,在订单发货操作中,可能涉及更新订单状态、库存扣减等多个操作,需要放在同一事务中。
using (TransactionScope scope = new TransactionScope()) { // 更新订单状态 order.OrderStatus = OrderStatus.Shipped; // 库存扣减操作 inventory.DecreaseStock(order.OrderDetails); scope.Complete(); }
- 使用事务范围:在对聚合根进行复杂操作时,使用
- 聚合根的唯一性标识
- 设置唯一标识属性:每个聚合根都应有唯一标识,如订单的订单编号。这个标识在整个系统中用于唯一识别该聚合根。
public class Order { public Guid OrderId { get; private set; } public Order() { OrderId = Guid.NewGuid(); } }
- 聚合边界控制
- 避免外部直接访问内部实体:聚合根作为聚合的入口,外部对象应通过聚合根来间接访问聚合内的实体。例如,外部代码不应直接访问订单明细,而是通过订单聚合根提供的方法来操作订单明细。
public class Order { private List<OrderDetail> _orderDetails = new List<OrderDetail>(); public void AddOrderDetail(OrderDetail detail) { _orderDetails.Add(detail); } public IEnumerable<OrderDetail> GetOrderDetails() { return _orderDetails; } }