领域驱动设计(DDD)-基础思想

本文涉及的产品
数据传输服务 DTS,同步至DuckDB 3个月
简介: 一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在领域驱动设计理念上,各路大侠的观点也是各有不同,能力有限、欢迎留言讨论。 二、领域驱动设计 DDD是什么 wiki释义:     领域驱动设计(英语:Domain-driven design,缩写 DDD)是一种通过将实现连接到持续进化的模型[1]来满足复杂

一、序言

    领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在领域驱动设计理念上,各路大侠的观点也是各有不同,能力有限、欢迎留言讨论。

二、领域驱动设计

DDD是什么

wiki释义:

    领域驱动设计(英语:Domain-driven design,缩写 DDD)是一种通过将实现连接到持续进化的模型[1]来满足复杂需求的软件开发方法。领域驱动设计的前提是:

  • 把项目的主要重点放在核心领域(core domain)和域逻辑
  • 把复杂的设计放在有界域(bounded context)的模型上
  • 发起一个创造性的合作之间的技术和域界专家以迭代地完善的概念模式,解决特定领域的问题

领域驱动设计是一种由域模型(墙裂推荐@阿白 的域模型系列来驱动着系统设计的思想,不是通过存储数据词典(DB表字段、ES Mapper字段等等)来驱动系统设计。领域模型是对业务模型的抽象,DDD是把业务模型翻译成系统架构设计的一种方式。

术概念

DDD中的模型

    模型(Model)与DTO、DO、POJO比较类似都是一个类中有属性、属性有Get/Set方法,并且业务的行为(Action)操作也是在模型类中(充血模型),Model可以看成是MVC三层架构层的业务逻辑层中的Service升级版,一个Model即做业务逻辑处理,又做数据传输对象,模型分为Entity、Value Object、Service这三种类型。

  1. Entity (实体)
    1. 有特定的标识,标识着这个Model在系统中全局唯一
    2. 内部值可以是变化的,可能存在生命周期 (比如订单对象,状态值是连续变化的)
    3. 有状态的Value Object
  1. Value Object (值对象)
    1. 内部值是不变的,不存在生命周期 (比如地址对象不存在生命周期)
    2. 无状态对象
  1. Service (服务)
    1. 无状态对象
    2. 当一个属性或行为放在Entity、Value Object中模棱两可或不合适的时候就需要以Service的形式来呈现

三种模型的复杂度是不一样的,在领域建模选Model模棱两可时,优先选择简单模型原则。模型复杂度顺序 Service > Entity > ValueObject

DDD模型的生命周期

  1. Factory (工厂)

用来创建Model,以及帮助Repository (数据源)注入到Model中

  1. Aggreagte (聚合根)

封装Model,一个Mode中l可能包含其他Model(类似一个对象中包含其他对象的引用,实际概念更为复杂些)推荐@何望 聚合根思考

  1. Repository (数据源)

数据源的访问网关层、通过Repository来对接不同的数据源

DDD模型的边界

  1. 限界上下文,领域边界上下文
    1. 域的拆分
      1. 按业务抽象进行划分
      2. 一个业务拆分成几个独立的域,每个域又可细拆成不同子域
  1. 防腐
    1. 一个域在访问其他域的模型时,把获取到的模型做层转换映射到自己域的模型中(不直接使用别的域模型作为自己域模型中的一部分)
      1. 防止源域模型发生变更,依赖源域模型的调用方,在需要源域模型新功能时,必须要全局依赖修改,才在能兼容
      2. 防止域上下文不一致产生的冲突

 

其他

一个团队,一种语言

一条业务线由研发、产品、业务共同协作和维护,大家只是在不同维度做同一件事情。领域驱动设计的实现方式不仅仅是代码,也可以是PRD、MRD、业务模型图,选择一种大家都能看懂的方式(领域模型术语),统一团队语言,从上层业务到底层实现都是同一个领域模型,减少信息传递经过翻译造成理解不一致。

DDD设计的特点

根据业务模型设计系统

不是通过数据库等数据源驱动设计,是根据业务语义抽象梳理设计成领域模型

数据模型统一

通过真实业务背景,梳理出业务域模型自然会形成出参、入参、中间临时属性收口统一为域模型

业务模型与数据源无关

  1. 数据源数据结构无论怎么变、数据源无论怎么换,领域模型统一无感知,无须变更。
  2. 一个域模型底层对应的数据源可以是1个或n个不同类型数据源
  3. 系统升级底层数据源结构改造时,变更对业务层是透明,域模型可无缝对接,可达到开着飞机换引擎的效果

业务属性字段命名统一、引用唯一

     在现在MVC模式开发中,入参model、数据传输model、数据源model 同一个业务属性含义可能有多种不同的命名,引用情况很难直接排除,当丰富某个业务字段值时,很难直接判断对原有业务的影响范围

业务行为Action收口

在原有开发模式下,一个Model类是一个POJO、DTO、DO,仅做数据传输,没有任何业务相关Action,属于典型的贫血模型。在DDD中一个Model就表述一个业务的域(可能是子域),这个Model不仅有属性,还有业务行为Action,并且这个域的所有操作都在这个Model中,这个Model不仅是数据传输的作用也是一个具体的Service,是属于充血模型。开发人员可以通过关注这个域模型就可以cover负责领域的全部,更不会出现大量的复制-粘贴重复代码。

业务操作高内聚、低耦合

所有这个域的操作都内聚在这个Model中,不会存在同一个相同业务行为在多个Service中存在现象。很多时候一个业务行为功能变更,在原有开发模式下需要把所有的service中有这个业务行为的地方都要变更(粘贴复制代码更为严重)

系统更能直观体现业务逻辑

产品是一直在演进的,PRD、技术方案都很难准确的表明现在产品的真实逻辑,很多时候大家都会遇见这种现象,产品经理不确定当前某个业务点的准确逻辑,需要开发阅读代码翻译给产品经理业务逻辑。

铁打的代码、流水的产研,产品经理、开发流动性都很大,新人仅看文档cover整个系统,很难做到。每个业务准确的细节点,还是要看系统代码实际的逻辑规则。

领域驱动架构

领域驱动设计没有特定的架构风格,它的核心是域模型驱动业务的思想,常见的领域驱动设计架构有经典的三层架构、REST架构、事件驱动架构、CQRS架构、六边形架构等。

经典三层架构

API层

API层是作为对外打包、前端接口调用使用。Domian层是整个域模型,不能直接把它打包成maven给别人使用,也不能直接把它作为接口给前端使用,有些需要API层作为进行转换后调用Domain,对调用Domain返回的数据进行包装筛选后再返回出去。

Domain层

系统的核心层,所有具体的业务逻辑处理、事件处理等都在这层域模型中处理

Repository 层

数据源代理层,Repository 层类似一个网关代理,它本身没有数据,数据都是通过它的代理来被Domain层访问,被代理的数据源不仅仅可以是DB、ES还可以是HTTP、RPC任何与Domain层进行数据交互的都叫Repository

领域驱动设计优势和劣势

DDD不是银弹,它只是复杂性业务的一种解决方式。DDD解决了‘复杂性’,DDD又存在本身设计的复杂性。

优势

系统演进更方便

随着业务的变化、系统设计也要演进升级。好的架构设计一定演化来的,不是一开始就设计出来的,但系统演进过程中的成本,一定是最开始的设计决定的。一个健康公司的成长,业务横向、纵向会发展的会越来越复杂,支持业务的系统也一定会越来越复杂。在领域驱动设计中,域模型对应的是业务模型,是系统架构的内核,通过域模型来驱动与外界的交互。

业务复杂性变化的演进

域模型可能是简单新增属性或action就能支撑整体的业务发展。企业订餐的业务系统要同时有用户端、运营端、企业端、商户端的数据展示和操作,当业务演进出一个新功能时,这四端系统可能都要同时改造支撑。在领域驱动中,系统的域模型是同一套,只需在领域层进行改造,即可同时支撑四端。

业务数据量变化的演进

公司业务数据量的变化后,现有的架构往往很难支持业务的发展,一定会进行新的技术选型支持业务。在DDD中,域模型为内核,在内核外的一层是代理层,通过这层代理来抽象透明化掉业务模型对系统底层设计的感知。比如原本数据量很小,一个简单的搜索直接使用MySQL like 模糊查询即可满足,在数据量巨大这种方式无法满足的时候,需要使用ES这种专业的搜索技术来实现,这时候仅需要在数据源层把原本指向数据源MySQL改成ES即可,业务代码全程透明无感知,可以达到给正在飞行的飞机换引擎的效果。

更方便测试

对于测试(包含开发自测)来说,流程跑不通是痛苦的,由于IO造成阻塞而非系统逻辑是更痛苦。测试的时候最喜欢的纯函数测试,不依赖任何IO(不包含机器内存层面),DDD设计思想是天然的在代码上把纯函数和普通函数区分开,Repository层是非纯函数,在Repository层Mock掉,整体系统就成了纯函数系统,对测试在Mock数据、切换数据源是非常方便和友好的。

劣势

系统改造成DDD复杂

我们常用的架构基本都是MVC三层架构方式,在常用的MVC三层架构中基本所有的业务逻辑都在service层中,并且是按service功能属性设计的Service层,现在要进行DDD思想开发,需要打破原有的设计,有些严重的还必需要进行重构设计。

团队开发熟悉DDD思想困难

改变自己比较困难,对别人产生影响更加困难。一个开发团队如果之前对DDD都没有了解,要推进和对团队产生影响是一个艰难的过程。

 

最后

DDD不仅是统一语言、以业务驱动系统设计,在熟悉新业务和系统重构时,领域驱动设计思想更能很好快速梳理业务。如下图领域驱动设计是以领域(业务模型)为核心,通过数据代理层(Repository)来与其他系统交互,来驱动整个系统架构设计。

 

三、参考引用

【1】域驱动开发

【2】域模型之一, 域模型的价值

【3】如何进行域划分设计

【4】星环 - 为什么业务定制要基于商业能力SDK

相关实践学习
如何在云端创建MySQL数据库
在云计算环境中,数据库服务的迁移和管理是一项关键任务。本场景将为您提供详细的步骤,以指导您在阿里云平台上创建并使用云服务器ECS、云数据库RDS、以及数据传输服务DTS。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
目录
相关文章
|
设计模式 前端开发 关系型数据库
【DDD】全网最详细2万字讲解DDD,从理论到实战(代码示例) 3
【DDD】全网最详细2万字讲解DDD,从理论到实战(代码示例)
5881 2
|
微服务 测试技术 Java
阿里技术专家详解 DDD 系列- Domain Primitive
关于DDD的一系列文章,希望能继续在总结前人的基础上发扬光大DDD的思想,但是通过一套我认为合理的代码结构、框架和约束,来降低DDD的实践门槛,提升代码质量、可测试性、安全性、健壮性。
62629 17
阿里技术专家详解 DDD 系列- Domain Primitive
|
设计模式 弹性计算 人工智能
阿里技术专家详解DDD系列 第四讲 - 领域层设计规范
在一个DDD架构设计中,领域层的设计合理性会直接影响整个架构的代码结构以及应用层、基础设施层的设计。但是领域层设计又是有挑战的任务,特别是在一个业务逻辑相对复杂应用中,每一个业务规则是应该放在Entity、ValueObject 还是 DomainService是值得用心思考的,既要避免未来的扩展性差,又要确保不会过度设计导致复杂性。
|
消息中间件 网络协议 前端开发
殷浩详解DDD:如何避免写流水账代码?
在日常工作中我观察到,面对老系统重构和迁移场景,有大量代码属于流水账代码,通常能看到开发在对外的API接口里直接写业务逻辑代码,或者在一个服务里大量的堆接口,导致业务逻辑实际无法收敛,接口复用性比较差。所以本文主要想系统性的解释一下如何通过DDD的重构,将原有的流水账代码改造为逻辑清晰、职责分明的模块。
殷浩详解DDD:如何避免写流水账代码?
|
微服务 设计模式 测试技术
深入理解 DDD(领域驱动设计)思想
领域驱动设计(DDD)是一种以业务为核心的软件开发方法,通过限界上下文、聚合、实体、值对象等模型,分离业务与技术复杂性,提升系统可维护性与扩展性,尤其适用于复杂业务系统的架构设计。
1129 0
|
前端开发 Java 数据库连接
领域驱动设计(DDD):分层架构
在应用系统开发中,采用严格的、单一的、真正的的分层架构是可以的,但实际上我们已经采用了多种架构模式设计系统。当多种不同范式的架构混合在一起,你会不会出现“指鹿为马”的现象呢?
领域驱动设计(DDD):分层架构
|
6月前
|
存储 设计模式 NoSQL
ddd领域驱动设计
领域驱动设计(DDD)是一种应对复杂软件系统的思维革命与系统方法。它通过“通用语言”统一团队认知,运用“限界上下文”划分业务边界,结合“聚合”“领域事件”等战术模式,精准构建业务模型。DDD不仅提升软件对业务的映射能力,更为微服务架构提供科学的边界划分依据,是打造高内聚、低耦合系统的核心方法论。
|
Java API 领域建模
领域驱动设计(DDD)-简单落地
一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在本文中的实战示例可能会与常见的DDD规则方法不太一样,是简单、入门级别,新手可以快速实践版的DDD。如果不熟悉DDD设计思想可看下基础思想篇 二、设计阶段     领域建模设计阶段常见的方法有 四色建模法、EventSourcing等 推荐一篇博文正确理解领域建
12635 1
|
消息中间件 开发者
DDD领域驱动设计实战(六)-领域服务(上)
DDD领域驱动设计实战(六)-领域服务
781 0
DDD领域驱动设计实战(六)-领域服务(上)
|
消息中间件 测试技术 领域建模
DDD - 一文读懂DDD领域驱动设计
DDD - 一文读懂DDD领域驱动设计
47961 6