DDD(领域驱动设计)我可以使用继承吗?
DDD (Domain Driven Design) Can I use inheritance ?
考虑以下示例:
- 我们有订单,任何订单都可以是不同的类型。
- 该订单有交易,每种订单可以分配n笔交易。
例如:
OrderA 必须有一笔交易。
OrderB 必须有两个事务。
OrderC可以有n笔交易。
我们在更新Order的值时,需要根据算法指定的订单类型计算交易的价值。
我们如何为这种情况设计模型?
我们可以在 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);
});
}
}
DDD 聚合根中的继承是一个棘手的话题。我想大多数人(我想我也在实施领域驱动设计中读到过这个)会选择不在 AR 中继承。
要考虑的重点是行为。以后不同的订单类型会有不同的public接口吗?如果答案是肯定的,那么您必须经历每个订单(以及存储库)具有不同 AR 的过程。我知道你没有问过这个问题,但最好记住它:)。
鉴于您的示例,恕我直言,使用组合的价值不大,因为新的 AR 只是 Order 的一个非常薄的包装器,并且该包装器除了委托之外没有任何责任。如果你保持代码干净,重构它(创建一个封装订单的 AR)应该很容易。
免责声明:在过去的 5 年里,我一直使用 DDD,但我仍然很难理解它...所以请对我的建议持保留态度。
考虑以下示例:
- 我们有订单,任何订单都可以是不同的类型。
- 该订单有交易,每种订单可以分配n笔交易。
例如:
OrderA 必须有一笔交易。
OrderB 必须有两个事务。
OrderC可以有n笔交易。
我们在更新Order的值时,需要根据算法指定的订单类型计算交易的价值。
我们如何为这种情况设计模型? 我们可以在 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);
});
}
}
DDD 聚合根中的继承是一个棘手的话题。我想大多数人(我想我也在实施领域驱动设计中读到过这个)会选择不在 AR 中继承。
要考虑的重点是行为。以后不同的订单类型会有不同的public接口吗?如果答案是肯定的,那么您必须经历每个订单(以及存储库)具有不同 AR 的过程。我知道你没有问过这个问题,但最好记住它:)。
鉴于您的示例,恕我直言,使用组合的价值不大,因为新的 AR 只是 Order 的一个非常薄的包装器,并且该包装器除了委托之外没有任何责任。如果你保持代码干净,重构它(创建一个封装订单的 AR)应该很容易。
免责声明:在过去的 5 年里,我一直使用 DDD,但我仍然很难理解它...所以请对我的建议持保留态度。