浅析 DDD 领域驱动设计(2)

简介: 浅析 DDD 领域驱动设计

六、领域模型(domain model)


领域模型是对领域内的概念类或现实世界中对象的可视化表示。又称概念模型、业务对象模型、领域对象模型、分析对象模型。

image.png



它专注于分析问题领域本身,发掘重要的业务领域概念,并建立业务领域概念之间的关系。


优点是系统层次结构清楚,各层之间单向依赖, Client -> (Business Facade) -> Business Logic -> Data Access Object 可见,领域对象几乎只做传输介质的用处,不会影响到层次的划分。


领域对象只是作为保存状态或者传递状态使用,它是没有生命的,只是数据没有行为的对象不是真正的对象。


七、贫血模型


贫血模型是指领域对象里只有 get 和 set 方法(一般是指POJO),所有的业务逻辑是不包含在这里面的而是放在 Business Logic层。


在使用Spring的时候,通常就暗示着我们使用的是贫血模型,我们把Domain类用来单纯地储存数据,Spring管不着这些类的注入和管理,Spring关心的逻辑层(比如单例的被池化了的Business Logic层) 可以被设计成Singleton的Bean。


假设我们这里改变一下,就在Domain类中提供业务逻辑方法,那么我们在使用Spring构造这样的数据Bean的时候会遇到很多麻烦,比如 Bean之间的引用,可能引起大范围的Bean之间的潜逃构造器的调用。


八、充血模型


大多业务逻辑和持久化放在Domain Object 里面,Business Logic只是简单封装部分业务逻辑以及控制事务、权限等,这样层次结构就变成 Client -> (Business Facade) -> Business Logic -> Domain Object -> Data Access Object。


image.png


优点:


是面向对象,Business Logic 符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重。


缺点


如何划分业务逻辑,什么样的逻辑应该放在 Domain Object中,什么样的业务逻辑应该放在Business Logic中,其实是比较模糊的。


即使划分好了业务逻辑,由于分散在Business Logic和Domain Object层中,不能更好的划分模块开发。


熟悉业务逻辑的开发人员需要渗透到Domain Logic中去,而在Domain Logic又包含了持久化,对于开发者者这是十分混乱的。


如果Business Logic要控制事务并且为上层提供一个统一的服务调用入口点,它就必须把在Domain logic里实现的业务逻辑全部重新包装一遍,完全属于重复劳动。


使用RoR开发时,每一个领域模型对象都可以具备自己的基础业务方法,通常满足充血模型的开发,充血模型更适合复杂业务逻辑的设计开发。


充血模型的层次和模块的划分是一门学问,对开发人员要求也比较高,可以考虑定义这样的一些规则:

(1) 事务控制不要放在领取模型的对象中实现,可以放在facade中完成。

(2) 领域模型对象中只保留该模型驱动的一般方法,对于业务特征明显的特异场景方法调用放在facade中完成。


九、传统的数据驱动开发模式


View、Service、Dao 这种三层模式,开发者会很自然的写出过程式代码,这种开发方式中的对象只是数据载体,而没有行为,是一种贫血对象模型,以数据为中心,以数据库ER图为设计驱动,分层架构在这种开发模式下可以认为是数据处理和实现的过程。


十、限界上下文(Bounded Context)


限界上下文:定义了每个模型的应用范围


一个业务领域可以划分成多个BC,它们之间通过Context Map进行集成。BC是一个显式的边界,领域模型Bianc便存在于这个边界之内。领域模型是关于某个特定业务员领域的软件模型,通常,领域模型通过对象模型来实现,这些对象同时包含了数据和行为,并且表达了准确的业务含义。


关于限界上下文,有一个很形象的类别,细胞和细胞膜的类比:


细胞之所以能存在,是因为细胞膜定义了什么在细胞内,什么在细胞外,而且确认了什么物质可以通过细胞膜


BC可以类比为细胞膜,大型系统由于其复杂性,对于一个对象如果采取统一建模方式,可能会产生不可预测的效果。例如书中提到的客户发票中的收费对象故障,其实类似问题也在很多地方可以看到。


十一、什么是 CQRS?


CQRS —— Command Query Responsibility Segreation(命令查询职责分离),故名思义是将 command 与 query 分离的一种模式。这种命令与查询的分离方式,可以更好地控制请求者的操作。查询操作不会造成数据的修改,因而它属于一种幂等操作,可以反复地发起,而不用担心会对系统造成影响。基于这种特性,我们还可以为其提供缓存,从而改进查询的性能。


query很好理解,就是我们经常使用到的查询。


那么 command 又是什么呢,我们可以看 CRUD,其实可以分为读(R)和写(CUD),大部分情况就是一个方法要么是执行一个Command完成一个动作,要么就是查询返回数据,比如我们回答问题的人不应该去修改问题。


只要充分理解了运用CQRS模式的意图,理解CQRS模式就变得容易了许多。下图是CQRS框架AxonFramework官方文档给出的CQRS架构图。



十二、统一语言(Ubiquitous Language)


业务人员和我们使用一样的语言,我们的程序比如让业务尽量集中在领域里,比如在传统的数据驱动里,如果说 张三喜欢李四,我们一般会这么写


UserService.Love(zhangsan, lisi)

但是我们业务人员很奇怪谁Love谁? 为什么要UserService?, 如果我们写成下面这样


zhangsan.Love(lisi)

如果我们用


Company.hire(employee)

来替代

companyservice.hire(company,employee)

这样我们就更容易让业务人员参与进来,而且代码可以更易于表示真实的业务场景。


image.png


以上是根据课堂笔记来记录的,如果有错误或者不懂的地方,欢迎大家在下面留言。


我是牧小农,怕什么真理无穷,进一步有进一步的欢喜!



目录
相关文章
|
存储 自然语言处理 前端开发
领域驱动设计(DDD)-基础思想
一、序言     领域驱动设计是一种解决业务复杂性的设计思想,不是一种标准规则的解决方法。在领域驱动设计理念上,各路大侠的观点也是各有不同,能力有限、欢迎留言讨论。 二、领域驱动设计 DDD是什么 wiki释义:     领域驱动设计(英语:Domain-driven design,缩写 DDD)是一种通过将实现连接到持续进化的模型[1]来满足复杂
7536 0
|
6月前
|
消息中间件 测试技术 领域建模
DDD - 一文读懂DDD领域驱动设计
DDD - 一文读懂DDD领域驱动设计
10482 3
|
消息中间件 开发者
DDD领域驱动设计实战(六)-领域服务(上)
DDD领域驱动设计实战(六)-领域服务
456 0
DDD领域驱动设计实战(六)-领域服务(上)
|
消息中间件 架构师 搜索推荐
DDD领域驱动设计的概念解析
DDD领域驱动设计的概念解析
237 0
|
存储 设计模式 前端开发
浅析 DDD 领域驱动设计(1)
浅析 DDD 领域驱动设计
355 0
浅析 DDD 领域驱动设计(1)
|
设计模式 领域建模 数据库
DDD领域驱动设计落地实践系列:初识DDD
笔者在经历的很多项目中都使用了DDD领域驱动设计进行架构设计,尤其是在业务梳理、中台规划以及微服务划分等方面,DDD是重要的架构设计方法论,对平时的架构设计有非常好的指导作用。从本文开始笔者将通过一系列的文章阐述自己对于DDD的理解以及如何在项目实战中落地实践DDD。本文作为系列文章的开端,主要和大家聊聊DDD的一些基本概念以及常用方法。
DDD领域驱动设计落地实践系列:初识DDD
|
设计模式 SQL 测试技术
一文理解 DDD 领域驱动设计!
以一种领域专家、设计人员、开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然
一文理解 DDD 领域驱动设计!
|
安全 数据安全/隐私保护
DDD领域驱动设计实战(六)-领域服务(中)
DDD领域驱动设计实战(六)-领域服务
242 0
DDD领域驱动设计实战(六)-领域服务(中)
|
安全 Java 项目管理
DDD领域驱动设计实战(六)-领域服务(下)
DDD领域驱动设计实战(六)-领域服务
558 0
DDD领域驱动设计实战(六)-领域服务(下)
|
存储 缓存 监控
浅谈我对DDD领域驱动设计的理解
DDD的全称为Domain-driven Design,即领域驱动设计。下面我从领域、问题域、领域模型、设计、驱动这几个词语的含义和联系的角度去阐述DDD是如何融入到我们平时的软件开发初期阶段的。要理解什么是领域驱动设计,首先要理解什么是领域,什么是设计,还有驱动是什么意思,什么驱动什么。