对领域驱动设计的初步认识(八)

    真有意思,讨论DDD了这么久,我们竟然连第一个D——“领域”的含义都没有达成一致。的确,Eric也没有明确地告诉我们。下面我谈谈自己的想法。
    首先我们要明白“业务”和“领域”的关系。它们是不同的,“业务”是指用户的业务范围和目标,是宏观范畴的,而且往往是复杂的、动态的和经常变化的,也就是说是“业务是客观存在”。“领域”是一种人们对业务的主观认识,“领域驱动设计”是一种业务分析方法。人类认识复杂的事物,往往采取分而治之的策略,选取一定的角度把一块业务抽取出来而形成“领域”。所以说“领域”是有边界的,而且是比较稳定的。
    在理想情况下,业务内部不同的“领域”相互独立,这些领域一起协作来完成整个业务功能。如下图所示:

理想的领域

。比如人员、权限、帖子就属于不同的领域。
    其实上面的情况只是理想情况或者单一的局部业务,而实际复杂场景会出现如下情况:

实际领域

这也就是说“领域”之间会出现交叉。因为“领域”不是业务的全部,而是业务不同角度的抽取,所以必然会出现交叉。大家注意,其中交叉部分中的“蓝色小块”就是基本核心对象是共同的。比如以“产品”为例,我们可以从研发、生产、维修等多个维度抽出多个领域模型,而大家会发现“产品结构”是他们共同的部分。
    业务变化了,准确来讲,不是原有的领域的边界变了,而是需要增加新的领域。而更复杂的情况是,新的领域和原来的领域是有交叉的。从“论坛”变为“SNS”的过程中,“论坛”本身并没有变,因为单一用户的业务需求是成长的,同时不同用户的需求也是有差别的,“论坛”不适合这个用户但还可能适合其他用户,所以说“论坛”是稳固也是没错的。但对于不断成长的用户,“jive论坛”可能不满足需求了,需要一种新的“JdonSNS”的领域。在这个新的领域里,“发帖和回帖”作为交叉部分可能仍然需要保留,但可能会赋予一种新的业务场景。
    有一句话,“业务本来就是集成的,根本就没有信息孤岛”,而那些所谓的“孤岛”都是我们这些做信息化的通过不同的业务切分弄出来的。从企业的整体业务看,各种“领域”会发生大量的交叉。而这种复杂性,我们只能从一个一个系统开始,然后再做集成,可是集成的领域建模应该怎么做一直是个困扰的难题。
    DDD的方向没问题,但目前的认识还有局限。在企业的复杂场景下,应该如何进行DDD建模一直是我思考的问题。前面的帖子里我提出一种观点——“向自然学习”,拿我们最熟悉的人体为例,人体细胞可以完成多种复杂的“场景(领域)”而靠的就是类似于“神经传导”。所以我一直建议弱化领域边界,强化“对象间的神经传导”,希望以此通过学习自然的方式来解决复杂业务场景下的DDD建模的适应性问题。



[该贴被flyzb于2010-12-14 23:26修改过]

个人理解:已经存在,却不知道(没有了解清楚,或者误解),就构成内部不稳定;原来不存在的,额外增加的,则构成边界不稳定了。内部不稳定,我们已经有不少办法解决得很好。而论坛重构成一个大型的SNS的话,就是一种边界不稳定。原来的设计是根据原来的领域,所以过大的边界改动,会引起领域变质,而重构的成本就可能很大了(干脆重新弄个)。

可能banq的想法是,扩展前后是两个领域,所以领域一直是相对稳定的;而我的想法是,从原领域扩展为新领域,这种变化就导致不稳定的领域了(这就是我认为领域一词不带有稳定的原因)。感觉这两种想法也是可行的吧。

而对于场景,个人认为是一个细化后的领域,也就是存在单一稳定的交互领域。DDD讲究一个整体领域,若果分开场景(领域)考虑的话,DCI。其实我有这样想法的,若果把以DDD中的领域集合起来时,是以消息的方式,而DCI中的场景不是也是这样吗?

领域的最主要特征是:高凝聚;而凝聚本身的含义是相对稳定。

冰块的例子非常典型,液体变成固定后,凝聚力强,水从无边无形的液体变成了有边有角的冰块,自然冰块周围就形成了边界。

数学上喜欢用“四边形”等符合来表示边,其实现实世界中是找不到真正“四边形”的,因为是人看到相对稳定的冰块四周形成了立体“四边形”,所以才认为冰块是有边的。

推导过程:高凝聚(相对稳定) ===> 边界 ====>领域。

算法也是一种领域,因为算法是依靠数学公式凝聚在一起,1+1=2就把两个1和一个2相对稳定凝聚在一起,形成一个事物,如果我们深入这个事物,就是进入其领域。

量力力学说了:电风扇如果以光速转动,就成为铁板一块,内部因子接近光速的运行,可改变其内部稳定性,改变其凝聚性,从而改变事物,这时的电风扇就不能叫电风扇了。

JiveJdon是以帖子为核心模型的论坛领域的软件,如果需求变为SNS,SNS我们都知道是以人交往为核心模型的社区领域,核心变了,这能叫拓展吗?电风扇已经变成铁块;水已经变成冰块了啊。

楼主最后一张图指出有两个领域可以共用交叉,这是客观世界中不存在的,这是人自以为聪明思考的结果。

儿科和内科两个领域都看发烧,人经过思考活动后,认为发烧有共同特征,可以合并,但是两个医生都学了治疗发烧课程后,分别到儿科和内科做医生,还是发现有其领域的不一样东西。

这里我不否认人类抽象合并的作用,但是别被这个混淆了你看世界的清澈度。世界是由各自高内聚性的事物组成。如果是动物,看不出他们之间共同点,只有人类才看到这些内聚性的共同特征,试图概况他们,最后是庸人自扰了哦,自己给自己套上烦恼绳索。

所以,什么“新的领域和原来的领域是有交叉的”都是人主观糊涂的产物,现实中领域之间边界很清楚。

大道无边,反者道之动,大道没有边,而道运动本质是反动的,那么无边的反面是有边,就是提醒大家,牢牢看清世界,世界任何事物是有边界的,不要自己迷惑自己,人迷惑人,有句话,鬼是没有,就怕人装鬼。

哈哈,谈得比较多,希望对大家有益,也别中毒啊,哈哈。


2010年12月15日 09:34 "banq"的内容
JiveJdon是以帖子为核心模型的论坛领域的软件,如果需求变为SNS,SNS我们都知道是以人交往为核心模型的社区领域 ...

为什么以帖子为核心模型是稳定的,而以需求为核心模型是不稳定的呢?

    我的观点是“不要把业务领域等同”。“业务”是客观存在,“领域”是主观认识。
    我们总是在说“领域是高内聚的”,但往往忽视“为什么”。“领域的高内聚”是因为“业务”。冰为什么会变成水,是因为“业务”变了——水分子间的作用力变了。按此也同样能解释关于上面电风扇的例子。
    关于“论坛——SNS”的问题,同样应该分清“业务和领域”的关系。我们可以回顾一下“论坛”的发展历史,它原本就是一个“交流平台”,这就是“论坛”的业务本质。而“SNS”也是一种“交流平台”。从业务本质上来讲,“论坛”和“SNS”并没有区别;当然它们的业务内涵仍然是有区别的。
    再说“儿科”和“内科”。儿科和内科只是西医对医学的一种划分方法。我不是医学的领域专家,但仍然知道西医里还有“跨学科”和“多学科融合”的说法。从传统中医的角度来讲,是不分什么“儿科”和内科的。从病人的角度来讲,只是需要一个“看病系统”而已。从文明发展角度来讲,人类的将来或者发达的外星文明会有一种统一的治病手段。所以千万不要让“领域”迷惑了眼睛,要记住是“业务决定领域,领域服务业务”。
    对于企业,让我们反思一下,那些信息孤岛是怎么弄出来的,就是我们从片面的角度分割业务弄出了一大堆孤岛式的系统。比如要做一个“企业个人任务管理系统”,突然发现不能新做一个,因为在原有的大量的业务系统里面已经有了各种各样的个人任务,我们必须把这些任务集中到一起才能形成一个企业完整的“企业个人任务管理系统”。这就是上面我说的领域融合交叉的问题。
    呵呵,banq别激动,我们继续讨论。

2010年12月15日 11:16 "flyzb"的内容
我的观点是“不要把业务和领域等同”。“业务”是客观存在,“领域”是主观认识 ...

我发现我们的差异还是边界划分不一样导致的,你把领域划定在主观认识,我把领域划定在客观存在的“业务”。

我比较更有兴趣谈你说的“业务”,“业务”有其客观性,专业性和相对稳定性,以及高内聚性。比如算法也算一个“业务”吧,牛顿能用数学把万有引力推导出来,说明他发现了万有引力这个“业务”的高内聚性。

为什么我排斥主观认识的东西?还是那句话,屁股决定脑袋。而且认识是不断发展的深入的,导致“领域”不断变化,甚至否定自己,这就无从谈起了。

我以前举过一个例子,张三在单位是经理,在家里是父亲,经过人主观的归类,认为“单位”和“家”中的张三是两个领域共用,其实错了,通常所谓抽象继承思路,你如果用类继承实现肯定不对,实际上,你没有必要将两个系统中张三合并,进入“单位”和“家”都以他们数据ID进入扮演相应角色即可,管他交叉不交叉。如果李四拿了张三的ID进入其“单位”和“家”也可以,这不是业务重点。

这里涉及到可复用的组件中间件其实也是一厢情愿,你今天抽取这个共性,明天会发现这个共性抽取(需要封装)反而阻碍了灵活性。Web服务把共性HTTP封装起来,认为所有Web服务的交叉模型就是HTTP,既然都有HTTP,那么我基于HTTP上的XML定义就可以通用。这就越搞越复杂了,REST架构说这太复杂,HTTP直接暴露,无需XML就可以通用。

原来类是将方法封装起来,因为任何类都有方法行为,这不是共性吗?结果,函数式语言绕过类封装,直接面向方法函数。

从以上都说明,对“业务”的任何主观认识都是有时间边界的,都是有限的,压下葫芦飘起瓢。真理都是相对的,边界的,真理都是人对“业务”的主观认识。


[该贴被banq于2010-12-15 14:49修改过]

如果banq能把领域模型为什么比需求更稳定说一说,将更有说服力
[该贴被xuzhh于2010-12-15 15:46修改过]
[该贴被xuzhh于2010-12-15 15:51修改过]

flyzb认为“领域是主观认识,业务才是客观存在”。DDD就是对“客观的业务”进行“主观的领域建模”。(我可以理解和赞同这个观点)。从这个观点来看,我们要关心在“业务”与“领域”之间建立一致的映射。

flyzb似乎也将场景与领域的概念等同起来,对于这个我有点不同的看法。

1)场景是从领域中分离出来的,场景(context)是由一些领域模型(data model)之间相互作用(interaction)而形成,这些领域模型在场景中因为相互作用而扮演了某种角色(role),离开场景就一般不再需要扮演了。

2)场景之间可能存在依赖关系,可以通过“事件机制”之间传导。但个人认为场景已经不小了,场景之间最好先独立开来(OCP),再考虑如何将各个场景连接起来。这样可以控制复杂度,降低一些不必要的复杂性。

3)每个场景之中的多个领域模型(扮演某种角色)之间的交互也可以通过“事件机制”进行传导。

4)从领域剥离出场景后剩下的部分,就是各个场景共有的部分,可称之为领域模型。

拿上面“水与冰”为例,具体化上面的看法。

水与冰随着气温的变化,形态发生了变化,但两者可以分解为水分子的集合。外部形态的变化是因为内部水分子相互作用发生了变化。这里水分子可以理解为共同的“领域模型”,不同的相互作用可以理解为不同“业务场景”。

领域模型之间不同的“相互作用”构成的场景之间可能存在关联,但建模时最好先把各个场景独立开来,对场景之间的转换或演变可进行独立思考。如 “冰”加热变成“水”,加热就是一种事件,可以通过“事件机制”在“水”与“冰”两个场景之间进行传导。

最后再打个比喻,可能会更浅显一些。

领域模型是演员,一个业务场景是一部电影的某个片断。每个电影片段中会出现一些扮演各自角色的演员,演员所扮演的角色们进行着一些活动。而根据剧情的发展,各个电影片断之间会呈现一些关联,可以通过“事件机制”传导。

这里回到flyzb提出的另一个问题jdon从bbs向sns的转换。这个已经不是增加新的业务场景那么简单了,这实际是在拍一部新的电影(一种全新的业务)。那么可以拍吗?可以,只要这些演员(领域模型),还可以演这出新戏,就没问题。葛优这个演员(领域模型)不就可以演绎多部电影《赵氏孤儿》、《让子弹飞》、《非诚勿扰2》吗?(多种业务,而不仅仅是一种业务的多个业务场景)。

但如果这些演员演不好或不适合这部新戏,也就是原有jdon bbs中的演员们(领域模型)不适合演绎sns这部新戏(新的一种业务),那么还要让他们演吗?也许重新找一批演员更合适(建立新的领域模型)?你说呢?

  进一步说,“领域”知识是我们对客观世界(“业务”)的认识积累。“领域”越接近客观,那么领域模型就生命力越强,能够适应“业务变化”。当然这种“业务变化”更多的情况是我们对业务认识的视角、深度和范围发生变化。在这里,“实体对象”具有重要意义。因为我们常说的某一“领域”是某一些实体对象在某一方面运动特质的体现。以企业为例,“产品”就是核心业务对象,产品设计、产品生产、产品维修、产品销售、产品质量等等都是这个核心业务对象的不同侧面(“领域”)。我现在面临的问题时,如何针对这种复杂场景进行建模。如果这些领域的边界过于“刚性”,那么我就很难把它们有机地融合在一起。当然“领域边界”是必须存在的,但应该隐于无形。我们可以通过控制领域对象的相互作用来保障领域边界的存在。其实这是完全符合客观存在的,因为“领域”本来就是我们从客观世界观测得到的一些领域对象相互作用的某一方面的特质。

2010年12月15日 19:15 "jdon007"的内容
flyzb认为“领域是主观认识,业务才是客观存在”。DDD就是对“客观的业务”进行“主观的领域建模” ...

这个我不能认同,可能理解角度不一样,我认为DDD中领域就是楼主所说的“业务”,DDD强调寻找领域中旋律,与之发生共振(基本是原话),我们可以替代后为:DDD强调寻找"业务"中旋律,与之发生共振。

只有客观的东西才有自己旋律,人做的主观的软件才要与之共振。

而领域模型(Domain Model)中的模型Model才是楼主所说的人的主观认识(也就是楼主说的'领域')。

看来,我们对Domain Model有基本认识误差,比较难以交流了,呵呵。

还有,大家讨论的场景其实在DDD中也有,就是中文版本的上下文,限定的上下文,拗口,就是有边界有前提的场景。该章节中谈到了如何共用一套模型,就是楼主画的两个领域交叉图,持续集成等等很麻烦,我个人认为先尊重客观各自为政好,否则维护一套统一模型成本高。
[该贴被banq于2010-12-15 20:22修改过]



而领域模型(Domain Model)中的模型Model才是楼主所说的人的主观认识

嗯,这个观点我可以接受,不过我还是强调“领域”是“业务”的某一切面而不是业务的全部。这是人类认识客观世界的规律。按照banq的说法,从领域到模型是有损失的,从模型到技术设计还会在损失。而我现在遇到的难题是如何进行多领域建模时多个模型的关系。
[该贴被flyzb于2010-12-15 22:24修改过]

补充一下我的看法。

flyzb将“领域”与“场景”这两个概念等同起来的说法,可能不妥。领域这个词的含义多广呀,音乐领域、软件领域、商业领域,而且我们说某某人是音乐领域的奇才是,不就是说这个人是音乐界的奇才。“领域”就是“界”呀。

flyzb所谓的“领域”的交叉,觉得还是用“场景”的交叉来表达比较好一点。两个“场景”的交叉部分就是两个“场景”都参与的一些“领域模型”(不是领域),只是在两个不同的“场景”中这些模型扮演的“角色”并不同。

此外,“交叉”这个说法,在这里的意义有点不够明朗。“场景”也是“有界”的,符合OCP原则的,否者扩展与修改某个场景就无从谈起。所以与其说“场景”之间有交叉,不如说有些“领域模型”参与了多个“场景”。

flyzb所说的业务集成,在我看来,如果两种业务的“领域模型”是相同的,可以做,相当于一些原有的“领域模型”相互作用形成一个新的“场景”;如果两种业务的“领域模型”相互独立,也可以做,相当于新建一些“领域模型”相互作用形成一个新的“场景”(当然也可以使用一些原有的“领域模型”)。

还是用电影做一下比喻,如果两种业务的“领域模型”相同,业务集成就相当于还是使用这些“老演员”(原班人马)演“新戏”;如果两种业务的领域“模型”相互独立,相当于启用了一些“新演员”演“新戏”(当然也可以使用一些“老演员”)。

“新戏”是在一部电影增加的“戏份”,电影的主题可以通过新增的戏份进行升华,但无论增加多少新戏,都不应改变电影的本质(领域)。
这放在“业务集成”上,就是要为“同时使用多种业务的共同用户”提供一个便利的平台,这些用户的需求决定了领域的边界。

To jdon007
  领域和场景是不同的。领域是宏观层面的,场景是微观层面的,虽然它们有相似点。
  如果可以用一个领域模型来描述“企业”的所有业务,我当然希望是这样的,但问题是有谁可以做到,那就是共产主义了,完全可以凭此打败微软、IBM之类的公司成为老大了。

领域“有界无边”,说起来拗口,简单说领域虽然有界,但其边界时可以扩展的,领域虽然有界,但其边界是无形的。

比如说音乐界不断发展,但界还是存在,虽然界也是一种主观认识的划分。因为音乐界不能独立于人类的所有活动。

我觉得DDD给我最大的启发其实只有一点,我们应该先使用领域语言来思考领域问题,而不是用技术语言来思考问题。此外,领域的边界是由用户的需求来决定的,用户的需求是动态可扩展,所以领域的边界也如此。所谓领域语言,就是从有所需的用户心中提炼出来的。用户需求相对于领域来说是一个“客观存在”。

领域虽然是对客观存在主观上一种划分,但不是一成不变的。一个领域模型是根据业务(用户需求)对领域的一种素描,业务不同,素描也就不同。这里有点不容易注意到的地方是,我们在说一个领域模型时,有时候是代表一个集合,有时候是代表一个或一部分个体,不注意到这点,可能会引起一些不知不觉的误会,这个要根据上下文进行意会了。

一个“现有”的领域模型(实体集)不可能包含“未有”的业务(也就不会包含所有业务了),但这个实体集可以根据业务进行拓展,也就是对现有的领域模型进行拓展,只要还是在这个领域内。当然,领域的场景很多时,因为人类思维的局限性,必然对领域进行再次划分,一些场景组成一个“大场景”,可称为“子领域”。你所说的具体某种业务,我认为就是一个“子领域”,一些具体业务场景的集合。

总结一些概念:
用户需求 = 业务
用户需求的边界=领域的边界 (简称为“领域”)
用户需求的素描 = 领域模型(包括从领域模型分离出来的场景,即模型参与的活动)
某种业务 => 某个领域模型集合
几种业务的集成 => 几个领域模型集合的合并(可能存在交集)
某种业务的划分 => 某个领域模型集合的划分

[该贴被jdon007于2010-12-16 10:45修改过]

既然这个帖子是咬文嚼字,名可名非常名,大道就在名字中,我再来咬一咬。

“领域”汉字中的域就是边界的意思,“领”大概应是在这个边界中领导,主要的,这和英文领域Domain,也就是Do main,主要的,做主要的。

领域模型实际就是在这个边界中找出主要的模型。

而我们通常谈的业务,也有主要的意思,问你在公司做什么?做业务,这里面有两层含义,做销售,或者管理工作;如果你做的是财务或食堂等次要服务性工作,你好意思说你是做公司业务吗?而且,在公司业务这条线的薪酬要超过其他次要服务性工作。

所以,业务领域合起来还是在强调在主要边界中找主要的。主要又主要,主要上加主要。当然要找到主要,前提是你先划定边界。

打个比喻:擒贼先擒王,你首先得知道王的边界,画个包围圈吧,因为主要再主要,就从面细化到线,再细化到“点”上了,只有封闭边界才能把点的大概位置圈出来。

所以,从领域到模型肯定是有损失的,因为我们是抓大放小,纲举目张;而从模型到技术设计还会在损失,则不认同,因为这就是DDD的最大贡献,模型出来,Java的代码就出来,何来损失;而过去通常意义上的需求的分析设计就是损之又损,最后变成代码都不是人样了。

需求这个字眼很有意思,是需要求你的意思;软件人员要让业务需求来求你;而业务领域建模,是我们和领域专家主动从业务领域中划边界,大领域中画出子领域,子领域中再找主要的王,也就是模型;这个过程是我们去发现客观现实,而不是客观现实来求你,大道无语,它怎么会来求你呢,所以,需求一词显示人的自以为聪明,其实非常无知。

谈了这么多类似哲学的方法,应该对楼主有帮助,你现在的难题"是如何进行多领域建模时多个模型的关系。" 既然模型是划定边界中主要的,它就不会跨出边界和其他边界里的主要模型有亲密关系。如果两个国家的领导人有亲密关系,这能成两个国家吗?所以,你在给自己下了一个逻辑上矛盾的伪命题,呵呵,我说得直了啊,抱歉。

从其他角度考虑不是一件容易的事情,需要时间,可以安静一段再想想。我感觉楼主你有丰富的业务经验,好像在寻找什么,我也很感兴趣一道帮你解决问题,首先,我们把那个共同目标先找出来,而在找出共同目标之前,我们先统一一下对话平台,基本用词语义统一,这样,就能更好交流。

关于场景,又叫上下文,应该是如楼上说的一个个活动场次,它首先是活动的,而领域模型是相对静止的,我们通过模型和场景将领域中的静和动分离出来,在软件运行时,再组合运行,这就是设计。