微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

DDD - 为什么我们需要工厂?

如何解决DDD - 为什么我们需要工厂?

短版

如果没有聚合会凭空出现,为什么我们还需要在 DDD 中使用工厂(被注入到应用层中),并且这样做至少会导致业务建模错误

长版

一个流行的 DDD 示例,它是由以下聚合和实体(过度简化)组成的电子商务应用程序

enter image description here

建模为

class Customer {
  private CustomerId id;
  // related business rules and processes
}

class Order{
  private OrderId id;
  private List<OrderLine> orderLines;
  // related business rules and processes
}

class OrderLine{
  private OrderLineId id;
  private int quantity;
  private ProductId product;
  // related business rules and processes
}
class Product{} 
// etc...

众所周知,订单的创建是通过工厂完成的,通常如下:

Order order = orderFactory.createNewOrder(customer);

但是我认为这个模型不是很清楚,因为我假设最初的(编造的)要求是

客户可以下订单。

那么将订单的创建委托给 Customer 聚合并让代码更冗长不是更有意义吗?即:

Order order = customer.placeOrder(...);
// Pass the data needed for the creation of the object,or even the factory service if the creation is complex

在我看来,扩展这个视图会导致系统的参与者在大部分时间都是聚合的,并且它们将包含用例的所有调用(它具有侧面 -效果是应用层也很薄)

第二种方法是否违反了 DDD ?一个负责创建另一个聚合的聚合感觉不对,但会生成更好的代码——在我看来——更好地匹配域。

解决方法

第二种方法是否违反了 DDD

没有。 Evans 在 Domain Driven Design 一书中描述的模式应该被理解为“重复出现的有用想法”,而不是“这些模式是强制性的”。

您会在文献中找到支持以下观点的观点:当我们对聚合的创建进行建模时,我们应该使用领域语言,而不是工厂。例如:Don't Create Aggregate Roots(Udi Dahan,2009 年)。

也就是说……当 Evans 在他的书中描述 FACTORY 模式时,他是在生命周期管理的上下文中这样做的,而不是建模。换句话说,工厂是存储库和聚合的表亲,而不是域实体和值对象。

将创建复杂对象和 AGGREGATES 实例的责任转移到一个单独的对象,它本身可能在域模型中没有责任,但仍然是域设计的一部分。

换句话说,我们可能仍希望在我们的域模型中使用 Customer::placeOrder,但要让该方法将对象程序集委托给专用工厂。


当然,对象创建并不是我们使用工厂模式的唯一地方;它也可以出现在对象重构中。一个常见的 REPOSITORY 模式是从持久数据存储中获取信息,然后将该信息传递给 FACTORY 以将该信息排列成适当的形状 - 也就是构成 AGGREGATE 的对象图。


我把工厂模式理解为 information hiding 的一个例子,当我们决定改变一组固定的信息如何组装成一个聚合时,工厂会限制爆炸半径。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。