【问题标题】:Best practices with a domain object collection in DDDDDD 中域对象集合的最佳实践
【发布时间】:2020-04-20 23:40:04
【问题描述】:

我有以下课程:

public class DomainClass {
    private Integer value;
    private Integer total;
    private Integer month;
    public Double getPercent(){/*Business logic*/}
}

我想对 DomainClass 对象列表执行相同的 getPercent 操作,而无需重复代码。我有 2 个想法来处理这个问题,但我不知道它们是否好。

想法 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
}

思路2——在数据库中查询操作,填充对象,调用业务方法

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 的好文章/书籍/示例。

【问题讨论】:

    标签: java design-patterns domain-driven-design


    【解决方案1】:

    您如何管理您的实体?你使用任何类型的 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框架干扰的领域)


    提问后更新。我使用Memento 模式。

    存储

    My Domain Class 具有导出 Memento 对象中所有数据的功能。存储库需要一个域实例,请求备忘录,然后:

    • 我生成了 SQL 插入/更新(带有 Spring 事务管理的普通 SQL)
    • 您可以加载您的 JPA 实体并使用 Memento 信息进行更新(应小心,但如果您编写测试,一旦完成,它将始终有效 - 因此,测试很重要;))

    阅读

    相反,从保存的数据构建一个域实例,我这样做:

    • 在实现存储库代码的持久层中,我扩展了我的 Memento(我们称之为 PersistedMemento
    • 当我必须加载某些东西时,我会构建一个 PersistedMemento,并使用它来构建域类的实例
    • 我的域类具有允许从纪念品构建对象的功能。注意:这并不总是必要的,但在我的情况下,主构造函数有额外的检查,当对象从保存的对象重建时无法完成。无论如何,这简化了 Domain 类的重建。

    为了保护域类不被域之外的世界使用:

    • 我的存储库需要一个存在的事务,因此它们不能直接在代码中的任何地方使用
    • Memento 类具有受保护的构造函数,因此它们只能在 Domain 包或 Repository 包中使用。 PersistedMemento 也隐藏在 Repository 包中,因此无法创建实例。

    备注

    当然不是完美的解决方案。域类有 2 个函数来支持非域需求。 Memento 类也可以是子类,并且可以使用一个实例来构建域类(但是为什么呢?使用默认构造函数构建它要简单得多)。但是,除了这少量的污染,域保持非常干净,我可以真正专注于域需求,而不考虑如何管理持久性。

    【讨论】:

    • 你好卢卡。我正在使用 JPA。
    • 你能给我一个例子来说明如何从 orm pojo 到域对象的映射吗?因为现在我在 PM 做事。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 2010-11-07
    • 1970-01-01
    • 2013-08-23
    相关资源
    最近更新 更多