【问题标题】:Is it acceptable for Domain Objects to create objects?域对象可以创建对象吗?
【发布时间】:2017-06-20 08:23:58
【问题描述】:

请看代码:

public System.Collections.Generic.IEnumerable<IDenomination> GetDenominations(decimal Cost, decimal PaymentReceived)
{
    decimal ChangeRequired = PaymentReceived - Cost;
    foreach (decimal CurrencyAmount in Currency.CurrencyDenominations())
    {
        if (ChangeRequired / CurrencyAmount >= 1)
        {
            int Quantity = (int)Math.Floor(ChangeRequired / CurrencyAmount);
            IDenomination  ChangeDenomination = ChangeDenominationsFactory.Create(CurrencyAmount, Quantity);
            yield return ChangeDenomination;
            ChangeRequired = ChangeRequired - (ChangeDenomination.Amount * ChangeDenomination.Quantity);
        }
    }
}

此方法是域对象的一部分。我担心的是域对象负责通过工厂创建对象。从 DDD 的角度来看,这是否可以接受?

昨天我正在阅读一个问题,SLaks (https://stackoverflow.com/users/34397/slaks) 回答(或评论)与此类似。他建议使用工厂或 Func 代表。我没有保存指向我收藏夹的链接。我花了将近 1.5 个小时来寻找这个问题,但是我找不到它。如果其他人可以找到它,请发布链接。我在徘徊 Func 委托是否会更好(这样包含上面迭代器的类就不必知道工厂。

【问题讨论】:

  • 听起来你真正的问题是关于耦合,而不是对象创建。如果是这种情况,您应该提出一个新问题。

标签: c# unit-testing domain-driven-design


【解决方案1】:

Domain Objects 可以创建对象吗?

是的,这通常是新表示的来源。

例如,请参阅Don't Create Aggregate Roots。或者事件源系统中的无数示例中的任何一个,其中域对象创建描述它们如何随时间演变的事件。

Greg Young 经常使用 TradeBook 作为事件源域的示例。订单来自外部世界,但领域模型负责决定将哪些订单配对在一起进行交易。因此,代表 Trade 的值对象是在域模型中创建的。

该对象是通过直接调用其构造函数,还是通过调用模型中其他对象的方法,或调用工厂中的方法,或调用域服务上的方法,在很大程度上是一个问题味道。

【讨论】:

    【解决方案2】:

    在 DDD 中,我希望这段代码在服务而不是域对象中。

    这段代码看起来并不依赖于域对象的任何状态,因此将其移动到域服务应该是微不足道的。

    【讨论】:

    • 这会使域模型贫血,不是吗?
    • 贫血是关于一个实体不允许处于无效状态,而不是包含/由所有域代码组成
    • @ConstantinGALBENU 我不记得状态与贫血域模型有任何关系。 martinfowler.com/bliki/AnemicDomainModel.html
    • @w0051977 可能是这样。我不知道您的域的其余部分是什么样的。但是,只是将不应该属于您的域的内容放在您的域中以使其不会贫血也是一种反模式
    • @w0051977 此外,由于此函数对域对象的状态没有任何作用,因此它在那里没有任何业务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    相关资源
    最近更新 更多