Maj*_*kel 3 inheritance domain-driven-design composition aggregateroot
考虑以下示例:
例如:
OrderA 必须有一笔交易。
OrderB 必须有两笔交易。
OrderC 可以有 n 笔交易。
当我们更新订单的价值时,我们需要根据算法特定的订单类型来计算交易的价值。
我们如何为这种情况设计模型?我们可以在aggregateRoot中使用继承还是我们应该使用组合?例如 ?
/// <summary>
/// AggregateRoot
/// </summary>
public abstract class Order
{
protected ISet<Transaction> _transactions;
public IEnumerable<Transaction> Transactions
{
get { return _transactions; }
}
public abstract OrderType OrderType { get; }
public decimal? Value { get; protected set; }
public void SetValue(decimal? value)
{
Value = value;
UpdateReleatedTransaction();
}
protected abstract void UpdateReleatedTransaction();
}
public class OrderA : Order
{
public OrderA()
{
_transactions.Add(new Transaction(this));
}
public override OrderType OrderType
{
get { return OrderType.OrderTypeA; }
}
protected override void UpdateReleatedTransaction()
{
EnumerableExtensions.ForEach(_transactions, tran => { tran.SetValue(Value); });
}
}
public class OrderB : Order
{
public OrderB()
{
_transactions.Add(new Transaction(this)
{
Status = Status.Open
});
_transactions.Add(new Transaction(this)
{
Status = Status.Close
});
}
public override OrderType OrderType
{
get { return OrderType.OrderTypeB; }
}
protected override void UpdateReleatedTransaction()
{
EnumerableExtensions.ForEach(_transactions, tran =>
{
if (tran.Status == Status.Open)
tran.SetValue(Value);
if (tran.Status == Status.Close)
tran.SetValue(-1*Value);
});
}
}
Run Code Online (Sandbox Code Playgroud)
DDD 聚合根中的继承是一个棘手的话题。我认为大多数人(我想我也在实现领域驱动设计中读过这篇文章)会选择在 AR 中不继承。
要考虑的要点是行为。未来不同的订单类型是否会有不同的公共接口?如果答案是肯定的,那么您必须经历每个订单拥有不同 AR(以及存储库)的路线。我知道你没有问过这个问题,但记住它是件好事:)。
鉴于您的示例,恕我直言,使用组合没有太大价值,因为新的 AR 只是 Order 的一个非常薄的包装器,并且该包装器除了委托之外没有任何责任。如果保持代码简洁,重构它(创建封装订单的 AR)应该非常容易。
免责声明:过去 5 年我一直在使用DDD,但我仍然很难理解它......所以请保留一点我的建议。