GitHub男人的天堂,你真的玩的转吗?超强超详细GitHub教程
领域驱动设计(Domain Driven Design,DDD)是由Eric Evans最早提出的综合软件系统分析和设计的面向对象建模方法,如今已经发展为一种针对大型复杂系统的领域建模与分析O e X ; s b 5方法。它完全改变了传O : O u s ` S 2统软件开发工程师针对数据库进行的建模f L 4 4 E & g q方法,从而将要解决的业务概念和业务规则转换为软件系统中的类型以及类型的属性与行为,通过合理运用面向对象的封装、继承、多态等设计要素,降低或隐藏整个系统的业务复杂性,并使得系统具有更好的扩展性,应对纷繁多变的现实业务问题。
领域驱动设计的开放性
领域驱动设计是一种方法论(Methodology)。根据维基百科的定义,方法论是一套运用到某个研究领域的系统与理论分析方法。领域驱动设计就是针对软件开发领F I i域提出的一套系统与理论分析方法。Eric Evans在创造性地提出领域驱动设计时,实则是针对当时项目中聚焦在以数据以及数据样式为核心的系统建模方法的批判。面k y D R N y想、设计原则与设计过程。
由于领域驱动设计是一套方i P _ D法论,它建立了以领域为核心驱动力的设计体系,因而具有一定的u ; ] 2 ) 2 ~ l开放性。在这个体系中,你可以使用不限于领域驱动设计提出U j ! }的任何一种方法来解决这些问题。例如,我们可以使用用例(Use Case)、测试驱动开发(TDD)、用户故事(User Story)帮助我们对领域建立模型;我们可以引入整洁架构思想以9 ] c及六边形架构,以帮助我们建立一个层次分明、结构清晰的系统架构;我们可以引入函数式编程思想,利用纯函数与抽象代数结构的不变性以及函数的组合性来表达领域模型。这些实践方法与模型已经超越/ B 2 o 7 ~ Y z F了Eric Evans最初提出的领域驱动设计范畴,但在体系上却是一脉相承的。这也是为什么在领域驱动设计社区,能够不断诞生诸如CQRS模式、事= ^ r z n @ y并通过统一语言进行领域建模时,可能会面临高复杂度的挑战。这是因为对于一个复杂的软件系统而言,我们要处理的问题域实在太庞大了。在为问题域寻求解决方案时,需要从宏观层次划分k f . i c不同业务关注点的子领域,然后再深入到子领域中从微观层次对领域进行建模。宏观层次是战略的层面,微观层次是战术的层面,只有将战略设计与战术设计结合起来,才是完整的领域驱动设计。
战略设计阶段
领域驱动设计的战略设计阶段是从两个方面来考量的:
- 问题域方面:针对问题域,引入限界上下文(Bounded Context)和上下文映射(Context MI U | K 5 Gap)对问题域进行合理的分解,识别出核心领域(Core Doma| T Tin)与子领域(SubDomain),并确定领域的边界以及它们之间的关系,维持模型的完整性。
- 架构方面:通过分层架构来隔离关注点,尤其是将领& p v c 2 #域实现独立出来,可以# O | p b s (更利于领域模型的单一性与稳定性;引入六边形架构清晰地表8 r ) y U达领域与技术基础设施的边界;CQRS模式则分离了查询场景和命令场景,针对不同场景选择使用同步或异步操作,提高架构的低延迟性与高并发能力。
Eric Evans提出战略设计的初衷是| a y 4 l 3 V要保持模型的完整性。限界上下文的边界可以保护上下文内部和其他上下文之间的领域概念S t G W M v } /互不冲突。然而,如果我们将领域驱动设计的战略设计模式引入到架构过程中,就会发现限界上下文不仅限于对领域模型的控制,而在于分离关注点之后,使得整个上下文可以成为独立部署的设计单元,这就是“微服务”的概念,上P # M v R ]下文映射的诸多模式则7 I _ & 对应了微服务之间的协作。因此在战略设q Q U u a计阶段,微服务扩展了领域驱动设计的- E j e U h * 8内容,反过来领域驱动设计又能够v g | X Q B W W V保证良好的微服务设计。
一旦确立了限界上下文的边界,尤其是作为物理边界,则分层架构就不再针对整个软件系统,而仅仅针对粒度更小的限界上下文。此时,限界上下文定义了技术实现的边界,对当前上下文的领域与技术实现进行了封装,我们只需要关m L h X B ^ c I心对外暴露的+ T {接口与T a R k H : / % )集成方式,形成了在服务层次的设计单元重用。z v ] P
边界给了实现限界上下? ] 6 *文内部的最大自由度。这也是战略设计在分治上起到的效用。我们可以在不同的限界上下文选择不同的架构模式,例如针2 K } ! j ?对订单的查询与处理,选择CQRS模式来分别处理同步与异步场景;还可以针对核心领域与子领域重要性的不同,分别选择领域模型(m I r {Domain Mode[ % u 8 :ct)
Eric Evans通过下图勾勒了战术设计诸要素之间的关系:
领域驱动设计围绕着领域模型进行设计,通过分z = ! U O层架构(Layered Architectu] T $ 4 =re)将领域独立出来。表示领域模型的对象包括:实体、值对象和领域服务。领域逻辑都应该封装在这些对象中。这一严格的设计原则可以避免业务 Q - U逻辑渗透到领域层之外,导致技术实现与业务逻辑的混淆。在领域驱动设计的演进中,又引入了领域事件来丰富领域模型。
聚合是一种边界,它可I @ O O { { = 5以封装一到多个实体与值对象,并维持f T ; j #该边界范围之内的业务完整性。在聚合中,至少包含一个实体i k ? % 2 U Z 8,且只有实体才能作为聚合根(Aggregate Roo X O * E进而以演进的方式对[ J X - y 2 D 之前的战略设计阶段进行迭代,从而形成一种螺旋式上升的迭代设计过程g F y z j ?,如下图所示:
面对客户的业务需求,由领域专家与开发团队展开充分的交流,经过需求分析与知识提炼,获得清晰的问题域。通过对问题域进行分析和建模,识别限界上下文,利用它划分相对独立的领域,6 $ { U = o k J再通过上下文映射建立它们之间的关系,辅以分层架构与六边形架构划分系统的逻辑边界与物理y s u Y D , 1 s l边界,界定领域与技术之间的界限。之后,进入战术设计阶段,深入到限界上下r w Q文内对领域进行建模,并以领域模型指导程序设计与编码实现。b _ . M m L若在实现过程中,发现领域模型存在重复、错位或缺失时,再进而对已有模型进行重构,甚至重新划分限界上下文。
两个不同 - a D d { &阶段的设计目标是保持一致的,它们是一个连贯的过程,彼此之间又相互指导与规范,并最终保证一个有效的领域模型和一个富有表达力的实现同时演进。