6

在领域驱动设计中,领域服务应该包含自然不属于实体内部的操作。

我有为每个实体创建一个服务并在其中分组一些方法(Organization实体和OrganizationService服务)的习惯。

但我越想:OrganizationService这并不意味着什么,“组织不是一种服务,它是一个东西。

所以现在我必须添加一个组织深拷贝功能,它将复制整个组织聚合,所以我想把它放在一个服务中。

我应该这样做:OrganizationService::copyOrganization(o)

或者我应该这样做:OrganizationCopyService::copyOrganization(o)

更一般地说: “服务”是包含多个操作的抽象概念,还是服务是具体操作?

编辑:鉴于第一个例子不太好,更多例子:

  • StrategyService::apply()/cancel()还是StrategyApplicationService::apply()/cancel()?(此处的“应用程序”与应用程序层无关;)
  • CarService::wash()还是CarWashingService::wash()

在所有这些示例中,最具体的服务名称似乎是最合适的。毕竟,在现实生活中,“洗车服务”是有道理的。但我最终可能会得到很多服务......

*注意:这不是关于意见的问题!这是一个关于领域驱动设计方法的精确、可回答的问题。当问“我应该”时,我总是厌倦接近投票,但有一种DDD 做事方式。*

4

2 回答 2

5

我认为如果域服务只有一种方法会很好。但我不认为这是一个规则,比如你在域服务或其他东西上不能有多个方法。如果接口只抽象一件事或一种行为,它当然很容易维护,但域服务的粒度完全取决于您的有界上下文。有时我们过于关注低耦合而忽略了高内聚。

于 2013-07-19T14:50:49.043 回答
1

这有点基于意见,我想将其添加为评论,但空间不足。

相信在这种情况下,将这些方法组合成一个具有不同构造方法的单独的组织工厂服务是有意义的。

   interface OrganizationFactory{
       Organization createOrganization();
       Organization createOrganizationCopy(Organization organization);
   }

我想这将符合信息专家模式和DRY原则——一个类拥有关于特定对象创建的所有信息,我认为没有任何理由在不同的地方重复这个逻辑。

不过,有趣的是,在 ddd 中对工厂模式的定义

将创建复杂对象和 AGGREGATES 实例的责任转移到一个单独的对象上,该对象本身在域模型中可能没有责任,但仍然是域设计的一部分。提供一个封装所有复杂程序集的接口,并且不需要客户端引用被实例化对象的具体类。

“对象”这个词在一般意义上甚至不必是一个单独的,但也可以是一个工厂方法(我的意思是类的方法和模式工厂方法) - 后来埃文斯给出了一个例子的工厂方法Brokerage Account创建Trade Order.

这本书提到了GoF工厂模式家族,我不认为有一种特殊的DDD工厂分解方式——重点是创建的对象不是半生不熟的,工厂方法应该添加尽可能少的依赖项.

更新DDD 不附加到任何特定的编程范式,而问题是关于面向对象的分解,所以我不认为 DDD 可以就每个对象的方法数量提供任何特殊建议。

有些人使用奇怪的经验法则,但我相信你可以遵循高内聚原则,将具有高度相关职责的方法放在一起。因为这是一个 DDD 问题,所以我想它是关于域服务(即不是基础设施服务)。我认为服务应该根据它们在域中的职责进行划分。

更新 2 无论如何CarService都可以做CarService::wash()//但会像乔姆斯基的生成语法那样做会很奇怪CarService::repaint()-语言中的一些陈述(句子)是有意义的,有些则没有。但是如果你的句子包含太多的主语(超过 5-7 个),即使它是有效的语言句子,它也将难以理解。CarService::diagnoseAirConditioningProblems()CarWashingServiceCarWashingService::diagnoseAirConditioningProblems()

于 2013-07-19T13:45:03.260 回答