一、什么是领域驱动设计

1.1、面向业务的设计

当我们需要构建一个业务复杂的系统,我们不仅要从技术角度去构建一个稳健的系统,还要从业务角度出发,保证系统能满足业务需求。

架构设计的考虑点:不仅面向技术,更应该面向业务;面对不同的业务复杂度,选择的架构可能不同。

架构师的工作:面对复杂的业务逻辑,需要整合业务和技术才能很好地解决。业务架构驱动技术架构。

一个典型开发团队:新手、中级开发者、高级开发者/架构师(技术架构)、领域专家/产品经理(业务架构)、项目经理

要解决的问题:将复杂的业务架构梳理好,并能为技术架构的设计提供要求或指导。

总结:要进行一个业务复杂系统的架构设计,我们要将技术架构和业务架构整合起来。

1.2、使用领域驱动设计,让业务架构和技术架构能整合起来

既然业务对系统架构有影响,那么如何能将业务语言转化为对技术架构设计有指导意义的信息?

其中一种方法就是领域驱动设计。

领域驱动设计:Domain Driven Design(DDD),一种软件开发的方法学

  • 强调开发人员与领域转件协作,交付业务价值
  • 强调业务高层次方向
  • 强调系统建模工具和方法,以满足技术需求

领域:一个组织的业务开展方式,体现业务价值。

例如:电商网站中的产品、订单、发票、库存、物流;保险公司的保险单、理赔、再保险等。

业务价值:有用的领域模型、抽象的业务定义、更好的用户体验、清晰的模型边界;目的是指导开发出优秀的技术架构。

如何使用DDD:

1、业务专家以通用语言准确传达业务规则给开发人员

2、开发人员根据业务规则进行设计模型的设计

3、再设计代码模型以满足设计模型的需求

最终目标:能体现系统业务,又能指导代码开发的一个模型;将设计模型和代码模型很好地结合起来。

通用语言(Ubiquitous Language):

  • 团队成员的行话
  • 面向业务
  • 表现形式:术语表、文档和图、模型语言。。。
  • 面临的挑战:领域专家持续不断介入、开发者对领域的思考方法

综上,我们可以考虑领域驱动设计的设计纬度,从2个方面来看领域驱动设计

设计的策略:

  关注如何设计领域模型以及对领域模型的划分

  • 领域/子域
  • 通用语言
  • 界限上下文
  • 架构风格

  用于清楚界分不同的系统和业务关注点

设计的技术:

  关注技术实现的层面教会我们如何具体地实施DDD

  • 实体/值对象
  • 领域服务
  • 领域事件
  • 资源库

  基于技术设计工具按照领域模型开发软件

总结:我们为使业务能指导架构开发,将业务架构与技术架构整合起来,提供的一种解决办法是领域驱动设计,并提出了领域驱动设计的实现策略和实现技术。

1.3、实现领域驱动设计的思路

  • 提供一套通用的建模语言和术语
  • 展示基于领域趋同的架构设计方法
  • 展示实现领域驱动设计的各项关键技术
  • 基于具体案例展示设计的策略和技术

二、领域与上下文

2.1、架构的轮回

领域(Domain):

  • 一个组织所做的事情以及其中所包含的一切内容
  • 业务范围及所进行的活动
  • 开发某个软件时,面对的就是组织的领域

领域模型(Domain Model):

针对整个业务系统创建的模型

有2种建模方式:

单一、内聚、全功能式:现在的系统越来越复杂,这种形式容易进入难以维护的境地。

功能拆分、服务化、子域:架构更简单更容易维护;适合分布式计算;现在越来越流行,如微服务

架构的迭代与轮回:

我们希望在第4步之前就要将架构简单化,避免到了不可维护的程度

复杂系统的简单化:功能拆分

拆分关注点:核心功能、辅助功能、第三方功能

拆分后的功能组装:系统集成

功能拆分在领域驱动设计的表现:

拆分关注点:子域

功能组装:界限上下文

2.2、领域/子域/界限上下文

子域分类(一个常见分类):

  • 核心域:核心业务
  • 支撑子域:专注于业务的某一方面
  • 通用子域:用于整个业务系统

界限上下文:

  • 领域存在于界限上下文中
  • 每个模型概念、属性和操作,在边界之内有特殊含义
  • 同一个名称的模型,如User,在不同接线上下文中,是不同的

拆分上下文的策略:几个可以考虑的角度

  • 根据业务/通用语言(合适)
  • 根据技术架构(不建议)
  • 根据开发任务分配(不建议)
  • 一个团队一个上下文(合适)

2.3、子域划分案例

以一个项目计划系统作为例子,阐明如何进行子域的划分

项目计划系统的需求:

  • 系统完成对某个项目任务的分解
  • 系统的目的是项目计划的制定
  • 计划的制定通过召开项目会议的方法进行
  • 项目会议的与会人员需要确保身份的有效性

讲解思路:

  • 假想业务流程
  • 围绕领域驱动设计的理念和实践
  • 从策略的设计到技术的设计
  • 层层剖析和演进

初步上下文拆分:

2.4、组织和集成模式

大泥球风格(Big ball of mud):

实践中比较常见,把所有代码都混合在一起,随着业务复杂,逻辑堆积,导致结构不清晰,边界模糊

改进:拆分后集成

高层次的架构分析:上游(Upstream)下游(Downstream):

集成的关注点:

  • 上下文之间的关系如何(谁是上游谁是下游)
  • 不同开发团队之间的关系如何

团队之间的关系:组织和集成模式

  • 合作关系:共同成败
  • 共享内核:共享内核显式边界和小型化
  • 客户方/供应方:上游/下游,下游受上游影响巨大;主流模式但不是最好模式
  • 遵奉者:上游无推动力,下游只能妥协或另谋他路
  • 上面几种不属于较好的方法,以下是比较好的方法
  • 防腐层(Anticorruption Layer):下游客户根据领域模型创建单独一层(可以理解为门面?或适配模式?)
  • 开放主机(Open Host):定义协议,让别人通过协议访问(如RESTful风格)
  • 发布语言(Published Language):共享语言完成集成交流(如发布对应API文档)

2.5、领域模型的上下文集成技术

一般领域模型中较常用的集成技术是以下几种

开放主机服务:

  • 上游上下文提供
  • REST

发布语言:

  • 上游上下文提供
  • XML/JSON/...
  • 消息事件

防腐层:

  • 下游上下文提供

2.6、案例中的上下文

集成的关注点:

  • 上下文之间的关系如何(谁是上游谁是下游)
  • 不同开发团队之间的关系如何

集成分析:

使用到的组织和集成模式:

  • OHS:开放主机
  • PL:发布语言
  • ACL:防腐层

三个子域的集成关系:

  • 【用户权限上下文】是【项目核心上下文】【计划讨论上下文】的上游;
  • 【计划讨论上下文】是【项目核心上下文】的上游;
  • 上游使用【开放主机】和【发布语言的】组织和集成模式
  • 下游使用【防腐层】的组织和集成模式

三、领域驱动架构

3.1、传统分层架构

一般领域层只包含接口,由其他层去实现。

问题:

  • 领域层如何和其它层进行耦合

解决思路:依赖倒置

依赖倒置:

    • 高层不应该依赖于低层,2者都应该依赖于抽象
    • 抽象不应该依赖于细节,细节应该依赖于抽象
    • 编程应该面对抽象,低层实现和高层实现互相独立,改变不会对系统做成影响,而且由于低层独立,可以进行更好的复用。
  • 领域层的服务接口谁去实现

应用层和基础设施层进行实现

当我们使用领域驱动架构时,使用了依赖倒置原则,希望面向领域面向抽象编程,使原来的分层架构变得模糊,不在存在严格的分层概念。

这个时候,有一种更加适合领域驱动架构的编程架构模式:平面型架构

3.2、平面型架构(重要的架构)

领域驱动架构推崇编程架构风格

原因:

  • 系统依赖复杂的领域模型,领域模型应该放中间被其它模块依赖
  • 有界限上下文,需要和其它服务交互
  • 分层架构不太容易实现

平面型架构:

基础架构:

  • 由内而外围绕领域模型展开
  • 应用程序包含业务逻辑

适配器:

  • 多种适配器

    • 数据持久化
    • 数据集成
  • 面向结构和Mock机制

3.3、SOA架构

根据适配器的不同形成不同的架构风格

3.4、RESTful风格架构

4、命令查询职责分离模式CQRS

Command Query Responsibility Segregation

传统数据操作:

CQRS:

解决领域数据和界面显示的匹配:

5、事件驱动架构EDA

Event-Driven Architecture

6、领域驱动设计的策略设计

这里讲解实现领域驱动设计的策略,并通过一个案例作为展示

策略设计的内容包括:

  • 通用语言:使用通用语言描述出业务需求
  • 领域/子域:对系统进行领域划分
  • 界限上下文:对领域的边界进行划分,并确认界限上下文之间如何交互
  • 架构风格:使用平面型架构,是否使用CQRS/EDA

案例策略设计的思路:

  • 领域/子域:

    • 核心域的名字和目标是什么?
    • 核心域包含哪些概念?
    • 核心域的支撑子域和通用子域是什么?
    • 核心如何与其他子域进行写作和集成?
    • 如何针对各子域安排人员?

策略设计的一个参考:

Core核心域

7、领域驱动设计的技术设计

当我们的策略设计完成后,需要关注技术层面,思考如何使用技术来实现这些策略。

7.1、实体与值对象

关于对象:

  • 数据对象:面向数据库

    • 数据驱动(Data-Driven)设计
    • 开发者关注数据的属性和关联关系
  • 实体对象:面向领域
    • 领域驱动(Domain-Driven)设计
    • 很多对象不是通过他们的数据属性定义
    • 实体具有一系列标识和行为定义
  • 普通的开发者趋向关注数据而不是领域

实体:

  • 有唯一标识
  • 具有可变性

唯一标识策略:

  • 用户提供初始唯一致

    • 用户通过界面输入,系统判断是否重复,重复则不允许创建实体
  • 系统内部自动生成唯一标识
    • UUID
    • 根据时间/IP/对象标识/随机数/加密
    • 第三方框架,如Apache Commons Id
  • 系统依赖持久化存储生成唯一标识
    • Oracle的Sequence
    • Mysql的自增列
    • 尽早标识/延迟标识
  • 来自另一个上下文(不推荐使用)
    • 从外部系统查找、匹配和赋值唯一标识
    • 需要考虑对象同步
    • 可以通过时间驱动架构和领域事件解决同步问题

推荐通过内部系统提早生成

贫血模型和充血模型:

贫血模型:

  • 优点:

    • 系统层次结构清楚,各层之间单相依赖,领域对象几乎只用作传输介质用,不会影响到各层次划分。
  • 缺点:
    • 不够面向对象,领域对象只是作为保存状态或者传递状态用,只有数据没有行为的对象不是真正的对象,在Business Logic里面处理所有业务逻辑,对于细粒度的逻辑处理,通过一层Facade达到门面包装的效果。
    • Business Login层比较庞大,边界不易控制,内部的各个模块之间的依赖关系不易管理。

充血模型:

  • 优点:

    • 面向对象,Business Logic符合单一职责,不像贫血模型里面那样包含所有的业务逻辑太过沉重。
    • 每一个领域模型对象都可以具备自己的基础业务方法,通常满足充血模型的特征。
    • 充血模型更加适合较复杂业务逻辑的设计开发。
  • 缺点:
    • 如何划分业务逻辑,逻辑应该正确放到Domain Object和Business Logic比较困难

值对象Value Object:

  • 当只关心对象的属性时,该对象应归为值对象
  • 值对象是不变对象
  • 值对象没有唯一标识
  • 值对象具有较低的复杂性

cusetomer为实体,address为值对象

值对象的特征:如何分离值对象

  • 度量或描述领域中的一个部分
  • 可以作为不变量
  • 将不同的相关属性组合成一个概念整体
  • 当度量或描述改变时,可以以另一个值对象予以替换
  • 可以和其他值对象进行相等性比较
  • 不会对协作对象造成副作用

值对象的应用:

  • 上下文集成
  • 表示标准类型

值对象的实现:

  • 只用构造函数
  • 不用setter方法

建模:使用通用语言

  • 识别实体
  • 挖掘实体关键行为
  • 识别值对象
  • 构建概念整体

建模例子:

实体与值对象的区别:

  • 从标识的角度

    • 实体有唯一标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法
  • 从是否只读的角度
    • 实体可变;值对象只读
  • 从生命周期的角度
    • 实体具有生命周期,而值对象无生命周期可言,因为只是一个值,依附于某个具体实体

7.2、领域服务

背景:

  • 现实中的事物:

    • 有些操作是一系列活动或动作,不是单个事物,概念上并不属于任何对象
    • 建模的基本表现范式是对象,单一些领域概念不适合建模成实体或值对象
  • 我们的思路:
    • 当领域中某个重要的过程或转换操作不属于实体或值对象的职责时,应该在模型中添加一个作为独立接口的操作,既领域服务(Comain Service)

领域服务区别于其它服务:

  • 应用层:资金转账应用服务

    • 获取输入
    • 发送消息给领域层服务并监听确认消息
    • 决定使用基础领域层服务发送通知
  • 领域层:资金转账领域服务
    • 与Account和Money等对象进行交互,执行相应的借入和贷出操作,提供结果的确认
  • 基础设施层:发送通知服务
    • 按照应用程序的指示发送电子邮件等信息

领域服务区别于实体和值对象:

  • 执行一个显著的业务操作过程
  • 以多个领域对象作为输入进行计算,结果产生一个值对象
  • 对领域对象进行转换

2、领域服务建模

3、依赖注入模式

领域事件

以前这个东西没有或不常用,系统复杂度上升后出现

同等地位 实体、值对象、领域服务、领域事件

1、领域事件

2、领域事件建模

3、领域事件实现

代码演示事件订阅者

代码演示事件存储

4、事件转发

聚合

用于理清边界

1、聚合

简化对象


2、聚合建模

3个都是聚合

资源库

1、资源库


2、资源库实现

代码演示

集成界限上下文

1、系统集成基础

2种策略

消息中间件

应用程序

这里比较重要,领域模型只定义接口,基础设置实现,然后由应用程序通过依赖注入来组装?

上面讲解了策略设计,技术设计

下面讲解实例

1、案例分析
2、技术设计

领取驱动架构项目实例

1、代码系统结构

使用自动化构建工具:Maven

Common是通用组件,和业务无关。

其它几个领域依赖Common组件,但是领域之间在Maven层面没有依赖关系。

代码结构:

通过一个父pom管理4个模块,其中3个领域模块依赖Common模块。

2、Common组件

封装一些通用的工具,或基类等,可以自行积累

通用工具类组件:

  • DomainModelBase:领域对象基类
  • Assertion:判断工具,用于进行判断操作,如果判断为假,则抛出IllegalArgumentException或IllegalStateException异常
  • Event/EventStore:事件以及事件存储方案
  • CommonUtil:通用工具
  • PersistenceUtil:持久化工具,抽象持久化
  • RestUtil:封装一些第三方工具
  • SerializationUtil:序列化工具
  • SpringUtil:Spring框架工具类

Event

  • DomainEvent
  • DomainEventPublisher
  • DomainEventSubcriber

Serialization

Json

Gson

FastJSON

EventStore

StoredEvent

EventStore

EventSerializer

MySQLJDBCEventStore

3、Core上下文

转载于:https://www.cnblogs.com/LiveYourLife/p/9342566.html

【系统架构理论】一篇文章搞掂:领域驱动设计相关推荐

  1. MTD系统架构和yaffs2使用、Nandflash驱动设计

    一.MTD系统架构 1.MTD设备体验 FLASH在嵌入式系统中是必不可少的,它是bootloader.linux内核和文件系统的最佳载体. 在Linux内核中引入了MTD子系统为NORFLASH和N ...

  2. 领域驱动设计(DDD):分层架构的三种模式

    DDD DDD(Domain Driven Design,领域驱动设计)作为一种软件开发方法,它可以帮助我们设计高质量的软件模型.在正确实现的情况下,我们通过DDD完成的设计恰恰就是软件的工作方式. ...

  3. 微服务架构设计基础之领域驱动设计

    背景 微服务现在可以说是软件研发领域无人不提的话题,然而业界流行的对比多数都是所谓的Monolithic(单体应用),而大量的系统在十几年前都已经是以SOA(面向服务架构)为基础的分布式系统了,那么微 ...

  4. 领域驱动设计在美团点评业务系统的实践

    至少30年以前,一些软件设计人员就已经意识到领域建模和设计的重要性,并形成一种思潮,Eric Evans将其定义为领域驱动设计(Domain-Driven Design,简称DDD).在互联网开发&q ...

  5. 大家一直在谈的领域驱动设计(DDD),我们在互联网业务系统是这么实践的

    至少30年以前,一些软件设计人员就已经意识到领域建模和设计的重要性,并形成一种思潮,Eric Evans将其定义为领域驱动设计(Domain-Driven Design,简称DDD).在互联网开发&q ...

  6. 微服务架构与领域驱动设计应用实践

    本篇文章一共分为三个部分,分别是微服务架构的演进过程.具体实践微服务的应用技术和领域驱动设计的意识转变.微服务架构已经渗透到互联网应用的方方面面,而领域驱动设计也逐渐被业界所接收. 微服务架构几乎都是 ...

  7. 如何使用ABP框架(2)三层架构与领域驱动设计的对比

    本文来自长沙.NET技术社区,原创:邹溪源.全文共有8500字,读完需耗时10分钟. 题图来自@pixabay 简述 上一篇简述了ABP框架中的一些基础理论,包括ABP前后端项目的分层结构,以及后端项 ...

  8. c/s三层结构信息系统的三个层次_如何使用ABP框架(2)三层架构与领域驱动设计的对比...

    本文来自长沙.NET技术社区,原创:邹溪源.全文共有8500字,读完需耗时10分钟. 题图来自@pixabay 简述 上一篇简述了ABP框架中的一些基础理论,包括ABP前后端项目的分层结构,以及后端项 ...

  9. 如何使用ABP进行软件开发(2) 领域驱动设计和三层架构的对比

    简述 上一篇简述了ABP框架中的一些基础理论,包括ABP前后端项目的分层结构,以及后端项目中涉及到的知识点,例如DTO,应用服务层,整洁架构,领域对象(如实体,聚合,值对象)等. 笔者也曾经提到,AB ...

  10. DDD(领域驱动设计)分层架构

    一.分层架构的模型 DDD全称为(Domain-Driven Design,简称DDD),领域驱动设计. 主要分为四层: 展现层:它负责向用户显示信息和解释用户命令,完成前端界面逻辑.这里的用户不一定 ...

最新文章

  1. debounce实现 js_javascript防抖函数debounce详解
  2. linux_OEL5.4_安装Oracle11g中文教程图解
  3. php log pecl,PHP日志扩展SeasLog-1.0.0正式版在PECL发布
  4. python函数的万能参数
  5. 百度视频携手神策数据 为用户精准推送短视频内容
  6. deepin ubuntu修改grub启动延时时间
  7. Redis 几种应用场景
  8. C#发送电子邮件 (异步) z
  9. D3DLOCK写纹理遇到的问题
  10. python实现pdf解密和pdf转图片
  11. 倒计时6天|2020腾讯广告犀牛鸟计划申请即将截止,错过再等一年!
  12. SPOJ QTREE4 lct
  13. 有什么电脑软件可以测试网速,电脑怎么测试网速(测网速大全)
  14. Nginx的keeplive
  15. 零一块学计算机二级题库,2017年计算机二级office题库及答案
  16. [原创]Javascript 利用mousetrap.js进行键盘事件操作
  17. iphone计算机照片大小,如何把iphone照片导入电脑 四种方法分享【图文】
  18. 0606关于mysql优化原理
  19. 利用python实现杜利特尔分解法
  20. 电磁兼容工程(Electromagnetic compatibility engineering Herry Ott )读书笔记--章12 数字电路的辐射

热门文章

  1. 删除在wps文档中的空白页,方便pdf输出无空白页
  2. 深度学习笔试100题
  3. 电脑桌面图标全部变成Word图标?
  4. A股日内回转(日内T+0)优缺点
  5. python的数组怎么用_Python中的数组-什么是Python数组以及如何使用它们?
  6. qt编写网易云界面(13)----一键换肤模块
  7. 解决方法:A fatal error occurred. The required library hostfxr.dll could not be found.
  8. 抖音爆款短视频配音如何制作?分享3个免费好用的配音软件
  9. 利用递归实现JSON扁平化
  10. Python 函数的了解与使用