IDDD 实现领域驱动设计-理解领域和子域
上一篇:《IDDD 实现领域驱动设计-一个简单业务用例的回顾和理解》
在《实现领域驱动设计》第二章的前半部分内容中,提到领域和子域的概念,并且作者把这两者又进行了细致的区分,其实在《领域驱动设计》书中,也有进行详细说明,只不过是在第十五章《精炼》中,章节比较靠后,我先是读了《实现领域驱动设计》这部分的内容,但读完之后,完全没有任何的感觉,或者说我自己和作者没有产生一些共鸣,也记不起来自己到底读了什么内容,但是在读《领域驱动设计》对应这部分内容的时候,我觉得有些内容是我想要的,也产生了一些共鸣,这让我对之前短消息项目也有了一些新的思考,我觉得还是蛮有价值的,下面是自己的一些理解。
一张很重要的图,引自:《实现领域驱动设计》
Domain 领域
首先,领域(Domain)不是领域模型(Domain Model),不要把他们两个画等号,从字面上进行理解,“领”的意思,可以理解为领土、领地或属于的某一区域,但不管它包含的是什么,它总是有一个界限,也就是说这个界限要进行明确,如果不进行明确,就会产生一些麻烦,比如“领地纠纷”等等,这个界限其实就可以看作是“领”的意思,“域”的意思,就是一个方面的具体称谓,加上“领”,领域的意思,其实就是明确某一方面的称谓。可能有点晕,我们开发某一套业务系统,比如快递行业的业务系统,那么这个快递业务系统之内的所有业务都包含在领域中,这个领域称之为快递业务领域,其中可能有很多的子领域,或者是业务模块,但都属于这个领域之内,如果超出这个领域之外,那么业务模块将不包含在快递业务领域之内了。在上一篇中有说到领域专家,其实,就是对某一领域精通的人,关键词是某一领域,而不是所有领域,强调的是界限的重要性。
从上面图中可以看出,业务领域中所有东西构成了这个业务的领域概念,也就是说它是唯一的,你开发什么业务系统,首先需要明确的是,你业务系统的领域是什么?如果连这个都确定不了,那么领域驱动设计也就没有再进行下去的必要了。让我自己来考验自己一下,之前开发的消息项目(MessageManager),这个消息项目的领域是什么?我想你应该会和我一样,脑海中首先想到的应该就是消息领域(Message Domain),其实我觉得这个答案没什么问题,消息项目不围绕消息领域开展,那围绕什么开展呢,你可能会有一些疑问,比如消息项目中会有一些用户模块,用户模块不应该属于用户领域吗?如果消息项目只有一个消息领域,那它们俩不相违背吗?其实这个答案,可以从上面的图中找到,消息领域是一个大的概念,它包含了这个消息项目中所有的业务领域概念,消息项目中的用户模块,只不过是消息领域的内部的一部分而已,不要被消息领域中的“消息”字眼所迷惑。
对于开发者来说,理解领域的概念是有一些歧异的,比如消息领域,我们开发者该怎么去描述它,或者表达它呢?我想你应该和我一样,首先,新建一个 Message.Domain 类库项目,然后把所有的业务操作都在这个类库中进行实现,实现完成之后,你告诉领域专家,说这个 Message.Domain 项目就是消息领域,仔细一想,好像也确实有些道理,对于开发者来说,消息领域的表达就是项目代码的实现,这样做也无可厚非。但是,有一点非常重要,在消息领域确定的过程中,不是只有开发人员的参与,最重要的还要有领域专家的参与和讨论,其实,对消息领域的最理解的人,不是开发者自己,而是领域专家,消息领域的表达也不只是代码表现这么简单,而是之前提到的通用语言,消息领域在开发者和领域专家之间的传递和确定,这个介质其实就是通用语言,之前有说到通用语言是开发者和领域专家共同创建的,它的表现形式可以是一个白板,也可以是一堆文件,又或者是一个项目代码等等,但不论是什么东西,它能在开发者和领域专家正确传递领域所包含的业务概念即可。
在上面图中,领域中有一个核心域(Core Domain)的概念,核心域是什么?它是领域中最重要的一块,你可以把它看作是人体中的心脏,也就是说是最核心的东西,开发者和领域专家花费最多的精力都是在它上面,一个业务系统一般有且只有一个核心域,但是一般核心域的精炼工作是需要花费很多的时间和精力,而且也很容易出错,如果业务系统中核心域的精炼出现了问题,那么这个业务系统注定是失败的,因为当一个核心域确定下来之后,开发者和领域专家剩余的工作,都是围绕着核心域进行展开的,比如一个人得了心脏病,而医生在诊断的时候,却认为是肝脏出了问题,然后他就对这个病人的肝脏做了手术,可想而知后果会怎样。。。这个看似简单的问题,但其实中间也蕴含了一些重要东西,首先,我们可以把它抽离出来,有三个人物:病人、诊断医生和手术医生,再想一下,我们业务系统开发,也有三个重要对象:业务系统、领域专家和开发者,然后,你再对它们进行对比下,就可以得出一些东西了,诊断医生是最了解病人的,由他来确定病人得了什么病,就好比领域专家把业务系统的核心域精炼出来,手术医生只不是实施者,用的是手术刀,而开发者用的是代码,但和看病不一样的是,核心域的精炼是领域专家和开发者共同探讨决定的,这就避免了诊断医生和手术医生所产生一些不必要的“冲突”,说了这么多,总而言之,核心域的精炼很重要,需要领域专家和开发者共同参与。
回到我们的消息领域上,那在消息领域中,核心域是什么呢?我的个人想法是发消息业务操作,这是消息领域中最重要的一个业务操作,消息的存在就是为了传递信息,在现实生活中,对于消息相类似的就是寄信,对于写信的我来说,我其实就是寄信的领域专家,为什么?因为我自己就是用户,对于寄信用户来说,我写信的目的就是让收件人可以收到我的信,具体这封信是怎么寄出去的,公路、铁路、飞机等等,这些我都不关心,我只关心的是现在这封信有没有到收件人手里。按照这个思路进行理解,对于消息领域来说,领域专家所能描述出来的核心域描述就是:发消息,这个和之前我们提到的待定项提交到冲刺一样,最简单的业务描述就是这样,至于消息发送限制、或者发送之后要不要邮件通知,这都是发消息具体的内部实现,对于消息领域以后的业务变化来说,变的也只是核心域的内部而已,我们只需要改变具体的实现就可以了,有点以不变应万变的意思,不变的是核心域,变的是核心域的内部实现。
描述这么多,可能有点晕,只需要记住两个概念就可以了,领域和核心域,具体的深入理解,只有运用后才可以真正体会到。
SubDomain 子域
什么是子域(SubDomain)呢?理解子域的概念,必须和核心域对应起来,子域也是领域的一部分,只不过它的重要性没有核心域那么大,它们之间的关系,你可以看作是人体器官中,心脏和其他器官的关系,在《领域驱动设计》中,其实并没有子域的概念,而是通用子域(Common Subdomain),而在《实现领域驱动设计》中,作者把子域拆分成了支撑子域(Generic Subdomain)和通用子域(Common Subdomain)。对于领域来说,除了核心域,用来支撑核心域的子域,就可以称之为支撑子域,在整个领域中,可以被公用的子域,称之为通用子域,通用子域还有一个理解是,在某一个业务领域中,它可能是被看作是通用领域,但是在另外一个业务领域中,它可能就被看作是核心域了,举个例子,比如在团购业务系统中,地图服务可能就被看作是通用领域,而对于地图服务商来说,毫无疑问,地图服务将是他们的核心域。
这些概念性的东西可能理解起来很费劲,我们再回到消息领域中,在上面分析中,我们已经确定了“发消息”是核心域,插一句,有人说,那回复消息是什么啊?难道有两个核心域?其实发消息就包含回复消息,因为回复消息也是发消息的一种信息,回到正题上,我们在消息领域中精炼一下支撑子域和通用子域,我现在可以想到的就是消息验证服务领域,就是在发消息之前对发件人、收件人、以及对消息内容进行验证,就好比你去邮局寄一封信,工作人员需要验证一下收发件地址一样,消息验证服务领域用来支撑发消息核心域,所以可以把它单独精炼出来进行探讨,还有就是,对于支撑子域来说,在整个领域中,可能会有多个,但大部分都是围绕核心域进行展开的,这也就是“支撑”的具体含义吧,说到这,我现在脑子里面有闪现一个,那就是消息发送之后的通知服务,这个也可以看作是支撑子域,需要记住的是,支撑子域虽然没有核心域那么重要,但它也是领域的一种,也是非常重要的,不要完全忽略它。
说了支撑子域,再来分析一下,消息领域中的通用子域,其实就是用户领域,用户的概念会贯穿整个消息领域,因为一切都是用户进行操作完成相关业务,用户领域的概念其实和上面说到的地图服务领域是一样的,在用户业务系统中,用户领域就不是通用子域了,而是核心域,对于非用户业务系统来说,用户领域在其他业务系统中,都可以被看作是通用子域。可能还有一点内容容易造成误解,就是消息领域中,“用户”的概念是很重要的,发消息是用户进行发送,那用户领域是不是应该被看作是核心域呢?我记得当时在开发消息项目的时候,曾经就把发消息业务操作放在了用户模型中,认为用户才能发消息啊,那如果是这样的理解思路,所有的业务系统中的业务操作,都应该是放在用户模型中,因为只有用户才能进行这些操作,但好像并不是这么回事,我们有点过于“面向对象”了,应用软件中和现实生活中的用户概念是不太一样的。
在业务领域中,对于通用子域来说,是比较容易精炼的,但是对于支撑子域来说,精炼它是有些难度的,难点就在于它和核心域的区分,有时候,我们可能会从核心域中剥离支撑子域,当然,最重要的,还是领域专家和开发者之间如何确立通用语言并与之沟通。
啰里八嗦的,就记录到这!
IDDD 实现领域驱动设计-理解领域和子域的更多相关文章
- 领域驱动设计理解&总结
领域驱动设计理解&总结 这篇文章主要是通读<实现领域驱动设计>之后自己的理解和总结(同时也参照一些博文的分析来加深自己的理解): 有些疑问是自定义内容,虽然有自己的理解,但依然感觉 ...
- DDD领域驱动设计之领域服务
1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 3.DDD领域驱动设计之领域基础设施层 什么是领域服务,DDD书中是说,有些类或者方法,放实体A也不好,放实体B ...
- 基于ABP落地领域驱动设计-04.领域服务和应用服务的最佳实践和原则
目录 系列文章 领域服务 应用服务 学习帮助 系列文章 基于ABP落地领域驱动设计-00.目录和前言 基于ABP落地领域驱动设计-01.全景图 基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践 ...
- DDD领域驱动设计之领域基础设施层
1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 其实这里说的基础设施层只是领域层的一些接口和基类而已,没有其他的如日子工具等代码,仅仅是为了说明领域层的一些基础 ...
- DDD领域驱动设计:领域事件
1 前置阅读 在阅读本文章之前,你可以先阅读: DDD领域驱动设计是什么 DDD领域驱动设计:实体.值对象.聚合根 DDD领域驱动设计:仓储 MediatR一个优秀的.NET中介者框架 2 什么是领域 ...
- [.NET领域驱动设计实战系列]专题十一:.NET 领域驱动设计实战系列总结
一.引用 其实在去年本人已经看过很多关于领域驱动设计的书籍了,包括Microsoft .NET企业级应用框架设计.领域驱动设计C# 2008实现.领域驱动设计:软件核心复杂性应对之道.实现领域驱动设计 ...
- NET 领域驱动设计实战系列总结
NET 领域驱动设计实战系列总结 一.引用 其实在去年本人已经看过很多关于领域驱动设计的书籍了,包括Microsoft .NET企业级应用框架设计.领域驱动设计C# 2008实现.领域驱动设计:软件核 ...
- 解构领域驱动设计(一):为什么DDD能够解决软件复杂性
1 为什么我要研究领域驱动设计 1.1 设计方法各样且代码无法反映设计 我大概从2017年10月份开始研究DDD,当时在一家物流信息化的公司任职架构师,研究DDD的初衷在于为团队寻找一种软件设计的方法 ...
- 如何使用ABP进行软件开发(2) 领域驱动设计和三层架构的对比
简述 上一篇简述了ABP框架中的一些基础理论,包括ABP前后端项目的分层结构,以及后端项目中涉及到的知识点,例如DTO,应用服务层,整洁架构,领域对象(如实体,聚合,值对象)等. 笔者也曾经提到,AB ...
- 基于ABP落地领域驱动设计-01.全景图
什么是领域驱动设计? 领域驱动设计(简称:DDD)是一种针对复杂需求的软件开发方法.将软件实现与不断发展的模型联系起来,专注于核心领域逻辑,而不是基础设施细节.DDD适用于复杂领域和大规模应用,而不是 ...
随机推荐
- [C#] 软硬结合第二篇——酷我音乐盒的逆天玩法
1.灵感来源: LZ是纯宅男,一天从早上8:00起一直要呆在电脑旁到晚上12:00左右吧~平时也没人来闲聊几句,刷空间暑假也没啥动态,听音乐吧...~有些确实不好听,于是就不得不打断手头的工作去点击下 ...
- Webstorm+Webpack+echarts构建个性化定制的数据可视化图表&&两个echarts详细教程(柱状图,南丁格尔图)
Webstorm+Webpack+echarts ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...
- ajax
常见的HTTP状态码状态码:200 请求成功.一般用于GET和POST方法 OK301 资源移动.所请求资源移动到新的URL,浏览器自动跳转到新的URL Moved Permanently304 未修 ...
- requests的content与text导致lxml的解析问题
title: requests的content与text导致lxml的解析问题 date: 2015-04-29 22:49:31 categories: 经验 tags: [Python,lxml, ...
- 深究标准IO的缓存
前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...
- XML技术之DOM4J解析器
由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...
- SQL Server 2016白皮书
随着SQL Server 2016正式版发布日临近,相关主要特性通过以下预览学习: Introducing Microsoft SQL Server 2016 e-bookSQL Server 201 ...
- Android 5.0 到 Android 6.0 + 的深坑之一 之 .so 动态库的适配
(原创:http://www.cnblogs.com/linguanh) 目录: 前序 一,问题描述 二,为何会如此"无情"? 三,目前存在该问题的知名SDK 四,解决方案,1 对 ...
- c#语言规范
0x00 分类 C#语言规范主要有两个来源,即我们熟知的ECMA规范和微软的规范.尽管C#的ECMA规范已经前后修订4次,但其内容仅仅到C# 2.0为止.所以慕容为了方便自己和各位方便查询,在此将常见 ...
- UWP简单示例(三):快速开发2D游戏引擎
准备 IDE:VisualStudio 2015 Language:VB.NET/C# 图形API:Win2D MSDN教程:UWP游戏开发 游戏开发涉及哪些技术? 游戏开发是一门复杂的艺术,编码方面 ...