繁体   English   中英

从Google数据存储区加载DDD实体的设计模式是什么?

[英]What are design patterns to load DDD entity from Google Datastore?

我正在学习DDD,并尝试使用Google数据存储区实施存储库。

我发现从数据存储区重新创建DDD实体非常棘手。 我已经阅读了一些将DDD实体映射到数据存储区实体的框架,但是我想首先学习底层API。

我虽然可以使用设置器来设置实体的状态,但这在DDD中通常被认为是反模式。

一种替代方法是使用构建器模式,其中将构建器实例传递给实体的构造器。 但是,这给实体带来了超出其职责范围的功能(恢复实体状态)。

有什么好的模式可以解决问题?

(答案主要来自我在OP中的评论,但我认为最好在答案中加以阐述)

二传手很好。 问题是域实体的“用户”不应该通过那些获取/设置者进行访问。 域实体应具有有意义的业务接口,以便基于此接口构建应用程序逻辑。 设置器应该是实现级别的东西,用于创建实现对象(在存储库等中)

我相信最好用一个例子来说明。


这是认为是反模式的二传手的错误方法

class OrderApplicationService {
  public void cancelOrder(String orderId) {
    Order order = orderRepository.getOrder(orderId);
    order.setOrderStatus(CANCELLED);
    order.setOpenQuantity(0);
    orderRepository.update(order);
  }
}

但是,更正确的方法是:

// Interface for Order

interface Order {
  void cancel();

  // no setters!!!
}

class OrderImpl extends Order {
  @Override
  void cancel() {
    this.status = CANCELLED;
    this.openQuantity = 0;
  }

  void setId(String orderId) { ... }
  // some other setters
}

class OrderApplicationService {
  public void cancelOrder(String orderId) {
    Order order = orderRepository.getOrder(orderId);
    order.cancel();
    orderRepository.update(order);
  }
}

存储库是通过impl创建和访问的,因此它可以访问getter / setter。 但是,您的应用程序逻辑仅面向接口,并且没有使用设置器/获取器(这是反模式)来实现逻辑。


以上方法是通过正确声明接口来强制执行的。 但是,如果您认为可以依靠自我声誉,则可以通过直接在Impl中使用与业务逻辑相关的方法以及设置器/获取器来简化故事,而无需使用界面。 并且在实现过程中,您应该知道在业务逻辑实现过程中仅应使用实体的业务方法(而不是getter / setter)。


而且,将二传手视为反DDD不是一个简单的经验法则。 在某些情况下,例如,将自由文本注释存储在实体中,将设置器提供为业务逻辑方法并不一定是错误的决定。

埃里克·埃文斯(Eric Evans)的整本书的第6章专门讨论您所描述的问题。

首先,DDD中的Factory不必是独立的服务-

埃文斯DDD,第2页。 139:

有多种设计工厂的方法。 在Gamma等人中彻底处理了几种特殊用途的创建模式-“工厂方法”,“抽象工厂”和“建造者”。 等人,1995年。<...>这里的重点不是深入研究工厂设计,而是显示工厂作为领域设计的重要组成部分的位置。

Evans FACTORY中的每种创建方法都会强制创建的对象的所有不变量,但是,对象重构是一种特殊情况

埃文斯DDD,第2页。 145:

重构对象的工厂将以不同的方式处理对不变式的违反。 在创建新对象的过程中,如果不满足不变量,则FACTORY应该简单地避免,但是在重构时可能需要更灵活的响应。

这很重要,因为它使我们创建了单独的工厂以进行创建和重构。 (在第155页的图表中, TradeRepository使用专用的SQL TradeOrderFactory ,而不是通用的通用TradeOrderFactory

因此,您需要实现一种单独的重构逻辑,并且有几种方法可以做到(您可以在《企业应用程序体系结构的马丁·J·福勒模式》 (第169页中找到完整的理论)中有一个副标题“将数据映射到域字段” ,但是没有所描述的所有方法看起来都很合适(例如,使对象字段在Java中为package-private似乎太麻烦了),所以我只希望使用以下两个选项之一

  • 您可以创建一个单独的FACTORY并将其记录下来,以便开发人员仅应将其用于持久性或测试。
  • 您可以使用反射来设置私有字段值,例如Hibernate那样

关于带有setters和getters的贫血领域模型, 即将发行的Vaughn Vernon著作对这种方法提出了很多批评,因此我敢说这 DDD中的反模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM