我从 DDD 开始,并尝试将其应用到我当前的项目中,但正如您所想,我有上千个问题。
这里我提供了一个示例域,这样我就可以提出不同的问题,并作为练习,您可以在上面解释如何制作东西。
我们假设的系统必须控制公司以及每个公司的工作人员。
域。
- 公司(身份证、姓名、地址)
- 员工(身份证、姓名、姓氏、年龄)
一个人只能在一个公司工作,一个公司可以有很多员工在工作。
操作
系统必须允许向公司添加新员工。为此,它接收公司 id
和新员工的 name, surname, age
。有一些限制需要满足:
- 公司内不能有其他员工与
姓名、姓氏和年龄
相同。 - 员工可以在另一家公司工作。
问题
我脑子里乱七八糟:)
实现我正在考虑的操作:
- 服务接收所有参数。
- 服务调用
CompanyRepository->findCompanyById
以检索公司实例。 - 服务使用指定的参数创建一个新的 Employee 实例。
- 服务调用
company->addEmployee
将员工附加到公司。 - 在
company->AddEmployee
中检查新员工是否满足条件(规范)。 - 服务调用
CompanyRepository->save(company)
以保存公司和员工。
因为 company+employee
是作为集群(聚合)管理的,所以我将公司视为聚合根。
- 这是一个很好的实现吗?
- 如果我将
company+employee
视为一个聚合,就像我描述的保存集群company+employee
的方式一样,我是否也必须检索所有相关的员工,当我从存储库中检索公司实例? - 尊重规范我很容易理解如何检查,例如,如果员工姓名超过 10 个字符,但是:如果公司有数千名员工,如何检查该员工是否存在于同一公司?
- 规范可以调用存储库操作吗?如果是,并且考虑公司+员工集群是正确的事实,那么正确的地方是什么?
CustomerRepository->findEmployeeByName(idCompany, nameEmployee)
或更好地创建特定的EmployeeRepository
。
最佳答案
1
什么是好或坏只是一种意见。 DDD 不应该是教条,您可以充分利用它和您自己的补充来构建良好的软件架构。
2
不,公司可以延迟加载员工(即当运行时在检索公司后第一次访问 Employee
属性时)或者公司可以实现 Load
方法也支持分页以仅加载所需的员工。
3
您应该在存储库级别实现它(例如 ICompanyRepository.ContainsEmployee(Employee)
)并使用底层数据映射器来执行这个繁重的操作。
此外,我倾向于将规范称为存储库中的前置条件/后置条件,因为这是确保它们在所有情况下都得到满足的唯一方法。
4
我会避免它,但如果您想确保大量域规则,则需要在规范中使用它们。顺便说一句,我不会使用存储库,而是使用服务。
正确的位置取决于要求。如果您想执行检查以确保域对象以有效状态存储在存储库中,如果您想从 ICompanyRepository.Add
或 中调用规范,我发现没有问题ICompanyRepository.Update
或 ICompanyRepository.AddOrUpdate
。这里的要点是您不应该在对象存储在存储库中和检索它们时都验证对象状态。如果您的规范和代码是可靠的,如果存储库过滤了域对象并将它们存储在底层数据存储中,那么您可以确定读取操作将获得有效的域对象。
旁注:虽然您不应该基于底层数据存储(关系、NoSQL、文件系统...)为您的领域建模,但同样,您不应该将 DDD 应用为教条。如果底层数据存储提供更好的方法来定义数据约束,我会尝试使用它们而不是实现可能无论如何都需要访问数据的复杂规范。
您的解决方案应该是最佳软件架构和运行时性能的平衡。
关于c# - 了解 DDD(服务、聚合、实体、存储库和规范),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32326703/