浅谈DDD(领域驱动设计)

背景(Why) 2003 年埃里克·埃文斯(Eric Evans)发表了《领域驱动设计》(Domain-Driven Design –Tackling Comp

领域驱动设计

背景(Why)

2003 年埃里克·埃文斯(Eric Evans)发表了《领域驱动设计》(Domain-Driven Design –Tackling Complexity in the Heart of Software)这本书,从此领域驱动设计(Domain Driven Design,简称 DDD)诞生。DDD 核心思想是通过领域驱动设计方法定义领域模型,从而确定业务和应用边界,保证业务模型与代码模型的一致性。

但 DDD 提出后在软件开发领域一直都是“雷声大,雨点小”!直到 Martin Fowler 提出微服务架构,DDD 才真正迎来了自己的时代。

大部分的Java程序员开发生涯是从学习J2EE经典的分层理论开始的(Action、Service、Dao),在这种分层理论中,我们基本没有啥机会使用那些所谓的“行为型”的设计模式,这里的核心原因,就是J2EE经典分层的开发方式是“贫血模型”。

是什么(What)

DDD,全称Domain-Driven Design, 是一种处理复杂领域的设计思想,它试图分离技术实现的复杂性,并围绕业务概念构建领域模型来控制业务的复杂性,以解决软件难以理解,难以演进的问题。它通过边界划分将复杂业务领域简单化,帮我们设计出清晰的领域和应用边界,可以很容易地实现架构演进。

DDD是面向对象的设计思想,是面向对象设计的一种升华。

实施(How)

DDD的实施分战略设计与战术设计

  • 战略建模:战略设计主要从业务视角出发,建立业务领域模型,划分领域边界,建立通用语言的限界上下文,限界上下文可以作为微服务设计的参考边界。战略建模是以一种最宏观的角度去审视整个项目对它进行拆分,来划分“界限上下文”,最终形成一个具有俯瞰视角的“上下文映射图”。
  • 战术建模:战术设计则从技术视角出发,侧重于领域模型的技术实现,完成软件开发和落地,包括:聚合根、实体、值对象、领域服务、应用服务和资源库等代码逻辑的设计和实现。

在实施过程中,我们需要明确“通用语言”,通用语言和限界上下文(Bounded Context)同时构成了DDD的两大支柱,并且它们是相辅相成的。

通用语言是以一种领域专家、设计人员、开发人员都能理解的语言作为相互交流的工具,在不断交流的过程中发现和挖出一些主要的领域概念,然后将这些概念设计成一个领域模型。由领域模型驱动软件设计,用代码来表现该领域模型。领域需求的最初细节,在功能层面通过领域专家的讨论得出。

领域模型贯穿软件分析、设计,以及开发的整个过程;领域专家、设计人员、开发人员通过领域模型进行交流,彼此共享知识与信息;因为大家面向的都是同一个模型,所以可以防止需求走样,可以让软件设计开发人员做出来的软件真正满足需求。

在这个过程中,需要业务专家的参与,他们才是最懂业务的人,他们能用他们已有的对这个领域的知识,与我们一起设计开发系统,让我们的系统更符合实际需要。典型的例子,在设计一个系统时,如果两个对象或模型有关联关系,那么这个关联关系是一对多、一对一还是多对多,有时我们并不能很好的判断出来,这个时候就需要领域专家应用他们的知识来帮助我们一起处理这部分的设计。

领域专家并不是一个职位,他可以是精通业务的任何人。可能是软件产品的设计者,甚至可能是销售员。

在设计的过程中,我们书面设计的文档不可能面面俱到,应尽量将文档减至最少,并且主要用它来补充代码和口头交流,解释我们模型中的概念,避免文档与项目脱节,设计的重要细节应该在代码中体现出来。

区别

那么DDD跟我们平时面向数据库编程,使用SpringMVC又有什么区别呢?
下面以一个例子作为说明。
在以往的项目中,我们接到了一个需求,我们会分析需求,然后设计我们的数据库表,设计DO、DAO、service、controller等,会把业务逻辑的实现写在service,假设在编码的过程中,我们发现多个service中有重复的业务逻辑,我们一般的做法有抽取方法到BaseXXX中,或者向下封装抽离一层manager等处理方式,然后大家一起调用公共的方法。
而使用DDD,会先设计出模型,同时模型是具备业务逻辑,在遇到有重复的业务逻辑时,我们考虑的是这部分的逻辑应该属于哪个模型的,它属于哪个限界上下文的,DDD中的模型不仅仅只是承载属性,他还有自己的逻辑,比如业务参数校验。

参考资料