0

我们最近决定在我的团队中为我们的新项目采用 DDD,因为它有很多明显的好处(来自 Active-Record 模式学校),还有一些事情还不清楚。

假设我有一个实体交易,它依赖于以下实体(每个实体又依赖于其他如此多的实体): 1. 客户 2. 账户 3. 货币

当我使用工厂实例化事务实体以传递给域服务以获取一些花哨的业务规则时,我是否会进行如此多的查询来设置所有这些依赖实例?

如果我的工厂中有跳过此类依赖项的重载,那么在某些情况下这些重载将为空,并且何时可以访问这些属性以及何时不能访问这些属性将变得太复杂而无法区分。使用 Active-Record 模式,我只使用延迟加载并让它们仅按需加载。DDD有什么想法吗?

编辑:

在我的场景中,“事务”似乎是聚合根的最佳候选者。我在我的应用程序服务“InitiateTransaction”中定义了一个方法(也有一个“FinalizeTransaction”,因为它涉及到 PayPal 的重定向),并将携带 AccountId、CurrencyId、LanguageId 和各种其他外键以及 Transaction 所需的 DTO 作为参数属性。

当调用我的域服务(交易处理器和欺诈规则评估器)时,我需要指定加载所有依赖项的“交易”聚合(“Transaction.Customer”、“Transaction.Currency”等)。

因此,如果我是正确的,所需的步骤是: 1. 调用一些存储库来检索客户、货币等。 2. 使用上面指定的依赖项调用 TransactionFactory 以获取事务对象 3. 使用完全加载的事务对象调用域服务以进行业务发生的规则

正确的?此外,我担心的是第 1 步和第 2 步。

如果“客户”、“货币”和其他实体/值对象“交易”依赖,则依次具有其他依赖关系。我是否也尝试设置这些?因为在我看来,如果我这样做了,我的应用程序服务中的代码将非常臃肿,并且不能很好地重用以放置在单独的方法中。但是,如果我不这样做,只是按照您的建议从带有“GetById(id)”的存储库中检索那些,我的代码最终可能会出现错误,因为我需要返回一个“用户”的属性“Transaction.Customer.CreatedByUser”例如,它将为空,因为存储库仅加载平面实例。

编辑:

我最终使用 GetById(id) 仅加载我知道它们在我的服务中需要的依赖项。由于平面加载而意外访问空实例并不是一件很有趣的事情,但我有我的单元测试来保护我免于将其投入生产!

4

1 回答 1

1

我高度怀疑Currency是一个实体,但是对事物进行建模很重要,例如它们如何定义和被真实域使用。忘记工厂或其他实现细节,如数据库,你需要确保你已经正确定义了这些概念。

完成此操作后,您也已经确定了聚合根。顺便说一句,实体应该封装相关的业务规则。使用服务来实现用例,即管理域对象与其他部分(如存储库)之间的交互。

您应该在存储库中保留与 db 和 CRUD 相关的所有内容,并让存储库仅与聚合根一起使用。此外,出于查询目的,您应该使用 CQRS,以便所有查询都在读取模型上完成。出于域的目的,Get(id) 就足够了 99%,并且该方法返回一个聚合根。

请注意,DDD 非常棘手,最困难的部分是正确建模 Domain,如果模型错误,所有流行语都是无用的。

于 2014-04-26T16:53:39.040 回答