容我找个借口先,日常工作太忙,写作略有荒废。一直想聊下领域驱动设计,以下简称DDD,之前也看过一些教程,公司今年两个项目--银行核心和信用卡核心,都深度运用DDD成功落地,有人说DDD挺难理解,在此讲下我的浅薄认知,
争取言简意赅的点明其核心要义。
  先扔出几个名词:Domain领域对象--对照现实中有唯一属性的事物,就像世界上唯一的你,既富且帅还有能改变世界的行为能力;ValueObject值对象--可重复使用的对象,因领域对象而存在,多附着于领域对象上,如快递地址,你我可以共用;
Aggregate聚合--若干难分难舍的领域对象愉快地成为一个歌唱组合;BoundedContext限界上下文--若干志同道合的聚合走到了一起;Aggregate root聚合根--一个聚合中作为老大的Domain,该聚合出入事项都必须经过他办理。
                                                            图1-各种对象的例子
  首先,DDD的核心理念
  领域驱动设计的断句可以为“领域--驱动设计”,即由领域概念来驱动系统设计,和“领域驱动--设计”,即领域驱动本身的设计,我倾向于前者,因为如果引入DDD,其理念应该是贯穿整个系统诞生过程的。
  DDD的核心理念我认为只需领悟三个词:面向对象、分层、隔离
  面向对象,集中体现在Domain领域对象的代码实现上。C++、Java和Python都强调OOP,但这个OOP很大程度上指的编程语法含义,如何将属性和方法形成一个对象,对象间又存在继承、实现等关系,与“面向过程”对应。DDD的面向对象,
是从现实中抽象出实体对象映射为数据库表和领域对象,该领域对象具有属性和方法。比如在对公信贷中,将信贷合同作为一个Domain,它本身就应该具备现实中“合同文本”事物的属性,包括合同ID、合同类型、签订日、甲乙方、合同内容、信
贷产品、到期日...等等,还应该有签订合同、修改合同、作废合同、关联合同...等等动作,并由若干Domain和ValueObject组合为一个聚合对象,若干聚合又可组合为一个限界上下文对象(若干,可能是零个/一个/多个)。这里要额外提一下,
ValueObject与Domain的根本区别就是Domain有唯一ID,此ID映射为现实世界中事物的唯一性。拿我们熟悉的SpringMVC做面向对象对比,与数据表进行映射的PO/Entity不带有任何动作,只有属性和get/set,如果中间过程有需要组装出来的DTO、
BO等也较少带有业务逻辑方法,更多只是为了在ServiceImpl中作为整体操作对象而存在。
  隔离,有两个方面的含义,一是业务逻辑的隔离,一是数据的隔离。业务逻辑的隔离体现在核心业务逻辑的实现都在一个个Domain对象内部,每个核心业务逻辑都具有业务原子特征,若干Domain对象组合为一个聚合,若干聚合成为一个
BoundedContext,若要使用这些功能,只能通过BoundedContext下的“聚合根”或领域对象提供的接口。数据的隔离体现在一个领域对象对应一些数据表,这些数据表的任何操作,只能通过该领域对象内的方法来实现,即形成一个垂直划分的数据
与逻辑结构。借用银行信贷的概念来讲,合同的业务逻辑全部由合同领域对象实现,且只能由合同领域对象操作合同相关的DB表,如果客户相关业务需要更新客户和合同信息,则由客户领域对象更新客户DB表并通过合同领域对象更新合同相关的
DB表。如下图,各数据要保持逻辑上的隔离,各上下文、绿色Domain之间逻辑隔离:
                                                            图2-各领域对象的全景实例
 
  分层,还是拿我们熟悉的SpringMVC做对比,通常是DAO操作数据库,Service引用DAO,Controller层引用Service来对前端或对外提供业务服务,逻辑的具体实现都大量堆积在ServiceImpl中。DDD将数据库表的CRUD单独作为Repository层,
简称Repo仓储层,Domain中调用Repo的CRUD完成对DB的操作,同时这里有个非常重要的分层原则,即同层之间是严格禁止相互调用的,只能上层调用下层且不能跨层。在Domain层之上是DomainService层,再上是Application层,甚至还有防
腐层等等。在分层上,我认为可以灵活处理,适当裁剪,如DAO层中使用Mybatis,再套上一层成为Repo层,也不失为一种好的实践,做好最为关键的Repo和Domain分层即可。
                                                            图3-DDD分层调用
 
 

图4-SpringMVC与DDD对比

图5-DDD项目包结构实例

  其次,DDD解决了什么问题。解决了领域对象Domain从无到有,领域划分的难题,类似于微服务如何划分的问题,并完成了概念模型到代码的映射。DDD引入了一系列的概念和模型,从理论上支撑了各种DDD对象的设计,并提出了多条核心
原则。当我们面对一个全新的系统建设项目时,就可以先从现实世界中的事物对象开始,整理出各种属性和动作,再将属性和动作按照亲和关系,抽象为领域对象或者值对象,并建立数据表,然后逐步建立起聚合、聚合根、限界上下文对象、领域
服务、应用服务、接口服务等,代码就像聚沙成塔一样,逐层组装为完整的系统代码。
 
 

图6-一种实现DDD结构的方法论

  最后,DDD与微服务的联系。微服务是一种大的架构思想,将关联的功能聚合为一个服务体,多个服务体逻辑上又提供一个系统的完整功能,微服务架构强调的是服务间的隔离与服务规模化后的治理,每个微服务自带数据库独立向外提供特定功
能,多个服务的治理又需要配合网关、缓存中心、消息队列、事务管理器、配置中心、服务容器、容器编排等中间件或平台,共同构成完善的微服务架构,微服务关注层级到服务体为止,强调哪些功能应该组合形成一个服务体,服务体间还可以是异
构的。DDD关注代码从无到有,逐步将“Domain领域对象”概念落实到代码中来,从领域对象到限界上下文,每个限界上下文又可以独立为一个微服务体,也可以是系统代码中的一个Module,DDD不关注整体应用架构,而是代码形成的过程,在代码层
面关注隔离与分层。所以,两者侧重不同,但我认为DDD可以作为微服务架构的前序,一个小处着眼,一个大处着手,结合起来即成了一个非常完整的架构落地方案了。
  全文完,感谢阅读。
 
本人原创,谢绝任何形式转载,否则追究法律责任。
 
    • 我的微信公众号,只写原创文章!
 

白话领域驱动设计DDD的更多相关文章

  1. 领域驱动设计(DDD)

    领域驱动设计(DDD)实现之路 2004年,当Eric Evans的那本<领域驱动设计——软件核心复杂性应对之道>(后文简称<领域驱动设计>)出版时,我还在念高中,接触到领域驱 ...

  2. 领域驱动设计(DDD:Domain-Driven Design)

    领域驱动设计(DDD:Domain-Driven Design) Eric Evans的"Domain-Driven Design领域驱动设计"简称DDD,Evans DDD是一套 ...

  3. python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))

    昨日内容回顾 1. 三个类 ChangeList,封装列表页面需要的所有数据. StarkConfig,生成URL和视图对应关系 + 默认配置 AdminSite,用于保存 数据库类 和 处理该类的对 ...

  4. 关于领域驱动设计 DDD(Domain-Driven Design)

    以下旨在 理解DDD. 1.     什么是领域? 妈妈好是做母婴新零售的产品,应该属于电商平台,那么电商平台就是一个领域. 同一个领域的系统都有相同的核心业务. eg: 电商领域都有:商品浏览.购物 ...

  5. 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式

    -之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...

  6. 轻量级领域驱动设计DDD Lite在嵌入式系统重构中的应用

    前言 目前,关于领域驱动设计(Domain Driven Design)DDD的培训,材料,视频都比较多,大家对DDD的一些概念都有所了解,但是在实际使用过程中,有很多的问题.例如 为什么DDD的架构 ...

  7. 分享我对领域驱动设计(DDD)的学习成果

    本文内容提要: 1. 领域驱动设计之领域模型 2. 为什么建立一个领域模型是重要的 3. 领域通用语言(Ubiquitous Language) 4.将领域模型转换为代码实现的最佳实践 5. 领域建模 ...

  8. 领域驱动设计(DDD)实现之路

    2004年,当Eric Evans的那本<领域驱动设计——软件核心复杂性应对之道>(后文简称<领域驱动设计>)出版时,我还在念高中,接触到领域驱动设计(DDD)已经是8年后的事 ...

  9. 领域驱动设计(DDD:Domain-Driven Design) 介绍

    Eric Evans的“Domain-Driven Design领域驱动设计”简称DDD,Evans DDD是一套综合软件系统分析和设计的面向对象建模方法,本站Jdon.com是国内公开最早讨论DDD ...

  10. 我对领域驱动设计(DDD)的学习成果

    领域驱动设计之领域模型 2004年Eric Evans发表Domain-Driven Design – Tackling Complexity in the Heart of Software (领域 ...

随机推荐

  1. UART-UART非常见波特率调试应用笔记

    UART非常见波特率调试 应用笔记 串口通信中的波特率选择,对于确保可靠的数据传输至关重要.波特率是衡量单位时间内传输的比特数,常见的波特率包括300.1200.2400.9600.115200等.不 ...

  2. Java动态数组及数组排序的三种常用方法

    一.动态数组 1.数组的定义: ​ 用于存储相同数据类型的一组连续的存储空间 2.数组的特点: ​ 数组的长度一旦定义,则不可改变 ​ 访问数组的元素需要通过下标(索引)访问,下标从0开始 ​ 数组是 ...

  3. 如何在2023年开启React项目

    在这里,我想给你一个新的React项目入门的简要概述.我想反思一下优点和缺点,反思一下作为一个开发者所需要的技术水平,反思一下作为一个React开发者,每个启动项目都能为你提供哪些功能.最后,你将了解 ...

  4. 【python基础】循环语句-while循环

    1.初识while循环 循环语句主要的作用是在多次处理具有相同逻辑的代码时使用.while循环是Python提供的循环语句之一. while循环的语法格式之一: 比如我们输出1-10之间的奇数,编写程 ...

  5. IM1281B电能计量模块_C语言例程

    一.前言 毕设采用了艾锐达公司的IM1281B电量计能模块,找了一圈没发现具体的51单片机的例程,现在写个能使用的C语言例程,方便以后的开发者们. 二.事前准备 引脚定义: 引脚 功能说明 V+ 供电 ...

  6. [AGC055A] ABC Identity 题解

    [AGC055A] ABC Identity 题解 题目描述 给定长度为 \(3n (1 \le n \le 2e5)\) 的序列,其中字母 A,B,C 各有 \(n\) 个. 一个合法序列 \(T\ ...

  7. 如何在矩池云上安装和使用 Stata

    Stata是一款功能强大的统计分析软件,本文提供了如何在矩池云安装使用 Stata,以及如何在 Jupyter 中使用 Stata 的简要教程. 安装 Stata 时需要确保按照官方指南进行操作,St ...

  8. 6大数据实战系列-sparkSql实战

    sparkSql两个最重要的类SqlContext.DataFrame,DataFrame功能强大,能够与rdd互转换.支持sql操作如sql().where.order.join.groupBy.l ...

  9. 3 大数据实战系列-spark shell分析日志

    1 准备数据源 文件格式: 访问时间\t用户ID\t[查询词]\t该URL在返回结果中的排名\t用户点击的顺序号\t用户点击URL 数据文件越大越好,至少100万行 2 启动任务 ./spark-sh ...

  10. Sentieon安装时 jemalloc error 解决办法

    背景 Sentieon建议使用jemalloc来改善Sentieon应用程序中的内存管理和整体性能,尤其是Sentieon bwa-mem.有时在安装运行过程中会出现报错: ERROR: ld.so: ...