专业的编程技术博客社区

网站首页 > 博客文章 正文

领域驱动设计开篇:领域驱动设计的本质及相关概念

baijin 2024-09-01 12:57:42 博客文章 4 ℃ 0 评论

引言

领域驱动设计(Domain Driven Design),简称DDD,大神 Eric Evans 2004年的《Domain-Driven Design: Tackling Complexity in the Heart of Software》一书中第一次提出。

领域驱动设计是一种用于指导软件设计的方法论,也是一种设计思维方式,用于解决软件复杂性问题,旨在加速那些必须处理复杂领域的软件项目的开发。

问题空间和解决方案空间

  • 问题空间:Problem Space

是当前环境下业务所面临的一系列问题和问题背后的需求,通常是业务和产品领域专家主导问题、需求的收集描述和分析。

  • 解决方案空间:Solution Space

解决方案空间是针对问题空间的解决方案,属于工程实现阶段,由技术专家主导方案设计。

软件开发过程,本质上可以看作是问题空间到解决方案空间的映射转化

  • 问题空间,找出业务挑战及其对相关需求场景用例分析
  • 解决方案空间,通过具体的技术工具手段来进行设计实现

理解领域、模型和领域模型

领域:Domain

“领域”是“知识或活动的集合”,相对于软件系统而言,领域就是软件应用所要解决的现实问题区域。领域对应于问题空间,是一个特定范围边界内的业务需求的总和。

领域模型:Domain Model

模型被用来描绘人们所关注的现实或想法的某个方面,本质上是一种简化和抽象,把与解决方案密切相关的方面抽象出来,而忽略无关细节。

要想构建满足需求的软件,开发团队需要软件面向的领域所涉及的知识可能非常庞大和复杂,而模型正是解决这种信息超载问题的有效工具

对领域进行模型设计的过程就是领域建模,领域建模的目的并非是要建立一个百分之百符合“现实”的模型,理论上,我们也无法实现这种对现实的完全建模,而只能是对现实某种程度的模拟。


领域建模的输出即领域模型,领域模型是针对特定领域里的关键事物及其关系的可视化表现,属于解决方案空间范畴。为了准确定义需要解决问题而构造的抽象模型,为软件系统的构建目标统一认知,是业务功能场景在软件系统里的映射转化。

领域模型并非领域专家头脑中的知识,而是对这些知识进行严格的组织和有选择的抽象。同时,领域模型并非某种特殊的图、文字或者代码,而是他们所传达的思想,图、文字或代码都可以作为模型的表示或传达形式,但他们不是模型,而是不同维度的模型视图。

领域驱动设计

领域驱动设计强调领域模型的重要性,并通过模型驱动设计来保障领域模型与程序设计的一致。领域驱动设计首先从业务需求中提炼出统一语言,并建立领域模型指导着程序设计以及编码实现;最后,又通过重构来发现隐式概念,并不断解决领域领域模型相关的新问题。本质上,领域驱动设计也是从问题空间映射到解决方案空间。领域驱动设计结合了宏观和微观两个层面的设计,分别对应于领域驱动概念中的战略设计和战术设计。

领域驱动设计:战略设计

战略设计的初衷是要保持模型的完整性,主要从下面两个方面来考量:

  • 问题域方面

针对问题域,引入限界上下文和上下文映射对问题域进行合理的分解,识别出核心领域与其他子领域,并确定领域边界以及它们之间的关系,维持模型的完整性。

  • 架构方面

通过分层架构来隔离关注点,尤其是将领域实现独立出来,能够更利于领域模型的单一性与稳定性;引入六边形架构可以清晰地表达领域与技术基础设施的边界。

领域驱动设计:战术设计

战略设计的初衷是要保持模型的完整性,通过战略设计将整个软件系统分解为多个限界上下文,然后对每个界限上下文进行战术设计。对每个限界上下文进行战术设计。模型驱动设计的构造要素以及要素间的关系如下图所示:

实体:Entity

不同于通过属性进行定义的传统对象,实体对象通过唯一标识进行区分,且具有持续的生命周期。

值对象:Value Object

值对象是具有属性且不可变的对象,但没有唯一标识。

领域事件:Domain Event

领域事件用于记录系统内的模型活动相关的离散事件,虽然系统内所有事件都应该能够被跟踪,但只有被领域专家关心的事件类型才创建领域事件。

聚合:Aggregate

聚合对象是实体和值对象的聚合,聚合具有一个唯一的根,即聚合根。外部对象不再直接访问聚合内部的单个对象或者实体,而是直接访问聚合根,并使用聚合根将指令传递给对应的分组。

领域服务:Domain Service

某些领域逻辑不适合分配给某个特定的实体对象,可将其这些操作封装成领域服务

资源库:Repositories

资源库不是配置库,它提供一个全局接口来访问特定聚合内部所有的实体类和值对象,应该包括创建,修改,删除聚合内部对象的方法。

工厂:Factories

工厂封装了创建复杂对象和聚合的逻辑,对客户端屏蔽创建的复杂性

领域驱动设计的优势

  • 团队沟通更顺畅

领域驱动设计早期关注于建立与领域模型相关的统一语言,使得团队间的交流更加容易。典型的,团队进行讨论时会需要更少的技术术语,因为在统一语言中已经建立了能够反映这些技术语言的简单且统一的词汇。

  • 灵活扩展

领域驱动设计基于面向对象分析和设计的思想,几乎领域模型的所有元素都是基于对象,也因此具备模块化和封装性的特点,这允许系统的不同组件甚至是整个系统都被周期性和持续的改动和改进。

  • 注重领域胜过接口

与首要关注UI的应用不同,领域驱动设计的实践是围绕领域概念和项目中领域专家的建议展开设计,因此,领域驱动设计产出的应用通常能够精准遵循和表示领域业务。同时,关注点在于领域使得领域驱动设计更适合于产出符合这些领域内用户期望的产品。

领域驱动设计的障碍

  • 需要鲁棒的领域知识,依靠项目中领域专家的支持

如果团队中没有熟悉应用所需领域知识的领域专家,即使具备技术再强的开发人员也无济于事。在某些情形下,领域驱动设计需要一个或多个外部人员在整个软件开发生命周期中扮演领域专家的角色。有些情况下,领域驱动设计需要在整个软件开发生命周期中与外部团队成员(充当领域专家角色)进行协作。

  • DDD强调不断迭代和持续集成,对缺乏迭代经验而偏重于瀑布模型的团队可能导致障碍

领域驱动设计实践依赖不断迭代和持续集成来构建高可扩展的项目,很多人认为迭代时好的实践。但是这种基于迭代和持续集成的时间,在某些组织中落地可能会存在阻碍,特别是如果过去经验是建立在僵化的开发模型上,比如瀑布模型。

  • 不适合偏向技术型的应用

领域驱动设计适合于具有非常高领域复杂性(业务逻辑复杂)的应用,但不适用于领域复杂性很低但技术复杂性很高的领域。DDD着重强调需要领域专家以便构造出项目依赖的统一语言和领域模型,但是如果项目的技术复杂性很高,领域能否理解是一种挑战。当全体团队成员没有完全理解技术需求或限制时可能会导致问题。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表