《实现领域驱动设计》前两章内容,基本上读完了,和《领域驱动设计》不同的是,它把很多的概念都放在前面进行讲述了,比如领域精炼、界限上下文等等,在《领域驱动设计》中,是很靠后的内容,不过这样也好,可以让你从一个大局的视角去看待问题,由广到细的思路学习,我觉得也蛮好的。另外,随着一点一点的学习,你会发现,领域驱动设计越来越有意思了,有很多“新鲜”的东西等待发现。


一张很重要的图(无意间搜到),引自:《Implementing DDD Reading - Strategic Design》

战略建模(Strategic Modeling)和战术建模(Tactical Modeling)

战略建模和战术建模,其实是《实现领域驱动设计》最前面的内容,位于《如何使用本书》部分,当时看的时候并没有很注意,但在前两章的内容中,发现有很多这样的字眼:“团队有人花额外的时间去了解战术模式、团队采用的是战略模式的建模方式。。。”,这就不得不让你回过头看下,什么是战略建模和战术建模?其实,关于这两点,作者并没有很准确的进行定义,只是分别描述了这两点内容的关键字,我们来总结一下:

  • 战略建模:界限上下文(Bounded Context)、上下文映射图(Context Mapping)。
  • 战术建模:聚合(Aggregate)、实体(Entity)、值对象(Value Objects)、资源库(Repository)、领域服务(Domain Services)、领域事件(Domain Events)、模块(Modules)。

像聚合、实体、值对象等,都可以称之为战术建模的工具,战略建模和战术建模的区别,你可以从字面上进行理解,战略的意思,就是从大局出发,是一种运筹帷幄的感觉,那为什么和界限上下文有关呢?在《理解领域和子域》中,有一张很重要的图,领域是业务系统的全部,其中包含核心域、子域和通用子域,相对应的就是限界上下文,你可以把某一块的领域和限界上下文进行映射,他们都是通用语言的一种表述,在项目之初,领域专家和开发人员的工作就是探讨限界上下文的划定,这个非常重要,如果限界上下文的划定有问题,那么将来战术建模的进行将“一塌糊涂”,就像作者一个例子一样,团队成员将用户和权限限界上下文划到具体的子域中实现,最后导致了一系列的问题,后来,团队发现问题后,将用户和权限限界上下文重新定义为身份和安全限界上下文,并划分到通用子域中,最后的效果显而易见,避免了很多问题的发生,也增加了业务系统的灵活性。

如果你注意的话,会发现上面说的只是“纸面”上的探讨,也就是说都没有进行实施,所以才称之为战略建模,而战术建模可以理解为战略建模的实现,前提是界限上下文都已经划定好,并确定无误。

问题空间(Problem Space)和解决方案空间(Solution Space)

和战略建模、战术建模一样,又是一个概念性的问题,在问题空间中,我们思考的是业务所面临的问题和挑战,而在解决方案空间中,我们思考的是如何实现软件以解决这些业务挑战。

具体什么意思呢?其实,问题空间和战略建模的概念有些类似,但只是思考的方式类似,他们是两个不同的概念,在上面图中,问题空间包括两部分:业务所面临的挑战、核心域+其他子域的组合,注意其中并不包含限定上下文的划分,领域专家和开发人员在探讨领域的设计中,首先,就是对问题空间的探讨,用来确定核心域和其他子域,并列出业务系统中可能会存在的一些问题。

在上面图中,解决方案空间包含的内容很多,它是什么的解决方案?其实就是针对问题空间的解决方案,当问题空间被确定下来后,我们就会对核心域以及其他子域进行探讨和实施,然后在其中划分出很多的限界上下文,并用软件的方式进行实现。

如果这样进行思考,你会发现,问题空间和解决方案空间对应于战略建模和战术建模,他们之间是有一些相似处,比如一个是探讨、战略,一个是实施、实现,但还是有些不同,比如界限上下文是战略建模中的概念,对应与问题空间和解决方案空间,界限上下文却是解决方案空间中的的概念,可以说问题空间和解决方案空间涵盖的东西很多,像战术建模就可以看作是解决方案空间实施的一种手段。

问题空间和解决方案空间,你可以不把它看作是领域驱动设计中的概念,因为在原著《领域驱动设计》中并没有这些概念,并不是说没有就不重要,在实现领域驱动设计中,还是非常重要的,你可以把它看作是一种思考的方式,就像你切一个西瓜,横切、竖切、还是直接用拳头爆掉,这些方式都可以,不管怎么实施,只要最后能吃到西瓜就行。对于领域专家和开发人员所建立的通用语言,到底该如何沟通,或者相互直接如何表达?我觉得探讨问题空间和解决方案空间,是一个很好的方式,你可以把他们看作是切西瓜的“刀”,很锋利,也高效。

理解限界上下文(Bounded Context)

上面的四点概念,在领域驱动设计的时候,可以不必了解,因为它只是实现领域驱动设计的一种概念方式,理解它也只不过可以让你少走些弯路,你完全可以按照自己的方式去实现,当然,偏离了大道,也怨不得别人。

限界上下文的概念很重要,我之前在做消息项目的时候,不是很了解这个概念,只是隐约记得什么限定上下文、界限上下文,然后就是实体、值对象和领域服务了,其实最准确的名字是限界上下文,限的意思就是划分、规定,界就是界限、或者一个边界,上下文就是业务的整个流程,总的来说,可以称限界上下文为业务流程在一个划定的界限中,我们知道,业务的描述是通过通用语言来表述的,限界上下文和通用语言的关系就是:在一个特定的限界上下文只使用一套通用语言,并且保证它的清晰性和简洁性。

上面的图来自《实现领域驱动设计》,这个图我们可以和上一篇进行对比下,在之前的团队开发中,是把身份与访问上下文划分到协作上下文中了,并导致了一系列的问题,协作上下文包含的内容有论坛、博客、及时消息、留言板等,但这些都不是核心域,核心域是敏捷项目管理,也就是一开始说的那个简单业务用例:待定项提交到冲刺中,协作上下文只不过是支撑子域,它的作用就是用来支撑敏捷项目管理上下文的,可以这样说,如果协作上下文出现了问题,并不影响这个项目的运行,顶多是影响某一模块的运行,比如待定项提交到冲刺中,这个业务操作完成后,会有一个消息通知,协作上下文出现了问题,消息通知发不出去,但是待定项是可以提交到冲刺中的,因为这两个业务操作分别处于不同的限界上下文中,也可以这样说,对于敏捷项目管理上下文,协作上下文是可以替换的。

那限界上下文和子域有什么关系呢?在上面图中,可以看到是一一对应的,比如通用子域对应于身份与访问上下文,但其实并不是这样,请注意那个虚线,虚线表示的意思是核心域和子域的界限,但界限中很多都是空白的,比如通用子域除了包含身份与访问上下文,还可以包含消息与通知上下文、日志记录上下文等等,同样,支撑子域也是如此。

我记得我在开发消息项目的时候,在领域层只有一个 MessageManager.Domain 项目,并且项目下有很多的文件夹,比如 Entity、Domain Service 等等,然后我就认为这个 Domain 项目,是整个消息项目的核心,并且,如果我再开发一个新的项目的时候,我也会这样做,这样有什么问题呢?好像没什么问题,因为对于消息项目,业务场景很简单,Domain 项目所代表的是整个领域层,也就是上面图中整个的概念,其实这种命名是有问题的,实体、值对象和领域服务等概念,是存在于一定的限界上下文中,而不是整个领域概念,也就是说,我当时在设计 Domain 项目的时候,就完全没有把限界上下文设计好,暴露出来最明显的一个问题,就是 Domain 项目中包含有 User 实体的概念,你明白了吧,我和作者描述的那个团队开发都犯了同一个问题。

我们再来看一张图:

上面是协作上下文所包含的内容,你可以看到有好多的聚合根、领域对象等等,对于协作上下文的开发,IDDD 作者的做法是,新建一个程序集项目,也就是我们所说的类库项目,这个每个限定上下文都互不影响,而不是像我那样包含在一个 Domain 项目中,分开开发更新也方便,如果限界上下文足够复杂,比如上面的协定上下文,包含的聚合根太多,我们也可以进行细分。还有个问题是,比如用户的概念,在博客、论坛、日历等场景中,所表达的概念是不同的,那我们的身份与访问上下文该如何进行设计,还有就是协定上下文中的用户概念改如何进行设计,这是一个很重要的问题,如果是我的话,我以前肯定会把用户的概念放在协定上下文中进行开发,因为消息项目我就是这么干的,但这样造成的问题也是很严重的。

对于上面所描述的问题,我们来分析一下,不管在博客、论坛、日历等场景中,用户的概念是唯一的,也就是说它必须是唯一标识的,不能有两个同样的用户同时存在,这是首要基本条件,还有就是,用户的一些基本属性,比如用户名、邮箱、密码等等,这些在不同的场景中都是可以确定的,也都是同样存在的,对待这些共有属性,我们可以抽离出来,除了属性之外,还有一些业务操作也是公用的,比如身份验证操作,我们也同样抽离出来,对于这些抽离出来的属性和操作,我们应该在哪边进行实现?该如何实现?是在协定上下文中吗?不是,我们应该把这些用户属性和操作放在身份与访问上下文中,并进行隔离实现,为什么要进行隔离?因为身份与访问上下文是在通用子域中,也就是说并不是在支撑子域中,通用子域和核心域、其他支撑子域都有联系,也就是说,不要把协定上下文中所包含的独有用户概念,放到身份与访问上下文中进行开发,如果这样做,那么身份与访问上下文就不是通用子域了,而变成了协定上下文的一个附属上下文。

一个模型应该要与一个上下文相适应,上下文可能是指一段代码,也可能是指特定团队的工作,如果一个模型是在一次头脑风暴会议上诞生的,那么它的上下文就可能会限制在这些讨论的范围中,在有特定意义的模型中,不管模型的上下文是什么,必须要说明模型中的术语是什么意思。以上是《领域驱动设计》中,关于模型和上下文的内容,注意,上面所说的上下文并不是限界上下文,上面所说的上下文可以是一段通用语言的表述,也可以是一段代码,如果概括的话,可以认为是限界上下文的一部分。

关于限界上下文,我只是了解冰山一角,有太多的内容需要进行探讨学习,但不可否认,限界上下文是领域驱动设计中,最重要的概念之一,可以称之为最重要的首要概念,因为它是领域驱动设计的开始,自己肚里知识有限,我希望后面可以再次对这部分内容进行补充,最后,引用《领域驱动设计》中的一段描述:

  • 细胞膜不仅能把细胞内部和外部区分开来,而且还能决定通过的物质。

有人会说,你搞这么多的概念有什么用?还不如直接实践来的有用,但有时候,你会发现,实践是建立在一定基础之上的。

本文转自田园里的蟋蟀博客园博客,原文链接:http://www.cnblogs.com/xishuai/p/iddd-bounded-context.html,如需转载请自行联系原作者

IDDD 实现领域驱动设计-理解限界上下文相关推荐

  1. 「战略」访谈录 | 聊聊领域驱动设计

    相信很多朋友对领域驱动设计会有这样或那样的困惑,比如领域驱动设计是什么?它在工作中有什么作用?为什么国内关于这方面的书籍少之又少?-- 为了解决这些疑惑,有幸邀请到专家张逸老师来聊聊领域驱动设计,下面 ...

  2. DDD 领域驱动设计-如何 DDD?

    注:科比今天要退役了,我是 60 亿分之一,满腹怀念-??? 前几天看了园友的一篇文章<我眼中的领域驱动设计>,文中有段话直击痛点:有人误认为项目架构中加入 Repository,Doma ...

  3. DDD专家张逸:《解构领域驱动设计》前言

    张逸 读完需要 5 分钟 速读仅需 2 分钟 述说撰写<解构领域驱动设计>一书的心路历程,三年磨一剑的认真态度与艰辛苦楚,如今写作完毕,也算是苦尽甘来.本书将由人民邮电出版社异步图书社区出 ...

  4. 何时使用领域驱动设计

    何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了.领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architectu ...

  5. 【转载】何时使用领域驱动设计

    何时使用领域驱动设计 转载自:https://www.cnblogs.com/daxnet/p/15177443.html 何时使用领域驱动设计? 其实当你的应用程序架构设计是面向业务的时候,你已经开 ...

  6. 何时使用领域驱动设计(DDD)

    何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了.领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architectu ...

  7. 万字长文解析何时使用领域驱动设计

    何时使用领域驱动设计 转载自:https://www.cnblogs.com/daxnet/p/15177443.html 何时使用领域驱动设计? 其实当你的应用程序架构设计是面向业务的时候,你已经开 ...

  8. 【领域驱动设计】三分钟搞懂领域驱动设计

    今天的企业应用程序无疑是复杂的,并依赖一些专门技术(持久性,AJAX,Web服务等)来完成它们的工作.作为开发人员,我们倾向于关注这些技术细节是可以理解的.但事实是,一个不能解决业务需求的系统对任何人 ...

  9. 深入理解领域驱动设计中的聚合

    简介:聚合模式是 DDD 的模式结构中较为难于理解的一个,也是 DDD 学习曲线中的一个关键障碍.合理地设计聚合,能清晰地表述业务一致性,也更容易带来清晰的实现,设计不合理的聚合,甚至在设计中没有聚合 ...

  10. nvme通用驱动_对领域驱动设计的理解与实践

    领域驱动设计(Domain-Driven-Design)是一种针对大型复杂系统的领域建模与分析方法论. 2003 年,Eric Evans 发布<Domain-Driven Design: Ta ...

最新文章

  1. hive to mysql_Hive And MySQL安装及设置
  2. Oracle字符集的查看查询和Oracle字符集的设置修改
  3. BZOJ 2820 YY的GCD 莫比乌斯反演
  4. Serverless 风起云涌,为什么阿里,微软,AWS 却开始折腾 OAM?
  5. thinkphp python_ThinkPhp 5.0 服务器搭建问题总结
  6. MySQL图形化管理器——EMS SQL Management Studio
  7. @程序员,一文掌握 Web 应用中的图片优化技巧!
  8. while(pid1 = fork()== -1);直接分号,循环语句为空
  9. 【spring cloud】(四)服务网关——gateway
  10. VUE常用插件库总结
  11. 异常与调试之SEH、UEH、VEH、VCH以及SEH原理
  12. 我的世界服务器怎么制作头颅,我的世界怎么刷生物头颅 我的世界生物头颅制作方法-游侠网...
  13. mysql 增加临时表空间_数据库临时表空间设置
  14. 西湖大学鞠峰组招聘环境微生物组与抗生素耐药方向博士后
  15. 前端自学之HTML(02)
  16. (2) [保护模式]段描述符
  17. html5调整文字段落之间的距离,css设置p段落上下间距距离
  18. 程序员从初级到中级10个秘诀
  19. JAVA外部库函数_java常用库函数
  20. Lumaqq移植到Android-登录篇

热门文章

  1. flutter系列之flutter工程结构详解(android视角)
  2. 月薪30K大佬源码阅读的经验总结,干货不容错过
  3. python编程学习笔记_python学习笔记--python编程基础
  4. eclipse查看git地址_40个适用于Linux管理员和开发人员的git命令(上)
  5. java证书不见了_java – 找不到证书链
  6. 昆明钟英高中2021年高考成绩查询,昆明官渡钟英中学2021年排名
  7. arma找不到合适的模型_愉悦宝贝丨投资水育早教找不到合适品牌?那是因为你没遇到愉悦宝贝!...
  8. html中c b和b s,Web开发中B/S架构和C/S架构的区别
  9. git 移除项目版本控制_Git - .gitignore怎么忽略已经被版本控制的文件
  10. Python 爬虫经常需要睡眠防止被封IP time sleep