java - DDD 中域对象集合的最佳实践
问题描述
我有以下课程:
public class DomainClass {
private Integer value;
private Integer total;
private Integer month;
public Double getPercent(){/*Business logic*/}
}
我想对没有重复代码的 DomainClass 对象列表执行相同的 getPercent 操作。我有两个想法来处理这个问题,但我不知道它们是否好。
想法 1 - 创建一个服务并迭代列表:
public class DomainObjectService{
....
public Double getPercent(List<DomainClass> list){
double value, total;
for(DomainClass d : list){
value += d.getValue();
total += d.getTotal();
}
// do percent operation
}
思路二——在数据库中查询操作,填充对象,调用业务方法
public class DomainObjectService{
....
public Double getPercent(){
double value, total;
.... query data with sql and set the above variables
// do percent operation
return new DomainBusiness(value, total).getPercentage();
}
我正在阅读,在 DDD 中,实体应该处理自己的逻辑,但在这种收集操作的情况下,应该如何处理它?
好吧,如果我的 DDD 基础知识是错误的。我想知道Java中DDD的好文章/书籍/示例。
解决方案
您如何管理您的实体?你使用任何类型的 ORM 吗?
我对这种操作的解决方案是构建一个管理对象集合的类。因此,例如:
public class DomainClasses{
private final List<DomainClass> domainClasses;
....
public Double getPercent(){
// manage the percent operation ...
// ... on all the members the way ...
// ... your business is expected ...
// ... to do it on the collection
return something;
}
// class initialization
}
通过这种方式,您可以重用每个类的 getPercent 代码,还可以实现它的特定版本以供集合使用。此外,该集合可以访问 DomainClass 的包私有 getter(如果有)来进行计算。通过这种方式,您只公开构建域对象所需的功能。
注意:如果您在没有任何 ORM 的情况下管理持久性,则此解决方案是可行的。或者,如果您想使用它,则需要额外的工作才能正确配置容器类。
一些链接:
https://www.mehdi-khalili.com/orm-anti-patterns-part-4-persistence-domain-model(我使用与 PM 分离的 DM)
https://softwareengineering.stackexchange.com/questions/371344/why-not-use-an-orm-with-ddd(我正在做的是将域对象转换为将被持久化的 DTO - 这有点为集合编写额外的代码,但一旦经过测试,它就可以正常工作,而且你得到的是一个不受 ORM 框架干扰的域)
提问后更新。我使用备忘录模式。
存储
My Domain Class 具有导出 Memento 对象中所有数据的功能。存储库需要一个域实例,请求 Memento,然后:
- 我生成 SQL 插入/更新(来自 Spring 的带有事务管理的普通 SQL)
- 您可以加载您的 JPA 实体并使用 Memento 信息进行更新(应小心,但如果您编写测试,一旦完成它将始终有效 - 因此,测试很重要;))
阅读
相反,从保存的数据构建域实例,我这样做:
- 在实现存储库代码的持久层中,我扩展了我的 Memento(我们称之为PersistedMemento)
- 当我必须加载某些东西时,我构建了一个PersistedMemento并使用它来构建域类的实例
- 我的域类具有允许从纪念品构建对象的功能。注意:这并不总是必要的,但在我的情况下,主构造函数有额外的检查,当对象从保存的对象重建时无法完成。无论如何,这简化了 Domain 类的重建。
为了保护域类不被域之外的世界使用:
- 我的存储库需要一个现有的事务,因此它们不能直接在代码中的任何地方使用
- Memento 类具有受保护的构造函数,因此它们只能在 Domain 包或 Repository 包中使用。PersistedMemento也隐藏在Repository 包中,因此无法创建任何实例。
笔记
当然不是完美的解决方案。域类有 2 个函数来支持非域需求。Memento 类也可以是子类,并且可以使用一个实例来构建域类(但是为什么呢?使用默认构造函数构建它要简单得多)。但是,除了这少量的污染,域保持非常干净,我可以真正专注于域需求,而不考虑如何管理持久性。
推荐阅读
- matlab - 如何在MATLAB中的图形的ylabel上写一个方程?
- php - 在进行注册之前检查用户是否登录
- asp.net-core-2.1 - 如何在 .net core 2 项目中启用 cors 在 apache2 服务器中运行
- sql - 列的 Netezza 时间戳数据类型
- qt - 处理 QMessageBox 实例的正确方法是什么?
- html - CSS 导航链接在悬停时不会改变
- azure - Azure - 将附加到 Service Fabric VM 规模集的负载均衡器从一个更改为另一个,或者将现有的从公共更改为私有
- python - 你如何测试立即运行的代码?
- php - 在 WooCommerce 购物车项目中显示特定格式的产品属性
- c++ - 复制向量本身