领域驱动设计之旅

1. 背景

软件复杂性这一问题,几乎是“软件危机”的同义词。上世纪60年代因为计算机硬件的发展,使开发功能更强大的软件成为可能,软件的规模越来越大,越来越复杂。因为开发软件的方法论、技术手段较为落后,软件的开发不甚顺利,存在诸多问题,当时学术界定义了“软件危机”一词,用以描述这一现象。随后的几十年间,涌现了各种各样的应对软件危机的方法,这些方法有的从软件的生命周期角度优化软件的开发过程,有的考虑如何设计良好的软件的体系结构,有的在编程实践中探索编码效率提升的技术。

从软件的生命周期角度看,出现了瀑布模型、螺旋模型、快速原型模型、敏捷开发、极限编程等软件开发模型;从软件体系结构的角度看,出现了人们创造了各种风格的软件体系结构模型、总结形成了各种软件开发、设计方法、并且软件体系结构文档化也得到了极大的发展。软件体系结构模型有分层模型、管道模型、客户端/服务器模型、总线模型等;软件开发、设计方法有基于架构的软件开发、基于构件的软件开发、服务导向架构、特定领域系统架构等;从编程实践角度看,各种高级语言和面向对象编程、面向切片编程、设计模式等编程技术也先后被发明。

软件生命周期管理、软件体系结构和文档化、程序语言与编程技术这三方面技术发展的同时,软件工程专业也逐渐发展成体系。

2. 领域驱动设计定义

领域是指一定的范围,在这个范围内领域内,有特定的用户,从事特定的工作,产生特定的价值。在用户层面,体现为软件所服务的特定用户,在功能层面,体现为软件为特定用户所解决特定的业务需求。我们可以通过亲自从事该领域的工作,或者从该领域的从业者身上取经获取领域知识。

工程开工前通常需要对所要建造的物品进行分析、描绘,得到一份指导施工的文件,得到这份文件的过程就是设计,软件工程也是一样。在软件定义阶段,涉及产品的设计,在软件开发阶段,涉及技术方案的设计。

eric evans于2003年出版了《领域驱动设计——软件核心复杂性应对之道》一书,提出了领域驱动设计这个方法,用来处理软件的复杂性问题。正如书名所提,能够有效地处理软件的复杂性是其特点,此外,领域驱动设计本身是一套软件开发设计方法,其中体现了与其他软件工程方法相同的原则:充分了解需求分析、设计高内聚、低耦合、优美的软件结构。运用领域驱动设计,能够在项目中很好地落地这些原则

并且在落地上述原则的过程中,领域驱动设计创造了其独特的概念体系,这套概念体系包括以下要素:战略建模、战术建模、问题空间、解决方案空间、核心域、支撑域、通用域、领域、子域、界限上下文、通用语言、上下文映射图、领域实体、聚合根、领域服务、领域事件、仓库、工厂、规格、值对象等。

3. 软件复杂性

软件的复杂性取决于业务的复杂性,业务越复杂,支撑业务的软件产品的复杂性越大。软件的复杂性主要体现在模块数量、模块之间的依赖两方面。软件的复杂性越高,则软件系统的模块数量越多,相互的依赖越复杂

3.1 软件设计的复杂性与软件代码的复杂性

编码活动,将软件设计转化为软件程序,在此过程中,设计复杂性转变为代码复杂性。狭义上的软件设计虽然能够指导软件开发,但是由于设计无法100%的完备,明确定义软件系统的每一行代码如何实现,只有软件系统的代码本身能够绝对准确地体现自己的设计。狭义的设计与软件系统本身体现的设计之间的差异,在极具创造性的编码活动中被消除,编码完成,则软件系统本身体现的设计才完成,我们把软件系统本身体现的设计称为广义的设计

3.2 软件复杂性与软件缺陷

随着软件复杂性的增加,软件的缺陷数量也会随之增长,因此软件的复杂性控制非常重要,使用恰当的软件复杂性控制手段,控制支撑复杂业务的软件系统的复杂性,能够有效地减少软件缺陷的数量。

3.3 软件复杂性与易维护性

简单的软件比复杂的软件易维护,因此,控制软件的复杂性,可以保证软件的易维护性,包括代码更容易阅读和理解,更容易修改扩展。

4. 软件复杂性管理

复杂性管理工作的目标是,通过一定的方法确定软件系统的层级模块,并且明确模块间的依赖关系。需要注意的是,模块的数量多少与否,依赖关系数量的多少,虽然可以用于参考衡量软件的复杂性,但仅仅是参考,最重要的是模块与模块之间的关系形成一定的风格,具有美感,使之易于理解、易于管理。

管理复杂性,可以分为代码复杂性管理和设计复杂性管理。在广义上看,管理设计的复杂性,就是管理代码的复杂性。在狭义上看,设计复杂性得到管理和控制,不一定说明代码复杂性得到管理和控制。我们最终希望看到的是一行一行代码构成的软件系统的代码复杂性得到控制,复杂性的控制绝不仅仅停留在设计图纸上。无论设计图纸多么清晰简洁明了,若是编码走样,软件的复杂性依然的得不到良好的控制。

5. 领域驱动设计与软件复杂性管理

领域驱动设计强调编码与设计的一致性。在编码向设计的映射过程,不至于引入过多的额外的复杂性。

对领域知识的获取以及对领域模型的精心维护是编码与设计的一致性得意保证的前提条件,若是领域知识获取不足,模型抽象错误、与现实差距过大,若是再加上缺少良好的架构保障,那么编码途中、以及将来对软件进行扩展时,极有可能会困难重重。

领域驱动设计强调领域知识的获取。软件设计师、软件开发人员与领域专家交流,获取领域知识,基于领域知识进行软件的设计与开发。了解领域,首先需要了解领域的构成,了解领域内绝对的、明确、清晰的术语,这是最基础、最重要的,领域驱动设计中把这套术称作“通用语言”,强调使用“通用语言”进行交流,促进需求分析。

领域驱动设计强调领域模型的维护。在设计阶段尽可能地构造所能构造的最优的模型,并且在迭代过程中不断打磨精化,体现对需求分析不轻易满足、不轻易止步、不肤浅的、势必全面而深入地了解的需求。

6. 领域驱动设计的实施

实现任何一项系统的非功能性需求,大体可以通过以下几个通用的方面开展工作:建模、度量、评估、设计和管理。领域驱动设计注重设计与管理,它通过定义在需求分析阶段、软件设计阶段、软件编码阶段所需要实施的活动与要点实现设计与管理。

6.1 实施步骤

6.1.1 领域分析

在需求分析阶段,通过讨论,梳理概念,逐步明确一个又一个的概念,逐渐将由发散性的、灵活的、充满模糊内涵的词汇构成的沟通语言,转变为收敛的、固定的、明确的“通用语言”。使用这套统通用的语言,描述一个系统的方方面面,高层的、细化的。

6.1.2 领域驱动设计风格的技术方案设计

领域驱动设计风格在架构上,表现为分层架构,自底向上依次是:基础设施层、领域层、应用层、视图层。基础设施层定义系统依赖的各类基础设施;领域层实现领域分析所得出的领域模型,领域模型由领域实体、领域聚合、领域事件、领域服务、领域规范、仓库等领域资源对象组合而成;应用层依赖于领域层,负责编排业务逻辑,包含各种横切逻辑;视图层调用应用层执行业务逻辑,并将执行结果转化为指定的格式呈现给用户。

6.1.3 编码

在编码阶段,希望软件开发人员忠于领域驱动设计风格的技术方案进行编码活动,实现设计方案向代码高度准确的映射。

6.2 实施效果

领域驱动设计指导的软件开发过程,领域模型始终作为设计与编码的核心,编码遵照精心维护的领域模型开展,忠诚体现领域知识,精心维护的领域模型与现实高度一致,将使系统易于扩展和维护。通过分层架构、以及领域层内对领域资源对象的分类,形成一套严格的、有章法和美感的编码风格,模块数量不一定少,但是划分适宜,依赖清晰,达到了控制软件复杂度的效果,同样保证了软件的易维护性。

6.3 主要的阻碍

如果想要比较好地实施领域驱动设计,切实服务于软件开发过程,提高软件系统的开发效率、质量,有赖于对其的深度理解。

从系统论的角度来说,如果我们希望深入、全面、完全地了解、掌握领域驱动设计,可以从其“通用语言”入手,逐个了解其中诸如领域实体、聚合根、领域服务、仓库等概念,并且在实际项目中寻找合适的地方尝试应用,应用以后发现需求分析确实更深入了、设计、编码的软件体系结构确实越来越有美感了,思考、编码的过程越来越快乐了,我们就走在正确的道路上,我们就正在逐渐掌握领域驱动设计。

在各行各业、大大小小的企业中,囿于企业的规模、发展程度、员工的经验,项目开发团队在实施领域驱动设计的过程中,不可避免地会遇到缺少领域专家这一现实的问题,我们不妨参考产品角色缺失这一问题的处理策略处理缺少领域专家这一问题。可以从外部获取资源,为团队配备领域专家,如果没有条件,则践行人人都是领域专家的方法,由参与项目的各个角色,需求分析师、系统分析师、系统架构师、开发工程师等共同分担这一角色的职责,不妨把握以下核心原则:1、需求分析阶段不轻易满足、不轻易止步、不肤浅的、势必全面而深入地了解的需求;2、软件设计阶段尽可能地构造所能构造的最优的模型,并且迭代过程中精化、打磨;3、编码阶段忠于设计。

你可能感兴趣的:(领域驱动设计之旅)