banq
2013-01-19 16:35
非常不错,恭贺一下,创新精神可嘉。具体细节需要详细了解和讨论。

gameboyLV
2013-01-19 16:56
2013-01-19 14:36 "@flyzb"的内容
既然是”领域服务“,那就是领域层对外的被调用接口,也就是领域的逻辑外观,但'领域服务"在本图中是被“仓储”调用而与领域对象无关。 ...

Eric Evans的《领域驱动设计》一书中68页有这么一段对领域服务的介绍:

“一些领域概念不适合被建模为对象,如果勉强地把这些重要的领域功能划分为Entity或Value Object的职责,那么不是歪曲了基于模型的对象的定义,就是人为地增加了一些无意义的对象。”

很明显领域服务并不是领域的边界,而是与领域对象处于同一层次。场景上下文才是领域的边界。同样是这本书的236页有这么一段:

“明确地定义模型所应用的上下文。根据团队的组织、软件系统的各部分的用法以及物理表现来设置模型的边界。在这些边界中严格保持模型的一致性,而不要受到边界之外问题的干扰和混淆。Bounded Context明确地限定了模型的应用范围。”

[该贴被gameboyLV于2013-01-19 16:58修改过]

flyzb
2013-01-19 22:03
DDD中的”上下文”实际上指的领域模型的一致性和完整性,而不是指功能边界,从14章的图14-3和图14-4的那个例子更可以明确地看出来。

另外,你引用的那段”领域服务“的话只是说明领域服务的逻辑与领域对象和值对象的不同。你应该好好领会一下”服务“的基本含义:

服务是指为他人做事,并使他人从中受益的一种有偿或无偿的活动。不以实物形式而以提供劳动的形式满足他人某种特殊需要。

对于”领域服务“,就是领域模型为应用层做事的。

[该贴被flyzb于2013-01-19 22:11修改过]

gameboyLV
2013-01-20 09:53
2013-01-19 22:03 "@flyzb"的内容
对于”领域服务“,就是领域模型为应用层做事的。 ...

应该是为领域层做事的才对,14-3那个图预订Context是实线,实线表示某种物理存在的事务,预订Context应该就是一套与其他Context进行通讯的API。

14-3这里例子似乎有歧义,你说RoutingService对外服务也许,对内服务也行,但是。。。另外一个例子就没有歧义了:

Jimmy Nilsson《领域驱动设计与模式实战》182页

//Order
public void Accept()
{
  if(_status != OrderStatus.NewOrder)
    throw new ApplicationException("You can only call Accept() for NewOrder orders");
    
    _status = OrderStatus.Accepted;
    _orderNumber = _orderNumberService.GetNextOrderNumber();
}
<p>

这段代码正好与Eric Evans的观点相互印证:

“一些领域概念不适合被建模为对象,如果勉强地把这些重要的领域功能划分为Entity或Value Object的职责,那么不是歪曲了基于模型的对象的定义,就是人为地增加了一些无意义的对象。”

因为OrderNumberService实际上是一个锁机制,所以不适合放在Order对象中,我就不信OrderNumberService还能为应用层做事?脱离了Order的OrderNumberService没有任何意义。

banq
2013-01-20 11:20
我认为两位对服务的看法都有道理,Eric Evans还认为服务是一个无副作用的函数,输入参数和输出结果能够确定,符合契约设计DBC:Design by Contact,因此易于测试,采取断言方式进行测试,而测试的输入参数和输出结果正好是DDD设计的两个领域模型。

楼主这个系统其实有两个服务,一个显式画出来,服务于实体模型;还有一种是隐式的,也就是API接口,实际可能就是一种服务,或者场景A出也可能是@flyzb 认为的服务。

以上只是个人见解。

clonalman
2013-01-20 12:07
有界上下文(Bounded Context)主要是领域系统边界,精确定义问题域,避免歧义等。

领域服务:定义明确的交互行为,如:上下文内聚合根之间、上下文之间、应用层与领域层之间

flyzb
2013-01-20 19:38
2013-01-20 09:53 "@gameboyLV"的内容
OrderNumberService还能为应用层做事 ...

呵呵。。咱们咬文嚼字一下。“服务”就是提供一种业务功能,而“领域服务”就是领域模型为上层提供业务功能的接口,说白了就是领域模型的逻辑外观层。领域服务是领域模型为应用层提供某种的业务功能的接口,当然属于领域层。

“上下文”是指领域模型的边界,而这种边界是由领域模型的所有领域服务共同构建出的一种“服务契约”。

另外,我希望从“命名”上不要随意违反常识,从'领域模型“的角度看,对外叫服务,对内叫功能。

[该贴被flyzb于2013-01-20 19:58修改过]

banq
2013-01-21 08:32
2013-01-20 19:38 "@flyzb"的内容
我希望从“命名”上不要随意违反常识 ...

这个我也是同意的,其实这种问题的发生我认为也是体现DDD的一个弱点之处,领域模型分 实体 值对象和服务三种,实体和值对象表达名词概念,动词概念本来可以用普通函数来表达,但是按照二选一,只能选择‘服务’来表达,而‘服务’的通俗概念不是一般意义上的函数接口,容易引起混淆。

如果在这里引入“事件”概念可能就很清晰了,实体 值对象 、服务 和事件,四个要素,这样在领域层,为实体服务的函数就不叫领域服务,而称为领域事件,实体通过发出各种事件调度技术架构为其服务,而将领域服务真正落实为开放给应用层的接口。

[该贴被banq于2013-01-21 08:34修改过]

root
2013-01-22 14:41
2013-01-21 08:32 "@banq"的内容
如果在这里引入“事件”概念可能就很清晰了,实体 值对象 、服务 和事件,四个要素,这样在领域层,为实体服务的函数就不叫领域服务,而称为领域事件,实体通过发出各种事件调度技术架构为其服务,而将领域服务真正落实为开放给应用层的接口。

...

如果这么交流的话,从领域边界提供的事件接口来看,楼主提供的仓储模型是不是只提供了仓储事件接口?事件是不是应该有更多的逻辑性以体现领域服务?

abbasky
2013-02-08 06:01
看了楼主的DDD应用,非常认同楼主的做法,但是我有些疑问,在楼主的仓储做了些什么工作呢?能否指点一二,谢谢!

ericyang
2013-03-29 12:38
事件,缓存,存储,,,我们抛开不看了,本来就是方法论,,,与业务无关。。。

话转回场景,放在应用层还是领域层?其实我倒还喜欢放到应用的,领域,只是提供领域对象和交互。。。

仓储,可不也是领域服务其一么,服务这个概念太广了,,,那么仓储有业务含义么?

转到值对象,我看到mapper,呵呵SOA的标志,,,我们看来可以把一切都叫服务,或者把服务叫做别的,,,唯一想对lz说的,就是领域层是分析域的,与数据和应用无关,如果你要DDD,那么值对象为何到了数据层。。。你可以理解它为别的东西,如果用DDD的概念,还是别叫值对象为好,免得误会。。。banq讲得可真委婉。。。呵呵

你又发明了一个数据实体,,,更加迷离了,,,到底是数据还是实体,业务的么?傻傻分不清楚啊,,,

最后,你提及把领域放到底层,这个忍不住,不同意了,分层的目的简单说是为了分清楚外,还有一个上知下而下不知上(后来又被从技术上颠覆了),而用DDD的分层也是如此,如果你搬它,很显然不一致,banq自己在很多回复里面常常很轻视最后的数据层,也是表达一个观点,领域层的东西是自给自足的,只有2个东西,对象(你叫实体和值对象也好)和交互(你叫服务也好,场景也好),然后。。。呵呵

gameboyLV
2013-03-29 23:29
我的值对象也就是Address之类的POJO对象,一个Address里可以包含国家、省份、城市等信息。

我总是觉得领域层之下应该有一些基础的、公用的数据结构,当然这些数据结构和DB无关。

就好像继承一样,一个领域如果继承于另一个领域,至少编码起来会方便很多。比如说,针对金融行业、电子商务、ERP等分别构建公共领域和业务规则,因为红冲、作废、抵扣之类的业务规则是不可能变化的。

joshuayan
2013-03-30 11:40
这里的值对象和DDD中的Value Object应该不是同一个东西,这里可以看作是DTO。

2012
2013-04-13 18:16
感觉Repo和DomainService的实现都应该在Infrastructure层.

ValueObject好像也应该是Domain Model的一种啊?

sinotao1
2013-05-13 15:57
重实践理性,能够从SSH的惯性中跳出来,就很不错了。

学术纠缠以及名词辨析,误导。概念理解体现功底,不过理解再正确,实际开发软件时,没法得心应手,又何用?

猜你喜欢