DDD(领域驱动设计)我可以使用继承吗?

Maj*_*kel 3 inheritance domain-driven-design composition aggregateroot

考虑以下示例:

  • 我们有订单,任何订单都可以有不同的类型。
  • 订单有交易,每种订单可以分配n笔交易。

例如:

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)

Aug*_*sto 8

DDD 聚合根中的继承是一个棘手的话题。我认为大多数人(我想我也在实现领域驱动设计中读过这篇文章)会选择在 AR 中不继承。

要考虑的要点是行为。未来不同的订单类型是否会有不同的公共接口?如果答案是肯定的,那么您必须经历每个订单拥有不同 AR(以及存储库)的路线。我知道你没有问过这个问题,但记住它是件好事:)。

鉴于您的示例,恕我直言,使用组合没有太大价值,因为新的 AR 只是 Order 的一个非常薄的包装器,并且该包装器除了委托之外没有任何责任。如果保持代码简洁,重构它(创建封装订单的 AR)应该非常容易。

免责声明:过去 5 年我一直在使用DDD,但我仍然很难理解它......所以请保留一点我的建议。