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