我已经被Eric Evans的书所说服,并且正在将DDD集成到我的框架中。所有基本元素(服务,存储库,有界上下文等)都已实现,现在我正在寻找有关如何正确集成它的反馈。
我有一些业务逻辑,必须在创建或修改实体时执行。这个例子非常简单。大多数业务逻辑将变得更加复杂。
此业务逻辑可以分为以下几个步骤:
我的第一次尝试是将所有这些放在聚合根上,但我觉得这不会起作用。我在集成这个逻辑时遇到以下问题:
对于上述问题的任何帮助都将受到高度赞赏,并提供其他反馈意见。
答案 0 :(得分:6)
您描述的算法应该保留在聚合根中,否则您最终得到anemic domain model,除了将字段传播到另一个聚合根,我将在后面描述我认为您应该做的事情。
就TDD而言,聚合根上的“包”访问方法(例如“calculate()”)应该协调整个操作,服务或存储库对象通常会调用该操作。这就是测试应该与设置实例变量的不同组合一起运行。聚合根应该公开其实例变量,子集合,并且每个子项应该通过getter公开它的实例变量 - 这允许测试验证它们的状态。在所有情况下,如果你需要隐藏信息使这些getter包或私有访问,并使用你的单元测试框架将它们公开用于测试。
对于您的测试环境,请考虑mocking存储库对象(您正在使用dependency injection吗?)来返回硬编码值。考虑使用dbunit之类的东西来处理已知状态的数据库。
就逻辑变化而言,创建与修改有关,您指的是如何持久存在或者是否需要考虑实际算法?如果是前者,我会让存储库负责,如果后者我会做两个单独的方法(例如“calculateCreate()”&“calculateUpdate()”),其中calculate()将适当地委托。
此外,还有一个并发问题需要考虑,因为它听起来好像计算值依赖于可变字段。因此要么需要小心锁定,要么只能由客户端一次使用的聚合根。这也适用于跨聚合传播字段 - 我可能会将存储库用于此目的 - 但您需要仔细考虑这应该或不应该影响使用存储库对象的其他客户端。