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

    从我自身从事企业软件开发历程看,更注重一个“悟”字。由于个人比较喜欢看武侠和玄幻之类的小说,至今每天闲暇之余都是除了看资料就是看小说。从练武的角度看,大家总是在讨论“四色原型”、“类和职责分配、逻辑到底放在服务里还是领域对象里”之类所谓“剑招”的东西,而我更喜欢体悟一些“剑意”的东西。我不懂得很多的剑招,来到这里才知道了“DCI、四色”,开阔了眼界,非常感谢banq和大家。通过学习,我进一步印证了自己在实践中的一些想法,让我的思路更加地清晰。xmuzyu让我谈一下自己的建模技术,其实我只是有一点体会,希望大家批评指正,我非常喜欢在讨论中悟道的感觉。
    “一上来先识别类,然后就考虑怎么分配职责”的做法是一种本末倒置的僵化的静态建模。这种方式往往让人落入一种只注重“形”而忽略“意”(业务本来的面目)的怪圈。我认为建模分为2个阶段,第一个是“有机的业务建模”,第二个是“技术建模”。“业务建模”和“技术建模”的区别是:“业务建模”完全是业务语言,不含任何技术成分,比如“类、值对象和职责”的概念,在“技术建模”中才涉及那些概念。“业务建模”做好了,“技术建模”就成了自然而然的东西了。
    “有机的业务建模”的一个非常重要的特征就是“有机”,就是强调业务模型中的每一个“业务主体”都是一个生命体。这些业务主体都有“生命特征”,在一定条件下受到外界的刺激就会发生一定的行为。这些业务主体构成了整个业务模型。当然,这些业务主体的规模和层次不同:比较大的业务主体就是“领域主体”,他有明确的领域边界;而领域主体的对外界响应其实是通过内部的“业务核心主体”的协作来完成的,有的看见的见摸得着————具有业务实体的特点,有的比较抽象————控制规则和流程,当然有的“业务核心主体”可能是个多核细胞。“有机的业务建模”有一个非常重要的工作就是“检查业务模型的生命健康状况”。需要注意的是这个业务建模可能是通过不完善的用户需求建立起来的,所以我们需要构建多种场景通过不同的刺激去看这个领域主体内部的响应中是否有“异常情况”,如果有那就要开刀了。
    关于“技术建模”,我认为“对内功能和对外功能要分开”,领域对象不建议同时承担对内和对外的功能,但小项目除外。服务对外要封装和隐藏领域内部的东西,提供的是服务接口;同时服务要负责领域内部对象的行为组装。从另外一个层面看,服务是需求,领域对象模型是实现。值对象的本质就是反映业务主体的不同业务特征,可能是业务主体的临时状态(比如用户的发帖数)或者属于另一业务主体的状态值。从微观看,聚合是交互最紧密的业务对象的封装,从宏观看,聚合是一个具有明确业务边界的独立业务核心主体。所以聚合只是形式,业务模型的正确建立才是决定要素。
    另外,我谈一下“面向关系设计”的意义。其实,不要一说“面向关系设计”就是错的。因为用户的角度看,业务本来就是面向关系和过程的,这非常自然;而从设计看,业务是不同主体在相互作用。这就是为什么越靠近用户的地方面向关系和过程的设计味道越浓的原因了。
[该贴被flyzb于2010-10-22 01:23修改过]

2010年10月22日 01:18 "flyzb"的内容
第一个是“有机的业务建模”,第二个是“技术建模”。 ...

其实以前建模可以分为分析和设计两个阶段,可能就是你说的业务建模和技术建模,这样做会产生两者隔阂,业务建模注重如何反应需求,技术建模比较注重技术实现,两个关注点不一样,那么两者如何衔接就成了没人关注的,但是最重要的部分。

如果将两者合并在一起,我个人发现只是按照DDD是不够的,DDD只是一种静态建模,更多的是考虑特征特点等静态对象属性,而没有从行为职责去考虑,所以,这时需要引入对象职责,通过对象职责和协作来完成聚合以及层次以及流程,确定聚合大边界和内部协作对象小边界,分离出规则和流程。等等。

一气呵成应该是领域驱动建模的一个特点,区别于过去方法的重要特征。呵呵,仅供参考和讨论。

  &nsbp; 其实我说的2个建模过程完全就是一体两面,而把他们分开是因为我觉得各种技术名词束缚了我们对业务的真正认识。“类和职责”的叫法让我总感觉比较僵化,像是没有生命的死细胞一样,觉得这是一种西医模式。我更崇尚一种中医模式,强调建模是动态的、基于场景交互的,应该用更自然的还原业务本来面目的眼光去审视建模过程,也就是说“有机的业务建模”实际上就是“技术建模”的问题域建模,而“技术建模”只是“业务建模”的技术落地而已。这和过去的方式是完全不同的,不知道谁能明白我真正的意图。
  &nsbp; 我不知道banq是否注意到一个现象,为什么大家在DDD建模过程中做“业务模型到类和职责的映射”过程中经常会出现迷茫,比如“什么是服务、值对象?逻辑究竟是放到服务里还是领域对象中?什么是聚合?怎么确定聚合的边界”。为什么会出现这些问题,就是这些其实都是“剑招”,这些招式的出现背后其实有很深的背景——“剑意”。对于初学者来说,往往会被“剑招迷花了眼”,所以我给大家提供几句我自己的“口诀”,但仍然需讲究一个“悟”。呵呵,喜欢武侠的都应该明白我的意思。
  &nsbp; 从我自身的体会来说,过早地进入“技术建模”或者“用技术建模来替代业务建模”是有危险的,容易犯“形而上学”的毛病。另外,我把“TDD思想提前到业务建模阶段”对软件的质量非常重要,让技术建模更加容易。
[该贴被flyzb于2010-10-22 09:07修改过]

完全明白,这是一体两面,这是分合方法,也是中医西药要点,哈哈,感觉找到知己了啊

2010年10月22日 07:29 "flyzb"的内容
“类和职责”的叫法让我总感觉比较僵化,像是没有生命的死细胞一样,觉得这是一种西医模式。我更崇尚一种中医模式,强调建模是动态的、基于场景交互的,应该用更自然的还原业务本来面目的眼光去审视建模过程,也就是说“有机的业务建模”实际上就是“技术建模 ...

其实也不是的,过去的业务模型更多表现在用例图,流程图,状态图等(与类没关的,是对业务的一种描述)。用例图就是一种对边界扑捉的方法。类这些的确是静态的,所以单单类图是不全面,或者说是危险的,所以出现了时序图,数据流图等,来更好地、全面地描述业务。而你所说两面一体,的确,问题是在于中间,中间怎样过渡很重要,觉得迷惘并非没有掌握业务,而是即使掌握了业务模型也不知道怎样把这两面联系起来——也就是到底具体怎么表示。

而这些图很多,描述一件事物往往要几张图,其清晰、准确,对于新手有很好的帮助,尽管开始有点辛苦难学。当学习到一定程度的时候,这些图会很自然地出现在脑袋里,可以不再画出来(需要再画)。

对于为什么探索职责分配,一直以来的问题,这是一直在探索到底OO能表述到什么程度,当职责分配不能合理表示出来的话,就说明OO这方面到头了。其实就是OO这种世界观能把世界认识到什么一种程度而已。

2010年10月22日 10:00 "banq"的内容
也是中医西药要点 ...

完全同意,本来单是静或者单是动,都是片面的。所以动静结合很重要,捉边界等属于静,获取过程属于动。而LZ喜欢剑意,也许就是更喜欢分析边界,获取出业务流程吧。而大家讨论的“四色”“类和职责”,是建立在大家脑海里面已经有一个较为相似的业务模型的基础上,再想办法把这个业务模型具体表示出来。

但软件问题出现最多的地方就是那个过度过程,所以大家也就集中讨论了。无他,有问题就解决而已╮(╯▽╰)╭。

[该贴被SpeedVan于2010-10-22 10:37修改过]

    关于建模工具,像“用例图,流程图,状态图之类”的并不是我理想的建模工具,虽然他们确实能表达一些东西。我理想的业务建模工具应该是能从角色(组织或者人)、流程、业务能力三个维度立体地、动态地分析描述业务模型,希望可以是一个动态的3D视图和流图,并可以按不同的维度分析展开。
    呵呵,不知道那个有远见的中国公司会考虑做这样的一个工具。
[该贴被flyzb于2010-10-22 12:57修改过]

业务模型是对用户丰富的,技术模型是对程序员丰富的,必须尽量减少它们之间的理解差异,比如要是说Order,用户知道这是个订单,程序员知道这是个对象,它们都会代表各自理解上的一种高层次的抽象,而设计就需要抹平这种各自理解间的差异。

而对于根实体的理解我觉得这会根据不同的场景有所不同,在浏览产品这个场景里Product就是根,这时候还没下Order,根本不会有Order对象存在,而下订单的时候Order就是根,因为此时已经把Product扔进购物车了,不应该再单独体现某一个Product,而应该整体地去体现这个Order下的Product,还要再加上由这些Product推演出来的总价格等额外域。相反如果没有Order,而是对所有Product统计这个总价格,这就没有意义。可以看出来总价格是这个领域的一个特定的域,必须要设计进Order。这是比较简单的情况,复杂的情况就得多和用户沟通去了解我们还没有发现的那些域和行为,它们可能已经在代码里了,但是暂时还没有清晰地作为一个概念被提出来,这个概念就是要发现并加入模型的东西。