DDD基于时间的不变量

时间:2017-06-23 15:33:01

标签: domain-driven-design

我目前正在尝试将DDD应用到现有系统中,并且对我的某个模型的一些不变性有点不好意思

在工资单系统上工作时,某些不变量在纳税年度开始时会发生变化,但系统仍需要支持当前的纳税年度。因此,例如,如果目前最低全职工作年龄为16岁但下一个纳税年度变为15岁,那我可以用DDD处理这个问题吗?

目前有一个参考数据存储库,其中包含开始日期/到期日期,可以使用当前日期读取,以确定在给定日期使用的正确记录,但据我所知,使用模型中的存储库是有点不。

我是否错过了DDD的一个显而易见的观点(例如,因为它需要一个存储库,它不是实体的不变量),还是有一种方法可以解决这个问题? (例如,当这种变化生效时,它们实际上是分开的聚合吗?)

3 个答案:

答案 0 :(得分:3)

  

目前有一个参考数据存储库,其中包含开始日期/到期日期,可以使用当前日期读取,以确定在给定日期使用的正确记录,但据我所知,使用模型中的存储库是有点不。

使用存储库的真正问题是尝试访问某些事物的“当前”状态,而不是与您正在进行的工作同时更改。

从模型访问 immutable 状态没有任何根本性的错误;在讨论中,这通常表示为 DomainService (又名:“纯函数”),它被传递给模型,而不是作为存储库。

在您的情况下,税收政策不受您的模型控制;它是来自外部世界的强加给你的东西;您的模型可以做的最好的事情就是使用最新版本的策略历史记录。

简而言之,您将模拟时间,并且您将拥有一个域服务,该服务在给定时间的情况下返回适用于该时间的税收政策的不可变表示(状态) (你知道的最好),该模型将明确记录哪些税收政策令人满意,而不仅仅是用什么密钥来查找该政策。

答案 1 :(得分:1)

如果您的聚合需要该时基信息,那么您必须提供它,无论它是否持久存在。另一方面,聚合应该具有外部服务的最小依赖性,你应该保持它们干净和纯净;所以聚合不应该做任何IO,甚至不应该是抽象的(通过使用域拥有的接口并在基础结构中实现)。

话虽如此,我会在调用aggregate命令方法之前查询repository of reference data,而我会将该信息作为值对象参数传递。因此,我不会在聚合中注入任何服务,甚至不作为命令方法的参数。

另外考虑一下:聚合关心信息存储的位置,甚至存储在某处?不,它只需要信息,而Application services最擅长到达存储库并从那里加载所需的数据。

答案 2 :(得分:0)

这是你应该工厂的原因之一。例如,根据您的情况,对EmploymentContract建模非常有意义

现在你会得到像这样的代码

public EmploymentContractFactory {

    public EmploymentContract(DateTime starttime, Person p) {
          if (starttime.Year == 2016 && p.Age < 16) {
             throw new TooYoungException();
          }
          else if (p.Age < 15) {
             throw new TooYoungException();
          }
          return new EmploymentContract(starttime, p);
    }
}

DDD的想法是你的实体/工厂足够聪明,知道它们何时有效以及可以创建什么。

这取决于你究竟是什么moddeling /你的域的复杂性。例如,如果您的域名涉及与合同相关的规则,那么您甚至可以使用&#34; ContractRule&#34;可以根据您的示范合同评估一些法律。 在这种情况下,您可以要求法律手册(聚合根)在特定日期返回所有适用的法律/规则,并使用您工厂中的那些法律/规则来确定您是否可以创建该特定合同。