本文尝试指出领域驱动设计的四个不足。目前我们采用的领域驱动设计,其主线是Eric Evans提出的所谓领域驱动设计元模型。该元模型因其高度的概括性与松散性,故而能够随着时间推移历久不衰。但也正因为此,使得它在指导领域驱动设计落地时,缺乏规范性和实践意义,更多需要凭借经验才能成功实施领域驱动设计。
领域驱动设计肇始于Eric Evans出版于2004年的著作《Domain-Driven Design-Tackling Complexity in the Heart of Software》:
领域驱动设计作为一个软件系统综合分析和设计的面向对象建模过程,如今已经发展为一种针对大型复杂系统的领域建模过程体系。
它改变了传统软件开发工程师针对数据库建模的方法,而是面向领域,将要解决的业务概念和业务规则转换为软件系统中的类型以及类型的属性与行为,通过合理运用面向对象的封装、继承、多态等设计要素,降低或隐藏整个系统的业务复杂性,并使得系统具有更好的扩展性,应对纷繁多变的现实业务问题。
领域驱动设计元模型
领域驱动设计的立意是建立以领域为驱动力的过程体系,在这一核心驱动力的设计思想指导下,并没有死板僵化的构建过程来约束你。Eric Evans定义了一套领域驱动设计元模型,该模型由诸多松散的模式构成:
至今,这套元模型在领域驱动设计的实施中仍然发挥着重要作用。
显然,领域驱动设计是开放的。从领域驱动设计诞生至今,整个社区并未放弃发展其体系的努力,也诞生了许多重要的补充模式,例如以“领域事件(Domain Event)”为核心的诸多模式:事件溯源(Event Sourcing)、CQRS模式等。
随着微服务和中台战略的兴起,领域驱动设计元模型中的限界上下文(Bounded Context)、核心领域(Core Domain)又得到了空前绝后的重视。
然而,在团队运用和实践领域驱动设计过程中,整套体系始终存在力有未逮之处。毕竟,领域驱动设计是否能够取得成功,不只限于一两位精通领域驱动设计的专家就可以力挽狂澜。团队成员的能力、管理规范等诸多因素都会影响整个实践的过程。
据我个人的经验和对实施领域驱动设计的反思,认为现行的领域驱动设计存在以下四个不足。
不足之一
Eric Evans构建的领域驱动设计元模型并不足以支撑软件的构建过程。这些模式之间虽然彼此影响,运用得当就能形成设计合力;然而模式的粒度并不均衡,运用上极为随意,缺乏一个统一的过程指导。
虽然领域驱动设计划分了战略设计阶段与战术设计阶段,但这两个阶段的划分仅仅是对构成元模型的模式进行类别上的划分,例如将限界上下文、上下文映射等模式划分到战略设计阶段,将聚合、实体、值对象等模式划分到战术设计阶段。
缺乏一个统一的过程去规范这两个阶段需要执行的活动、交付的工件以及阶段里程碑。Eric Evans没有清晰定义这两个阶段该如何衔接,它们之间执行的工作流到底是怎样的。
除了极少数精英团队,大多数团队都需要一个清晰的软件构建过程,否则将茫然不知所措。领域驱动设计没能形成这样的统一过程,就使得其缺乏可操作性,团队在运用领域驱动设计时,更多取决于设计者的行业知识与设计经验,使得领域驱动设计在项目上的成功存在较大的偶然性。
因此,领域驱动设计缺乏一个规范的过程指导,是其不足之一。
不足之二
领域驱动设计倡导以“领域”为核心驱动力,无论是对领域知识的抽象还是精炼,本质上都是针对问题域的业务需求。
可是,业务需求是如何获得的呢?获得的业务需求应该具备什么样的特征?业务需求的粒度和层次是怎么定义的?该如何规范和约定团队各个角色对需求分析的参与?以及在不同的阶段,业务需求的表现形式与验证标准分别是什么?
种种问题,领域驱动设计都没有给出答案,甚至根本就未提及!虽然说这些问题都可以纳入到需求管理体系,故而可以认为它们游离于领域驱动设计之外;可是,不同层次的业务需求贯穿于领域驱动设计过程中的每个环节,识别限界上下文需要对业务需求和业务流程有着清晰的理解,建立领域模型需要的领域知识和概念也都来自于用户故事层次的业务需求。毫无疑问,需求管理体系会直接影响领域驱动设计的质量。
因此,领域驱动设计没有匹配的需求管理体系,是其不足之二。
不足之三
领域驱动设计战略阶段的核心模式是限界上下文,指导架构设计的主要模式是分层架构,前者决定了业务架构,后者决定了系统架构。
领域驱动设计的核心诉求是让业务架构和系统架构形成绑定关系,以面对需求变化时,使得系统架构能够适应业务架构的调整,满足架构的演进性。领域驱动设计虽然给出了这些模式的特征,却失之与简单松散,不足以支撑复杂软件项目的架构需求。
因此,领域驱动设计缺乏面向领域的架构体系,是其不足之三。
不足之四
领域驱动设计以模型驱动设计为主线,却没有给出明确的领域建模方法。
无论是否采用敏捷的迭代建模过程,建模分为分析、设计与实现这三个不同的活动确是客观存在的事实。虽然我们必须努力保证领域模型的一致性,但这三个活动存在明显的存续关系,每个活动的目标、参与角色与建模知识存在本质差异,这也是客观存在的事实。
基于此,我们需要分别为领域分析建模、领域设计建模和领域实现建模提供对应的方法指导,减轻每个建模活动的知识负担,明确每个建模活动获得的领域模型的验证标准,避免领域建模的随意性。
因此,领域驱动设计没有领域建模固化流程的支撑,是其不足之四。
精简和丰富知识体系
针对领域驱动设计的四个不足,我对领域驱动设计的知识体系进行了精简与丰富。
精简,意味着做减法,就是要剔除领域驱动设计元模型中不太重要的模式,凸显核心模式的重要性,并对领域驱动设计过程进行固化,提供更为直接有效的实践方法,建立具有目的性和操作性的构建过程。
丰富,意味着做加法,就是突破领域驱动设计的范畴,扩大领域驱动设计的外延,引入更多与之相关的知识体系来丰富它,弥补自身的不足。
要构建全新的领域驱动设计体系,还需要匹配软件构建的目标。软件构建就是不断对问题域求解,获得解决方案进而组成完整解决方案域的过程。若要构建优良的软件系统,那么在这个构建过程中,还需要控制软件的复杂度。因此,我们需要在问题域与解决方案域的背景下定义能够控制软件复杂度的领域驱动设计过程,并将体系的内容限定在领域关注点的边界之内,避免体系的扩大化。
既然要支持软件构建过程,就需要结合项目的管理过程。
项目的管理过程姿态万千,如何与领域驱动设计结合,却属于空白区域。
例如,当团队采用Scrum过程时,产品待办项(Product Backlog)与冲刺待办项(Sprint Backlog)与领域驱动设计要建模的领域知识有什么关系?当开发人员领取一个用户故事进行开发时,是否意味着在此时才开始领域建模?什么时候开始识别整个系统的限界上下文,又到什么时候结束这一业务架构的分析工作?
如果采用RUP来指导软件的构建,那么该如何区分业务建模与领域驱动设计之间的关系?在领域驱动设计中,用例起到了什么样的作用?在设计基于组件的系统架构时,这些可重用的组件是否就等同于限界上下文呢?
领域驱动设计统一过程
鉴于此,我们构建的领域驱动设计体系就必须形成一个统一过程。
宏观层次,以需求管理体系和面向领域的架构体系为支撑;微观层次,通过领域建模固化流程来保障解决方案的落地;同时糅合领域驱动设计元模型中有价值的模式作为参考,甚至形成能够重复执行的最佳实践。
如此,就可以使得这一体系做到规范与松散互补充,固化与开放相结合。我将这一体系称之为“领域驱动设计统一过程(Domain-Driven Design Unified Process,简称为DDD-UP)”:
领域驱动设计统一过程参考了RUP的结构,整个过程用两个坐标轴来表达:
- 横轴代表了推动领域驱动设计在构建过程中的时间,体现了过程的动态结构,构成元素包括阶段(Phase)、迭代(Iteration)。其中阶段又分为三个阶段,分别为:全局分析阶段、架构规划阶段和领域建模阶段。
- 纵轴表现了领域驱动设计在各个阶段中执行的工作,体现了过程的静态结构,构成元素包括角色(Workers)、工作流(Workflow)和元模型模式(Pattern)或方法(Method)。
采用这一结构的目的就是希望为领域驱动设计引入一个规范而统一的过程,让团队在实施领域驱动设计可以变得有章可依,有章可循,而不仅仅是靠一两个人的经验来决定成功的高度。
搭建整个领域驱动设计统一过程是一个庞大的体系,我会在后续文章中对该过程做概要的描述。我个人正在编写的书籍《解构领域驱动设计(暂定名)》,也将按照这个过程体系进行编写。