三 领域驱动设计

目录领域驱动设计-运用领域模型-绑定模型和实现MODEL-DRIVEN DESIGN建模范式和工具支持为什么模型对用户至关重要HANDS-ON MODELER

领域驱动设计-运用领域模型-绑定模型和实现

聪明的项目组成员花费了几个月的时间进行仔细的研究并且开发出了详尽的领域模型(类图)。然而对类图研究不能让我深入地了解该应用程序的代码和设计,这让我备感困扰。当开发人员开始实现应用程序时,他们很快就发现,尽管分析人员说得头头是道,他们依然无法将这种错综复杂的关系转换成可存储、可检索的且具有事务完整性的单元。

由于模型是“正确的”,这是经过技术分析人员和业务专家大量协作才得到的结果,因此开发人员得出这样的结论:无法把基于概念的对象作为设计的基础。于是他们开始进行专门针对程序开发的设计。他们的设计确实用了一些原有模型中类和属性的名称进行数据存储,但这种设计并不是建立在任何已有模型的基础上的。

这个项目虽然建立了领域模型,但是如果模型不能直接帮助开发可运行的软件,那么这种纸上谈兵的模型又有什么意义呢?

领域驱动设计要求模型不仅能够指导早期的分析工作,还应该成为设计的基础。这种设计方法对于代码的编写有着重要的意义。不太明显的一点就是:领域驱动设计要求一种不同的建模方法

个人理解:建了模型可以更快了解所需知识,可又不能转化成程序代码实现,到底要怎样?我也搞不懂了,反正觉得好复杂

MODEL-DRIVEN DESIGN

严格按照基础模型来编写代码,能够使代码更好地表达设计含义,并且使模型与实际的系统相契合。

那些压根儿就没有领域模型的项目,仅仅通过编写代码来实现一个又一个的功能,它们无法利用前两章所讨论的知识消化和沟通所带来的好处。如果涉及复杂的领域就会使项目举步维艰。

另一方面,许多复杂项目确实在尝试使用某种形式的领域模型,但是并没有把代码的编写与模型紧密联系起来。这些项目所设计的模型,在项目初期还可能用来做一些探索工作,但是随着项目的进展,这些模型与项目渐行渐远,甚至还会起误导作用。所有在模型上花费的精力都无法保证程序设计的正确性,因为模型和设计是不同的。

模型和程序设计之间的联系可能在很多情况下被破坏,但是二者的这种分离往往是有意而为之的。很多设计方法都提倡使用完全脱离于程序设计的分析模型,并且通常这二者是由不同的人员开发的。之所以称其为分析模型,是因为它是对业务领域进行分析的结果,它在组织业务领域中的概念时,完全不去考虑自己在软件系统中将会起到的作用。分析模型仅仅是理解工具,人们认为把它与程序实现联系在一起无异于搅浑一池清水。随后的程序设计与分析模型之间可能仅仅保持一种松散的对应关系。在创建分析模型时并没有考虑程序设计的问题,因此分析模型很有可能无法满足程序设计的需求。

这种分析中会有一些知识消化的过程,但是在编码开始后,如果开发人员不得不重新对设计进行抽象,那么大部分的领域知识就会被丢弃。如此一来,就不能保证在新的程序设计中还能保留或者重现分析人员所获得的并且嵌入在模型中的领域知识。到了这一步,要维护程序设计和松散连接的模型之间的对应关系就很不合算了。

个人理解:业务画的模型图,在技术人员看来,需要进行翻译成程序模型图(流程图),这样,两个模型之间肯定会有不同的部分,会有一些领域知识舍弃,那这两个模型对应关系需要来维护,无疑增加了复杂度。

无论是什么原因,软件的设计如果缺乏概念,那么软件充其量不过是一种机械化的产品——只实现有用的功能却无法解释操作的原因。

如果整个程序设计或者其核心部分没有与领域模型相对应,那么这个模型就是没有价值的,软件的正确性也值得怀疑。同时,模型和设计功能之间过于复杂的对应关系也是难于理解的,在实际项目中,当设计改变时也无法维护这种关系。若分析与和设计之间产生严重分歧,那么在分析和设计活动中所获得的知识就无法彼此共享。

个人理解:上面的我也没看懂,反正就是说业务涉及的模型和技术流程图是有很大不同,原因是思考方式不同,这样很难对应维护。

MODEL-DRIVEN DESIGN(模型驱动设计)不再将分析模型和程序设计分离开,而是寻求一种能够满足这两方面需求的单一模型。不考虑纯粹的技术问题,程序设计中的每个对象都反映了模型中所描述的相应概念。这就要求我们以更高的标准来选择模型,因为它必须同时满足两种完全不同的目标。

有很多方法可以对领域进行抽象,也有很多种设计可以解决应用程序的问题。因此,绑定模型和程序设计是切实可行的。但是这种绑定不能够因为技术考虑而削弱分析的功能,我们也不能接受那些只反映了领域概念却舍弃了软件设计原则的拙劣设计。模型和设计的绑定需要的是在分析和程序设计阶段都能发挥良好作用的模型。如果模型对于程序的实现来说显得不太实用时,我们必须重新设计它。而如果模型无法忠实地描述领域的关键概念,也必须重新设计它。这样,建模和程序设计就结合为一个统一的迭代开发过程。

将领域模型和程序设计紧密联系在一起绝对是必要的,这也使得在众多可选模型中选择最适用的模型时,又多了一条选择标准。它要求我们认真思考,并且通常会经过多次反复修改和重新构建的过程,但是通过这样的过程可以得到与设计关联的模型。

要想创建出能够抓住主要问题并且帮助程序设计的单一模型并没有说的那么容易。我们不可能随手抓个模型就把它转化成可使用的设计。只有经过精心设计的模型才能促成切实可行的实现。

个人理解:建模好难,不管怎么说,将业务和技术思维抽象成通用模型,本身就是学习成本,不是人人都能达到的。真的怀疑做模型的时间是不是还不如直接开发来的干脆,少搞这些虚头巴脑的东西。老外对模型是真爱!

建模范式和工具支持

为了使MODEL-DRIVEN DESIGN发挥作用,一定要在可控范围内严格保证模型与设计之间的一致性。要实现这种严格的一致性,必须要运用由软件工具支持的建模范式,它可以在程序中直接创建模型中的对应概念。

面向对象编程之所以功能强大,是因为它基于建模范式,并且为模型构造提供了实现方式。从程序员的角度来看,对象真实存在于内存中,它们与其他对象相互联系,它们被组织成类,并且通过消息传递来完成相应的行为。许多开发人员只是得益于对象的技术能力——用其组织程序代码,只有用代码表达模型概念时,对象设计的真正突破之处才彰显出来。Java和许多其他工具都允许创建直接反映概念对象模型的对象和关系。

没看懂,直接忽略。设计不是一蹴而就的。我们需要反复研究领域知识,不断重构模型,才能将领域中重要的概念提炼成简单而清晰的模型。

为什么模型对用户至关重要

从理论上讲,也许你可以向用户展示任何一种系统视图,而不管底层如何实现。但实际上,系统上下层结构的不匹配轻则导致误解,重则产生bug。

如果程序设计基于一个能够反映出用户和领域专家所关心的基本问题的模型,那么与其他设计方式相比,这种设计可以将其主旨更明确地展示给用户。让用户了解模型,将使他们有更多机会挖掘软件的潜能,也能使软件的行为合乎情理、前后一致。

个人理解:这里说了很多理论,其实就是一点,如果模型做的不好,直接导致做出来的东西会复杂难用,用户难以接受。

HANDS-ON MODELER

人们总是把软件开发比喻成制造业。这个比喻的一个推论是:经验丰富的工程师做设计工作,而技能水平较低的劳动力负责组装产品。这种做法使许多项目陷入困境,原因很简单——软件开发就是设计。虽然开发团队中的每个成员都有自己的职责,但是将分析、建模、设计和编程工作过度分离会对MODEL-DRIVEN DESIGN产生不良影响。我曾经在一个项目中负责协调不同的应用程序开发团队,帮助开发可以驱动程序设计的领域模型。但是管理层认为建模人员就应该只负责建模工作,编写代码就是在浪费这种技能,于是他们不准我编写代码或者与程序员讨论细节问题。

个人理解:现在软件工程就是分了很多流程:调研-需求评审-概要设计-详细设计-系统开发-测试-上线-维护,难道每个人负责自己的模块不好吗?很多对日外包就是拿日本人设计好的伪代码和流程图,直接用程序翻译出来。难道自己的理解有问题了?

开始项目进展的还算顺利。我和领域专家以及各团队的开发负责人共同工作,消化领域知识并提炼出了一个不错的核心模型。但是该模型却从来没有派上用场,原因有两个。

其一,模型的一些意图在其传递过程中丢失了。模型的整体效果受细节的影响很大这些细节问题并不是总能在UML图或者一般讨论中遇到的。如果我能撸起袖子,直接与开发人员共同工作,提供一些参考代码和近距离的技术支持,那么他们也许能够理解模型中的抽象概念并据此进行开发。

第二个原因是模型与程序实现及技术互相影响,而我无法直接获得这种反馈。例如,程序实现过程中发现模型的某部分在我们的技术平台上的工作效率极低,但是经过几个月的时间,我才一点一点获得了关于这个问题的全部信息。其实只需较少的改动就能解决这个问题,但是几个月过去了,改不改已经不重要了。因为开发人员已经自行编写出了可以运行的软件——完全脱离了模型的设计,在那些还在使用模型的地方,也仅仅是把它当作纯粹的数据结构。开发人员不分好坏地把模型全盘否定,但是他们又有什么办法呢?他们再也不愿意冒险任由呆在象牙塔里的架构师摆布了。

与其他项目一样,这个项目的初始环境倾向于不让建模人员参与太多的程序实现。对于该项目所使用的大部分技术,我都有着大量的实践经验。在做建模工作之前,我甚至曾经在同类项目中领导过一个小的开发团队,所以我对项目开发过程和编程环境非常熟悉。但是如果不让建模人员参与程序实现,我就是有这些经历也无法有效地工作。

如果编写代码的人员认为自己没必要对模型负责,或者不知道如何让模型为应用程序服务,那么这个模型就和程序没有任何关联。如果开发人员没有意识到改变代码就意味着改变模型,那么他们对程序的重构不但不会增强模型的作用,反而还会削弱它的效果。同样,如果建模人员不参与到程序实现的过程中,那么对程序实现的约束就没有切身的感受,即使有,也会很快忘记。MODEL-DRIVEN DESIGN的两个基本要素(即模型要支持有效的实现并抽象出关键的领域知识)已经失去了一个,最终模型将变得不再实用。最后一点,如果分工阻断了设计人员与开发人员之间的协作,使他们无法转达实现MODEL-DRIVEN DESIGN的种种细节,那么经验丰富的设计人员则不能将自己的知识和技术传递给开发人员。

HANDS-ON MODELER(亲身实践的建模者)并不意味着团队成员不能有自己的专业角色。包括极限编程在内的每一种敏捷过程都会给团队成员分配角色,其他非正式的专业角色也会自然而然地产生。但是如果把MODEL-DRIVEN DESIGN中密切相关的建模和实现这两个过程分离开,则会产生问题。

整体设计的有效性有几个非常敏感的影响因素——那就是细粒度的设计和实现决策的质量和一致性。在MODEL-DRIVEN DESIGN中,代码是模型的表达,改变某段代码就改变了相应的模型。程序员就是建模人员,无论他们是否喜欢。所以在开始项目时,应该让程序员完成出色的建模工作。

任何参与建模的技术人员,不管在项目中的主要职责是什么,都必须花时间了解代码。任何负责修改代码的人员则必须学会用代码来表达模型。每一个开发人员都必须不同程度地参与模型讨论并且与领域专家保持联系。参与不同工作的人都必须有意识地通过UBIQUITOUS LANGUAGE与接触代码的人及时交换关于模型的想法。

将建模和编程过程完全分离是行不通的,然而大型项目依然需要技术负责人来协调高层次的设计和建模,并帮助做出最困难或最关键的决策。

个人理解:每个人都要会一点建模,就算是开发人员,也要参与其中,就算是业务人员,也要稍微懂些代码。每个人要有自己的专业能力,同时也要全面发展,了解整个流程的工作内容。一句话:可以不做,但是不能不会。突然有一个需要程序员去做需求或者详细设计,也要能扛下来这个任务。目的不是让一个人做多个任务,担任软件开发流程中的多个职责,而是懂得一些后大家沟通建模没有障碍,会相互理解。