如何领域驱动设计?-实践感悟&总结分享
主要是在开发过程中,个人对于领域驱动设计的实践感悟和总结;也是对新进开发人员的培训资料;希望对关注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可以被多种语言和多种技术框架实现,具体的框架实现需要根据实际的业务场 ...
随机推荐
- Es6中Map对象和Set对象的介绍及应用
map和set的方法,工作中有使用到,所以学习一下: Map 对象 Map 对象保存键值对.任何值(对象或者原始值) 都可以作为一个键或一个值. var myMap = new Map(); myMa ...
- css3文本域焦点烟花效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [USACO19FEB]Moorio Kart(DP)
Luogu5243 题解 即O(N^2)暴力统计出每个森林的路径,从ctgn个集合中各选出一个数,使得长度>=Y的方案数. 用背包统计.具体实现: \(dp[i+j][0]\leftarrow ...
- Luogu P1120 小木棍 [数据加强版] 来来来我们一起来剪枝,剪枝,剪枝、、、
好啊...太棒了... dfs(拼到第几根木棍,这根木棍剩余长度,上一根木棍的位置) len是木棍的长度,cnt是木棍的个数 震撼人心的剪枝: 1.枚举长度从最大的木棍开始,直到sum/2,因为之后只 ...
- POJ1185炮兵阵地(状态压缩DP)
POJ飞翔.数据弱 ZQOJ飞翔 数据强 Description 司令部的将军们打算在N×M的网格地图上部署他们的炮兵部队.一个N×M的地图由N行M列组成,地图的每一格可能是山地(用"H&q ...
- linux mysql下载地址
linux mysql下载地址: https://dev.mysql.com/downloads/mysql/5.7.html#downloads
- STL之vector(不定长数组)
vector就是一个不定长数组,另外它把一些常用操作“封装”在了vector类型内部.例如,若a是一个vector,可以用a.size()读取它的大小,a.resize()改变大小,a.push_ba ...
- Python 类 面向对象(Classes)
Python 支持面向对象 class Greeter(object): #构造函数 def __init__(self,name): self.name = name # 创建一个实例变量 #定义一 ...
- 使用Myeclipse导入IDEA项目
问题描述:使用Myeclipse导入IDEA创建的Web项目,成功导入,但是显示的是一个普通的JAVA项目,无法加载到tomcat下. 解决方案:右键项目Properties,选择Myeclipse- ...
- 性能测试工具LoadRunner01-性能测试基础
什么是性能测试? 在一定的约束条件下(指定的软件.硬件.网络环境等)对产品按一定的性能指标进行测试,确定系统能承受的最大负载压力,解决性能瓶颈.给用户最好的体验. 性能测试流程? 什么时候开始性能测试 ...