看懂这本书你要先从真正理解名字开始!
看了对于此书的短评,把这本书看成是一本“正确的废话”的人我想不在少数,10年前我看此书也是一样的感觉,10年后微服务大火,很多人又把“领域驱动设计”挂在嘴边,此时我再看此书确实感觉自己看懂了,我想这其中的奥秘其实就在“领域驱动设计”这六个字里。让我给大家仔细分解一下。
首先要解释的是“设计”这个词,这个“设计”不是我们脑子里一般泛指的设计,而是指传统软件建模中的一个阶段,传统的建模理论把软件的开发分为4个阶段,分别是“业务建模”、“需求”、“分析”和“设计”。我们来看看《UML模式和应用》中对分析和设计的定义。
分析(analysis)强调的是对问题和需求的调查研究,而不是解决方案
设计(design)强调的是满足需求的概念上的解决方案(在软件和硬件方面),而不是其实现。
有益的分析和设计可以概括为:做正确地事(分析)和正确地做事(设计)
上面三句话已经很清楚的解释了“分析”和“设计”这两个词的意思,所以“分析”阶段产生的模型就叫做“分析模型“,而“设计”阶段产生的模型也就是“设计模型“。同理,所谓的“分析模式”和“设计模式”的意思也就清楚了。
解析了“设计”的含义,我们再看“领域”的含义,所谓“领域”就是“领域模型”,那么什么是领域模型呢?我们先看“传统的”面向对象分析和设计理论中的“领域模型”的定义,来自《UML模式和应用》第三版P100、P101中的话:
领域模型(domain model)是对领域内的概念类或现实世界中对象的可视化表示。领域模型也称为概念模型、领域对象模型、分析对象模型。
在对象建模中,我们总会提到关于软件对象的职责,并且方法是纯软件概念。但是,领域模型描述的是真实世界的概念,而非软件对象的概念,对象职责在设计工作过程中非常重要,但它完全不属于领域模型。
第一段的重点在于“领域模型”是“分析”阶段产生的,所以也叫“分析对象模型”,第二段的重点在于对象的职责是属于“设计”的,不属于“分析”阶段的对象职责自然就不属于领域模型,是不是有点颠覆“三观”?
那么什么是Eric Evans心中的“领域模型”呢?
很多设计方法都提倡使用完全脱离于程序设计的分析模型, 并且通常这二者是由不同的人员开发的。之所以称其为分析模型,是因为它是对业务领域进行分析的结果,它在组织业务领域中的概念时,完全不去考虑自己在软件系统中将会起到的作用。分析模型仅仅是理解工具,人们认为把它与程序实现联系在一起无异于搅浑一池清水。 随后的程序设计与分析模型之间可能仅仅保持一种松散的对应关系。 在创建分析模型时并没有考虑程序设计的问题, 因此分析模型很有可能无法满足程序设计的需求。
纯粹的分析模型甚至在实现理解领域这一主要目的方面也捉襟见肘, 因为在程序设计和实现过程中总是会发现一些关键的知识点, 而细节问题则会出人意料地层出不穷。 前期模型可能会深入研究一些不相关的问题, 反而忽略了一些重要的方面。 而且它对于其他问题的描述也可能对应用程序没有任何帮助。最后的结果就是:编码工作一开始,纯粹的分析模型就被抛到一边,大部分的模型都需要重新设计。即便是重新设计,如果开发人员认为分析与程序开发毫不相关,那么建模过程就不会那么规范。 而如果项目经理也这么认为, 那么开发团队可能没有足够的机会与领域专家进行交流。
领域中还有一些方面适合用动作或操作来表示, 这比用对象表示更加清楚。 这些方面最好用SERVICE来表示,而不应把操作的责任强加到ENTITY或VALUE OBJECT上,尽管这样做稍微违背了面向对象的建模传统。
这三段话分别来自本书的P31和P51,我们先来看第一和第二段话,作者指出了“分析”和“设计”的脱节这个面向对象分析和设计方法论的致命问题,作者描述的这些问题我想有经验的开发人员因该都是深有体会的。第三段的话很关键也最不好懂,作者认为一个好的“领域模型”应该是“分析”和“设计”不脱节的,既能够包含“分析”阶段产生的对象(Entity、ValueObject)也能够包含表示动作或操作的“Service”,虽然这样和传统的面向对象建模相违背(为什么会违背我想你现在应该已经清楚了)
然后我们再来看Eric Evans定义的“领域模型”到底是什么有那些特征。
如果整个程序设计或者其核心部分没有与领域模型相对应,那么这个模型就是没有价值的, 软件的正确性也值得怀疑。同时,模型和设计功能之间过于复杂的对应关系也是难于理解的,在实际项目中,当设计改变时也无法维护这种关系。若分析与和设计之间产生严重分歧,那么在分析和设计活动中所获得的知识就无法彼此共享。
在MODEL-DRIVEN DESIGN中, 代码是模型的表达, 改变某段代码就改变了相应的模型。
任何参与建模的技术人员, 不管在项目中的主要职责是什么, 都必须花时间了解代码。 任何负责修改代码的人员则必须学会用代码来表达模型。
这三段话分别来自本书的P31和P40,重点说明了带有操作的“领域模型”和“设计”还有代码之间的关系,作者认为这三者因该相互紧密结合,因为“领域模型”融合“分析”和“设计”而“设计”本来就是指导编码的,所以编码和模型应该某种程度上“二合一”,来点题外话在这里Eric并没有明确说如何达到“二合一”的效果,但是要想达到“二合一”的效果,只有两条路,第一种就是“模型即是代码”,这就是为什么有些建模工具都能生成代码的原因,但是这条路正如大家看到的并不好走,所以更“现实”的方法就是“代码即是模型”,这就对代码的要求相当的高了,当然Eric也说了分析和设计的人员应该花时间了解代码,而全书后面的部分也就是各种“模式”也是在教你怎么写出“代码即是模型”。
好了,最后让我们看“驱动”二字,我先问一个问题“测试驱动开发”里,是先有测试还是先有开发?两者都不对,所谓“驱动”是两者交替相互成长的意思,“领域驱动设计”中的驱动也是如此,不是让你先有模型再有代码,写代码的过程中模型就完全不改了。也不是一定要先设计一个“完美”的模型,而是相互“驱动”,模型的改动会反应的在代码上,而代码的改动也将更好的帮助模型完善。
总结一下,所谓的“领域驱动设计”,说的是“领域模型”驱动设计,其中的领域模型和传统的面向对象分析设计的方法论不同,其中不但包含了“领域实体”还包含“领域服务”,这种模型和代码相互驱动达到了代码即是模型的效果,解决了传统OO理论中分析和设计相互脱节的问题,所以“DDD”也被称为OO的进阶”道理就在于此。
好了,希望这篇书评能够让你入门“DDD”,达到抛砖引玉的效果,谢谢耐心观看。