了解DDD(服务,聚合,实体,存储库和规范)

时间:2015-09-01 08:14:40

标签: c# domain-driven-design

我从DDD开始并试图申请我当前的项目,但你可以假设我有数千个问题。

在这里,我提供了一个示例域名,以便我可以提出不同的问题并作为练习,您可以向我解释如何制作内容。

我们的假设系统必须控制公司以及每个公司的工作人员。

域。

  • 公司(身份证,姓名,地址)
  • 员工(身份证,姓名,年龄)

一个人只能在公司工作,公司可以有很多员工在工作。

运营

系统必须允许向公司添加新员工。为此,它会收到公司id和新员工的name, surname, age。有一些限制要满足:

  • 公司中不能有另一名员工name, surname and age
  • 员工可以在另一家公司工作。

问题

我心里一团糟:)

实现我正在考虑的操作:

  • 服务接收所有参数。
  • 服务电话CompanyRepository->findCompanyById以检索公司实例。
  • Service使用指定的参数创建一个新的Employee实例。
  • 服务电话company->addEmployee将员工附加到公司。
  • company->AddEmployee检查中,新员工满足条件(规格)。
  • 服务电话CompanyRepository->save(company)除了员工外,还要保留公司。

因为company+employee作为集群(聚合)进行管理,所以我认为公司是集合根。

  1. 这是一个很好的实施吗?
  2. 如果我认为company+employee是一个聚合,就像我描述的保存集群company+employe一样,当我从存储库中检索公司实例时,我是否也必须检索所有相关的员工?
  3. 尊重规范我可以很容易地理解如何检查,例如,员工姓名是否超过10个字符,但是:如果公司有数千名员工,如何检查员工是否存在于同一家公司?
  4. 规范可以调用存储库操作吗?如果是的话,考虑到公司+员工集群是正确的,那么什么是正确的地方? CustomerRepository->findEmployeeByName(idCompany, nameEmployee)或更好地创建特定的EmployeeRepository

1 个答案:

答案 0 :(得分:3)

1

什么是只是一种意见。 DDD不应该是一个教条,你可以充分利用它和你自己的补充来构建良好的软件架构。

2

不,公司可以懒惰地加载员工(即,在检索到公司后第一次运行时访问Employee属性)或公司可以实现Load方法,该方法也支持分页只加载所需的员工。

3

您应该在存储库级别(例如ICompanyRepository.ContainsEmployee(Employee))实现此功能,并使用底层数据映射器执行此繁重的操作。

此外,我倾向于将规范称为存储库中的前/后条件,因为它是确保在所有情况下都能满足它们的唯一方法。

4

我会避免它,但如果你想确保很多域规则,你需要在规范中使用它们。顺便说一句,我不会使用存储库,但我会改用服务。

正确的地方取决于要求。如果要执行检查以确保域对象以有效状态存储在存储库中,如果要从ICompanyRepository.AddICompanyRepository.Update或{中调用规范,我发现没有问题{1}}。这里的要点是,当它们存储在存储库中以及何时被检索时,您不应该验证对象状态。如果您的规范和代码是可靠的,如果存储库已经过滤了域对象并且已将它们存储在基础数据存储中,那么您可以确定读取操作将获得有效的域对象。

旁注:虽然你不应该根据底层数据存储(关系,NoSQL,文件系统......)对域进行建模,但是你不应该这样做像教条一样应用DDD。如果底层数据存储提供了更好的方法来定义数据约束,我会尝试使用它们而不是实现可能需要访问数据的复杂规范。

您的解决方案应该是最佳软件架构和运行时性能之间的平衡。