轻松学DDD之一:模型驱动设计
轻松学DDD之一:模型驱动设计
我是2012年开始接触到DDD(领域驱动设计)的, 后续陆陆续续研读过几遍Eric的大作《领域驱动设计:软件核心复杂性应对之道》,也使用DDD重构过一个项目。总的感受是DDD的一些概念比较晦涩难懂,很难掌握,因此想写个系列短文,希望能用通俗易懂的语言帮助大家更轻松更深入地理解DDD。文章很多都是我个人体会和理解,难免有错误,希望大家能及时指正,共同提高。
本文是系列短文第一篇,介绍DDD的起始概念模型驱动设计。
在常宁等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站制作、网站设计 网站设计制作按需求定制网站,公司网站建设,企业网站建设,品牌网站设计,成都营销网站建设,成都外贸网站制作,常宁网站建设费用合理。
1. 软件开发方法回顾
软件开发可以看做是一个把用户需求转换为可正确运行的程序的过程,其中最关键部分是把用户需求转换成代码。我们要学习的DDD实际上就是一种软件开发方法,它相比之前的软件开发方法,能更好地应对软件的核心复杂度。为了能更好的理解它,我们先回顾下之前的软件开发方法及其存在问题。
在上世纪60年代,由于需求简单,软件开发以作坊式开发为主。但是随着硬件的飞速发展,软件复杂度也迅速激增,终于在70年引发了软件危机。为了应对危机,业界借鉴成熟生产制造管理方法,发展出以“过程为中心”的瀑布式开发方法。
1.1 瀑布式开发
瀑布式开发把整个软件开发过程划分为需求分析、方案设计、编码、测试等阶段,希望以这种类似工业流水线的作业分工方式来控制软件开发的风险和成本。
- 需求分析:通过需求分析我们需要明确用户想要的功能,会怎么来使用这些功能,通过这些功能能得到什么价值;消除用户需求中的二义性、相互矛盾的地方;细化各种正常/异常功能场景,验收准则,性能、可靠性等非功能性约束。
- 设计:在设计阶段需要根据需求分析结果决定软件的总体实现方案。在系统设计阶段会确定子系统划分,进行开发、运行平台、数据库等关键技术选型;在方案设计阶段则会明确模块划分,模块内部架构,协作流程,关键算法等。
- 编码:根据设计完成代码编写。
- 测试:测试软件是否满足用户需求。
上图展示了应用瀑布式开发方法的软件开发流程,我们可以看到这种方法可以通过专业分工和流水作业来分解复杂度和提升效率,这在在一定程序上缓解了软件危机。但是与工业生产不同,软件需求和开发过程存在很多不确定因素,因此这种方法在应用过程中也发现了很多问题。 - 每个需求的各阶段由不同的人依次完成,阶段之间用文档传递知识,各阶段之间缺乏沟通和反馈,错误和理解偏差不能及时纠正,往往影响软件的正确交付。
- 每个需求输出各自的分析、设计文档,没有整合。随着软件规模增长,分析和设计会丧失对软件整体性的把握,进而影响分析和设计的全面性和正确性。
- 由于缺乏反馈,分析、设计和代码之间的差异会越来越大,耗费大量人力编写的分析设计文档会逐步失去价值,协作会越来越困难,软件也越来越难以按期正确交付。
为了解决瀑布式开发的开发效率低下、响应需求速度慢的问题,轻量级的,更能适应变化的敏捷软件开发方法被普遍认可并迅速流行起来,极限编程就是其中的一种。
2 极限编程
XP主要由13个实践构成,是一种近螺旋式的开发方法。它将复杂的开发过程分解为一个个相对比较简单的小周期;通过积极的交流、反馈以及其它一系列的方法,开发人员和客户可以非常清楚开发进度、变化、待解决的问题和潜在的困难等,并根据实际情况及时地调整开发过程。
为了与瀑布式开发做对比,我们把XP简单理解为下图:
通过上图我们可以看到,XP没有划分分析、设计、编码和测试等阶段,需求可以在一个周期为1~2周的迭代中快速交付。XP之所以能做到快速交付,有如下几个原因:
- 客户、业务专家、开发、测试大家坐在一起完成需求开发,面对面沟通取代了文档,节省了文档编写、维护的工作量。
- 通过简单设计、TDD、ATDD、CI等工程实践保证分析、设计、编码、测试之间更快速的反馈和充分的并行化,有效缩短了开发周期。
- 通过不断重构代码来保证代码更加简洁,能更好地反应软件的核心复杂度。
- 通过结对、代码集体所有权、系统隐喻、编码规范、完整团队促进了技能和知识的共享。
XP非常反对做预先设计,需求分析与设计会被拆分到用户故事乃至TDD的小步迭代中去做,在每个小迭代中代码只会根据当前需求简单实现;当在后续迭代过程中发现代码难以满足新需求时,需要通过重构来增加代码对新需求的适应性,以便能够快速实现新需求。这种做法固然能带来很多好处,但是也存在一些缺陷:
- 如果软件复杂度高,需求之间有着复杂的关联,开发在没有很理解业务逻辑就贸然开始写代码,会带来非常大的重构成本,甚至于需要重写。
- 只有代码承载业务共识,维护业务共识的成本高,最终导致难以维持业务共识。大家交流的共识除了存在于头脑中外,只存在于代码中,这对于代码的业务表达力和专家/客户的代码理解能力都提出了非常高的要求,最终可能导致大家对于业务的理解的差异会越来越大。
3. 模型驱动设计
为了弥补XP在应对软件核心复杂度的缺陷,eric在2003年提出了一种新的方法,他认为我们需要引入领域模型并围绕它来做需求分析和软件设计,这就是模型驱动开发。这一论述有以下几个要点:
- 模型是统一的,它反映了领域的核心复杂度,而不是领域内每个需求面面俱到的细节。一些不涉及软件核心价值且不影响全局的细节可以在放在迭代中考虑,相关知识沉淀在代码中即可,就像XP做的那样;但是涉及软件核心价值,或者影响全局的业务逻辑需要纳入领域模型中做统一细致的分析,并在软件生命周期内不断地演进精炼。
- 模型是交流和协作的中枢。客户、业务专家、开发、测试等各种角色一起参与构建模型的,大家基于共同的模型来做交流和协作。
- 模型与代码是绑定的。代码修改能方便地同步到模型,模型修改也能方便地同步代码。这要求模型不只体现问题域的知识和约束,也能体现实现域的知识和约束;涉及业务逻辑的代码需要不断提炼,剥离技术实现细节,以便能很好地表达模型。
最后总结下,模型驱动设计通过对软件核心复杂度的统一建模,解决了瀑布式开发在需求分析、软件设计上的沟通、反馈和知识整合上的缺陷,也解决了XP极简主义设计存在的缺陷。
文本重点叙述了我们为什么需要领域模型,领域模型构建需要注意的几个基本原则,但是具体要怎么来构建领域模型呢?请看下一篇《轻松学DD之二:如何高效消化知识》。
当前标题:轻松学DDD之一:模型驱动设计
分享路径:http://scyanting.com/article/pgopij.html