如何领域驱动设计?-实践感悟&总结分享
主要是在开发过程中,个人对于领域驱动设计的实践感悟和总结;也是对新进开发人员的培训资料;希望对关注DDD的童鞋有所帮助。
概述
领域驱动不是纯粹的技术问题,领域建模(建立数据表只是一部分)是领域专家(客户/产品团队)和开发人员沟通努力、抽象的的结果。
领域建模的目的是,经过有效的沟通、详细分析、 良好设计可以更好的适应未来的变化。
领域驱动设计的核心是建立正确的领域模型。
面向人员
后端开发人员、产品人员
一、背景
领域驱动设计是什么?
领域驱动设计的核心是建立正确的领域模型,正确的反应业务,并适应变化。
为什么建立一个领域模型是重要的
(1). 领域模型是具有边界的领域抽象,反映了领域业务需求的本质,边界指只领域内所关注的部分;
(2). 领域模型只反映业务,和任何技术实现无关, 包括实体概念(如商品)和过程概念(资金转账);
(3).领域模型确保业务逻辑内聚在一个模型中,帮助可理解和重用;
(4). 领域模型帮助开发人员平滑转换为软件构造;
(5).领域模型贯穿软件分析设计开发整个过程,领域专家、设计、开发人员始终保持沟通,共享信息,确保软件真正满足需求;
(6).建立正确的领域模型并不简单,需要领域专家、设计、开发人员积极沟通共同努力,然后才能使大家对领域(业务需求)的认识不断深入,从而不断细化和完善领域模型;
(7).领域模型是整个软件的核心,是最有价值和最具竞争力的部分;设计足够精良且符合业务需求的领域模型能够更快速的响应需求变化;
领域建模时思考问题的角度
二、概念
领域驱动分层
User Interface 用户界面层
在PC页面、APP界面、WebAPI接口展示数据;
发送命令给应用层要求其执行某个用户命令;
Application 应用层
定义系统要完成的所有任务,对用户界面层提供应用功能。对内调用领域层(领域对象或领域服务)完成业务逻辑,应用层不包含业务逻辑。
Domain 领域层
负责表达业务概念,业务状态信息以及业务规则,领域模型处于这一层,是业务软件的核心。
限界上下文
限界上下文是个高内聚的领域模型(例订单模块),是未来系统做水平拆分的关键,可以说就是将一个限界上下文模型拆分升级为一个子系统。
开发人员可以简单理解,限界上下文可以转换成代码,放在一个高内聚的dll项目;
AggregateRoot 聚合根
聚合,它通过定义对象之间清晰的所属关系和边界来实现领域模型的内聚,并避免了错综复杂的难以维护的对象关系网的形成。聚合定义了一组具有内聚关系的相关对象的集合,我们把聚合看作是一个修改数据的单元。
聚合的特点:
(1). 每个聚合有一个根和一个边界,边界定义了一个聚合内部有哪些实体或值对象,根是聚合内的某个实体;
(2). 聚合内部的对象之间可以相互引用,但是聚合外部如果要访问聚合内部的对象时,必须通过聚合根开始导航,绝对不能绕过聚合根直接访问聚合内的对象,也就是说聚合根是外部可以保持 对它的引用的唯一元素;
(3). 聚合内除根以外的其他实体的唯一标识都是本地标识,也就是只要在聚合内部保持唯一即可,因为它们总是从属于这个聚合的;
(4). 聚合根负责与外部其他对象打交道并维护自己内部的业务规则;
(5). 基于聚合的以上概念,我们可以推论出从数据库查询时的单元也是以聚合为一个单元,也就是说我们不能直接查询聚合内部的某个非根的对象;
(6). 聚合内部的对象可以保持对其他聚合根的引用;
删除一个聚合根时必须同时删除该聚合内的所有相关对象,因为他们都同属于一个聚合,是一个完整的概念;
如何识别聚合及聚合根?
我觉得我们可以先从业务的角度深入思考,然后慢慢分析出有哪些对象是:
有独立存在的意义,即它是不依赖于其他对象的存在它才有意义的;
可以被独立访问的,还是必须通过某个其他对象导航得到的;
如何识别聚合根?
如果一个聚合只有一个实体,那么这个实体就是聚合根;如果有多个实体,那么我们可以思考聚合内哪个对象有独立存在的意义并且可以和外部直接进行交互。
Entity 实体
不能独立存在的业务对象,必须挂在聚合根上。
ValueObject 值对象
定义:在领域中,不需要唯一键标识的对象,包括:
常见的值对象:
字符串常量;
枚举;
无主键约束的引用对象;
如果有两个Customer的地址信息是一样的,我们就会认为这两个Customer的地址是同一个。也就是说只要地址信息一样,我们就认为是同一个地址Address。
Domain Service 领域服务
领域中的一些概念不太适合建模为对象,即归类到实体对象或值对象,因为它们本质上就是一些操作,一些动作,而不是事物。这些操作或动作往往会涉及到多个领域对象。
领域服务一个很重要的功能就是可以避免领域逻辑泄露到应用层。
Domain Event 领域事件
容易降低耦合,方便做到高扩展性;
领域聚合根之间很难做到强一致性,大多数都是最终一致性;
Infrastructure 基础设施层
本层为其他层提供通用的技术能力;提供了层间的通信;为领域层实现持久化机制;总之,基础设施层可以通过架构和框架来支持其他层的技术需求;
三、案例分析
那些是聚合、聚合根、实体、值对象?
注意
开发人员/团队需要和产品团队/客户保持充分的沟通。
如何领域驱动设计?-实践感悟&总结分享的更多相关文章
- (转)EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- EntityFramework之领域驱动设计实践
EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领 ...
- .NET应用架构设计—面向查询的领域驱动设计实践(调整传统三层架构,外加维护型的业务开关)
阅读目录: 1.背景介绍 2.在业务层中加入核心领域模型(引入DomainModel,让逻辑.数据有家可归,变成一个完整的业务对象) 3.统一协调层Application Layer(加入协调层来转换 ...
- 【DDD】领域驱动设计实践 —— UI层实现
前面几篇blog主要介绍了DDD落地架构及业务建模战术,后续几篇blog会在此基础上,讲解具体的架构实现,通过完整代码demo的形式,更好地将DDD的落地方案呈现出来.本文是架构实现讲解的第一篇,主要 ...
- [转]EntityFramework之领域驱动设计实践
本文转自:http://www.cnblogs.com/daxnet/archive/2010/11/02/1867392.html Entity Framework之领域驱动设计实践 EntityF ...
- .NET领域驱动设计—实践(穿过迷雾走向光明)
阅读目录 开篇介绍 1.1示例介绍 (OnlineExamination在线考试系统介绍) 1.2分析.建模 (对真实业务进行分析.模型化) 1.2.1 用例分析 (提取系统的所有功能需求) 1.3系 ...
- [转] .NET领域驱动设计—实践(穿过迷雾走向光明)
阅读目录 开篇介绍 1.1示例介绍 (OnlineExamination在线考试系统介绍) 1.2分析.建模 (对真实业务进行分析.模型化) 1.2.1 用例分析 (提取系统的所有功能需求) 1.3系 ...
- 【DDD】领域驱动设计实践 —— 业务建模小招数
本文结合团队在ECO(社区服务系统)业务建模过程中的实践经验,总结得到一些DDD业务建模的小招数,不一定是完美的,但是对我们团队来说很有效用,希望能帮到其他人.后面会陆续将项目中业务建模的一些经典例子 ...
- 【DDD】领域驱动设计实践 —— 业务建模战术
本文结合团队在COMMUNITY(社区服务系统)业务建模过程中的实践经验,总结得到一些DDD业务建模的小招数,不一定是完美的,但是对我们团队来说很有效用,希望能帮到其他人.后面会陆续将项目中业务建模的 ...
- 【DDD】领域驱动设计实践 —— 架构风格及架构实例
概述 DDD为复杂软件的设计提供了指导思想,其将易发生变化的业务核心域放置在限定上下文中,在确保核心域一致性和内聚性的基础上,DDD可以被多种语言和多种技术框架实现,具体的框架实现需要根据实际的业务场 ...
随机推荐
- vue.js路由学习笔记
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- [JavaScript] New-Agnostic Constructor Pattern
function User (name, password) { var self = this instanceof User ? this : new User(); if (name != nu ...
- JTAG与JLink说明
JTAG接口解读 通常所说的JTAG大致分两类,一类用于测试芯片的电气特性,检测芯片是否有问题:一类用于Debug:一般支持JTAG的CPU内都包含了这两个模块. 一个含有JTAG Debug接口模块 ...
- day_04 列表
1. 列表list 能装对象的对象,有序的(按照我们存放的顺序) 以[]表示,里面可以存放大量各种元素,各个元组用逗号隔开 列表也具有索引和切片 2. 列表的增改删查 1. 增 1.append() ...
- linux 中iscsi服务
###############第一步: 创建一个2G的分区第二步: yum install targetcli -y 第三步:创建一个2G的分区,并同步 第四步: 执行tagetclils查看 ...
- javascript中对两个对象进行排序 和 java中的两个对象排序
javascript中的对象数组排序 一 定义一个对象数组 var text = [{"name":"张","age":24},{" ...
- spring AOP正则表达式的几个问题
基于包名的正则表达式,是根据抽象父类的包名过滤,还是实现类的包名过滤, 还是抽象父类实现的接口的包名过滤? org.springframework.aop.aspectj.AspectJExpress ...
- 报错:The valid characters are defined in RFC 7230 and RFC 3986
访问 spring boot controller时,报错:The valid characters are defined in RFC 7230 and RFC 3986 1.特殊符号 @Spri ...
- vue(3)IDE
使用vscode,下载:https://code.visualstudio.com/Download 1.安装vscode 2.安装插件 方式一:https://marketplace.visuals ...
- Android官方架构组件介绍之LiveData(二)
LiveData LiveData是一个用于持有数据并支持数据可被监听(观察).和传统的观察者模式中的被观察者不一样,LiveData是一个生命周期感知组件,因此观察者可以指定某一个LifeCycle ...