DDD战略设计相关核心概念的理解
前言
本文想再讨论一下关于领域、业务、业务模型、解决方案、BC、领域模型、微服务这些概念的含义和关系。初衷是我发现现在DDD领域建模以及解决方案落地过程中,常常对这些概念理解不清楚或者有歧义,导致我们不知道如何运用这些概念来落地我们的软件。先通过一个图来说明一下这些概念之间的关系,如下图所示
领域、业务、业务模型
- 领域,即问题域、问题空间,领域是一种边界、范围。所以,一个领域代表了一个问题域的边界,也可以理解为是一个业务的边界。领域边界越大,业务范围就越大,反之则相反;通常我们大家交流都比较喜欢用业务这一词,比如这块业务,那块业务,业务的边界,我是一个业务开发人员(区分于我是一个中间件开发人员)。而领域一词,相对比较抽象,不是那么容易懂。
- 领域既然是一个边界,所以可以划分领域的大小,即领域划分,划分出来的子领域简称子域,每个子域对应一个小的问题域和和小的业务;当然,不同的子域的重要性也是不同的,所以才有了核心子域、支撑子域的说法,这点显而易见。
- 每个业务都有一个对应的业务模型(注意这个业务模型不是领域模型,而是一个业务概念的模型,领域模型下面会提到),这个业务模型设计的时候,完全不需要考虑任何软件设计的思想,比如对象的抽象、继承、存储、性能,等。我们是从业务本身出发,分析业务边界范围内的各种业务概念,以及业务概念之间的关系,通常我们可以使用一个业务模型的图来表达这些业务概念以及业务概念之间的关系。那么如何得到一个业务模型呢?最常见的有名词动词形容词分析法,还有比如四色原型分析法,都可以。找一个适合自己的就行;业务模型本身非常有价值,它提炼了领域内业务的核心概念及其关系,可以帮助我们更好的理解业务本身。
解决方案
- 什么是解决方案?我们在进行DDD领域驱动设计的实践时,会进行需求分析、领域划分、领域建模等工作。而我们的系统要落地,则需要有一套解决方案。例如,我们要实现一个电商平台,需要一个复杂的系统解决方案,但是如果这个解决方案过大,各模块、组件都揉在一起,那么就不利于整个系统的维护、演进、伸缩,等。所以,我们需要把解决方案拆分为一个个独立的小的解决方案;所以,我们可以发现,领域和解决方案,是两个完全不同的概念,领域代表问题空间,解决方案代表解决方案空间。
- 解决方案该如何拆分呢?简单的回答是:看情况,凭经验。说的具体点,就是我们需要使用软件设计的各种原则、最佳实践、设计模式、非功能特性的需求,以及团队成员的情况来指导我们进行解决方案的拆分或者直接不拆分,最终得出一个综合考虑后的拆分结果。所以,我们发现解决方案的拆分的维度可能有很多,没有一个单一的在任何情况下都合理的切分维度。有时我们可能从性能的角度来拆分,有时从不同架构分开演进(如CQRS架构)的角度,有时从分开伸缩的角度,有时从切合团队组织架构的维度。但是拆分的时候,多考虑一些各个因素,才能让我们更好的进行解决方案空间的拆分。
BC
- BC,即Bounded Context,中文翻译为限界上下文。BC在DDD一书中首次出现,BC的理解分为两个层面:1)Bounded,表示边界的意思;2)Context,即上下文,我理解为是一个场景的上下文,这个场景不局限于普通的业务场景,而是各种上下文都涵盖在内,是一个时空感知的概念。比如我们两个人在公司交谈时的上下文是一个上下文,但是在路上交谈时,则切换到另一个上下文了,因为交谈的地点发生了变化;所以,BC合起来理解,就是一个上下文的边界。
- BC有什么用呢?就是为了表达上面介绍的某个粒度的解决方案的上下文边界。那为何要强调这个边界呢?有了这个边界,我们才可以定义这个边界内的领域模型中所有对象概念的明确含义。如果没有这个上下文边界,对同一概念在不同上下文的理解,大家就会产生偏差。举个栗子:商品,在商品中心的解决方案BC中,商品中心负责管理电商平台的所有商品,所以商品在商品中心BC中,是一个聚合根;但是在订单中心解决方案BC中,虽然也叫商品,但是它只是一个值对象。我们知道订单中心的订单是一个聚合,订单内聚合了多条订单明细,每个明细是一个实体,每个订单明细对应了一个商品。虽然叫做商品,但是这个商品本质上只是商品中心的商品的一部分信息,如商品ID、标题、价格,且是只读的。甚至更为常见的,叫同一个名称的对象,在不同的BC中,是属性完全不一样的不同的对象。
- 那为何解决方案的边界要叫做BC呢?对,我们可以不用叫做BC,比如你就叫做解决方案边界,也没问题。只是Eric在写作DDD这本书时,把他叫做BC,所以我们沿用了他的概念。我们主要的目的是为了用BC来表达解决方案空间的边界。
- BC和子域的关系?没有关系。因为它们是不同的东西被划分后的产物,对解决方案空间进行划分产生了BC,对领域划分后产生了子域。而且它们划分的依据也不同,所以必定会出现BC与子域的关系是1对1,1对多,多对1的各种可能性。注意,我说的是被划分后的产物,所以这个产物叫什么其实不重要,我们真正要学会的是划分的原则、依据、经验,有了这些,我们才能合理地划分BC和子域。
领域模型
- 什么是领域模型?这里讨论的领域模型是指DDD一书中提到的领域模型,领域模型是DDD软件设计方法论中的核心概念,它是业务分析、软件设计的综合结果,是一个系统设计模型。领域模型存在于某个粒度解决方案空间里。所以,任何一个领域模型,都是在特定的BC边界内才有意义;
- 领域模型和业务模型的区别:我觉得领域模型有一个引起人们误会的地方,就是它的名称。很多人容易把领域模型理解为上面提到的业务模型,因为领域容易联系到业务,所以领域模型就是业务模型,比如非常著名的一本书《UML和模式应用》中,就认为领域模型是需求分析阶段的业务模型,是一种业务概念实体的模型。实际上两者是不同的,因为业务模型是对业务概念及其关系的表达,而领域模型在业务模型的基础上,用OOA/D的思想进行进一步精炼和抽象的对象关系模型,而且领域模型中有聚合、实体、值对象的区分。举亮个栗子:1)业务模型中,我们可能会有买家、卖家、读者、教师的业务概念,但是在领域模型中,我们已经把这些概念抽象为了账号这个模型。2)再比如一个读者持借书卡去图书馆借书这个场景,在业务模型中会存在一个借书卡的业务概念,而在领域模型中,我们很可能会去掉借书卡,因为它只是一个借书的工具,是借书系统用来识别读者的一个工具,系统真的的目的是为了知道哪个账号在借书,而不关心如何识别出这个账号。如果我们有一个网上借书系统,那就不需要借书卡了,而是要提供账号登录功能。在DDD一书中,作者一步到位直接根据需求设计出领域模型,在提炼需求分析需求的过程中直接应用软件设计思想和抽象思维一步到位产出领域模型,我个人觉得是有点快的,更好的做法应该是先分析出业务模型,再对业务模型进行精炼,得到领域模型;
- 既然领域模型存在于某个粒度的解决方案空间中,而这个粒度的解决方案空间可能会对应多个子域。所以,这个领域模型则基于多个子域的业务模型结合起来推导出来的一个系统模型。同理,同一个子域内也可能有多个解决方案空间,既有多个BC,每个BC内有一个领域模型;
- 那如何进行领域建模得到领域模型呢?这个就比较复杂了,不过经过前面的讨论,大致分为两个大的阶段:1)先得到业务模型;2)再对业务模型进行模型精炼;如何精炼?运用软件设计思想和原则,以及归纳演绎的抽象思维;所以,领域建模归根结底也是要“看情况,凭经验”,是不是很沮丧:)
微服务
最近几年,微服务开始流行起来,把DDD也带火了一把。那为何微服务的流行会让DDD也火起来呢?是因为微服务需要划分,而DDD中的BC的概念,大家发现正好可以和微服务的边界完全契合。比如都是对解决方案空间进行划分,都按照各种软件设计思想和原则进行划分,都提倡零共享。不过,DDD中实际上对BC的描述没有太多,尤其是如何得到BC这块没有展开。可能这块对大师来说是自然而然的事情,不需要过多介绍吧。
概念总结
- 领域=问题域=问题空间=业务边界
- 每个粒度的问题域都会推导出一个业务模型
- 领域拆分、业务建模,是需求分析阶段该做的事情
- 解决方案的边界即BC,解决方案可拆分
- 每个粒度的解决方案都会推导出一个领域模型
- 解决方案拆分、领域建模,是软件设计阶段该做的事情
- BC边界即微服务边界,不同BC内的解决方案的架构可以是不同的,也即每个微服务的架构可以不同
DDD战略设计相关核心概念的理解的更多相关文章
- 领域驱动设计(DDD)部分核心概念的个人理解
领域驱动设计(DDD)是一种基于模型驱动的软件设计方式.它以领域为核心,分析领域中的问题,通过建立一个领域模型来有效的解决领域中的核心的复杂问题.Eric Ivans为领域驱动设计提出了大量的最佳实践 ...
- 领域驱动设计(DDD)部分核心概念的个人理解(转)
领域驱动设计(DDD)是一种基于模型驱动的软件设计方式.它以领域为核心,分析领域中的问题,通过建立一个领域模型来有效的解决领域中的核心的复杂问题.Eric Ivans为领域驱动设计提出了大量的最佳实践 ...
- 理解maven的核心概念
原文出处:http://www.cnblogs.com/holbrook/archive/2012/12/24/2830519.html 好久没进行java方面的开发了,最近又完成了一个java相关的 ...
- Maven(三)理解Maven核心概念
转载自: http://www.cnblogs.com/holbrook/archive/2012/12/24/2830519.html 本文以类图的方式,介绍maven核心的12个概念以及相互之间的 ...
- 后端技术杂谈11:十分钟理解Kubernetes核心概念
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 本文转自 https://github.com/h2pl/Java-Tutorial 喜欢的 ...
- 十分钟带你理解Kubernetes核心概念
什么是Kubernetes? Kubernetes(k8s)是自动化容器操作的开源平台,这些操作包括部署,调度和节点集群间扩展.如果你曾经用过Docker容器技术部署容器,那么可以将Docker看成K ...
- JBPM4.4_核心概念与相关API
1. 核心概念与相关API(Service API) 1.1. 概念:Process definition, process instance , execution 1.1.1. Process ...
- 消息中间件——RabbitMQ(六)理解Exchange交换机核心概念!
前言 来了解RabbitMQ一个重要的概念:Exchange交换机 1. Exchange概念 Exchange:接收消息,并根据路由键转发消息所绑定的队列. 蓝色框:客户端发送消息至交换机,通过路由 ...
- 深入理解Vue组件3大核心概念
摘要: 搞懂Vue组件! 作者:浪里行舟 原文:详解vue组件三大核心概念 Fundebug经授权转载,版权归原作者所有. 前言 本文主要介绍属性.事件和插槽这三个vue基础概念.使用方法及其容易被忽 ...
随机推荐
- Honey Heist
5092: Honey Heist 时间限制: 1 Sec 内存限制: 128 MB 题目描述 0x67 is a scout ant searching for food and discover ...
- POSTMAN编写文档
第一步:创建文件夹: 同时创建全局变量: 第二步:创建分组文件夹: 第三步:添加请求: 类似正常调试,然后多了一步保存: 保存: 请求方式发生相应变化,同时颜色也发生变化,说明保存成功: ====== ...
- django学习之- simple_tag
如何将前端的数据直接通过python模块进行渲染,使用django的simple_tag功能,如下 django后端编写: 1:在对应的app目录下创建目录:templatetags 2:在templ ...
- P1540 机器翻译(STL 链表)
题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先 ...
- BZOJ1017魔兽地图DotR 樹形DP
@(BZOJ)[樹形DP, 三維DP] Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA ...
- flask如何处理并发
1.使用自身服务器的多进程或者多线程,参考werkzeug的run_simple函数的入参.注意,进程和线程不能同时开启 2.使用gunicorn使用多进程,-w worker 进程数,类型于运行多个 ...
- Cg入门8:Vertex Shader - 更好的数据组织方式struct
数据结构的使用:与C语言语法一样 參数的传递:參数匹配的是映射的语义的类型 输入输出:採用结构体,输入输出相应的參数的in和out可省略.函数的參数结构体就是输入參数集,函数的返回结构体就是输出參数集 ...
- SpringBoot学习之快速入门创建
maven构建项目 1.访问http://start.spring.io/,进入快速创建工程的主页 可参考下图所示: 2.选择构建工具Maven Project.Spring Boot版本1.3.6以 ...
- 聊聊高并发(二十四)解析java.util.concurrent各个组件(六) 深入理解AQS(四)
近期总体过了下AQS的结构.也在网上看了一些讲AQS的文章,大部分的文章都是泛泛而谈.又一次看了下AQS的代码,把一些新的要点拿出来说一说. AQS是一个管程.提供了一个主要的同步器的能力,包括了一个 ...
- 【手势交互】4. Kinect for XBox
"You are the Controller",Kinect for Xbox的广告词.明白说明了Kinect体感的交互方式.作为一款集成了诸多先进视觉技术的自然交互设备,Kin ...