戏说领域驱动设计(八)——边界

  我们在前面花了大手笔聊子域与限界上下文,不知道作为读者的您的感受是什么。当然了,我可不是郭德纲自己给自己叫好。您应该也发现了一个规律,此两节的内容其实都是在讲“分”:子域从业务上划小,BC从物理上进行划小。虽然说BC属于分析模型,但那东西只要一确定您可就得按这个方案进行开发了,所以说其确定了物理上的边界并无问题。既然是“分”,就使得每一个被划小的单元都有了自己的专属地盘儿或者叫势力范围。“文明”是一个很有名的策略游戏,里面每一个国家都有一个自己的界,不经允许别人是进不去的。这个界在DDD中的意义和游戏中一样,除了起到隔离的作用还能有效的解决系统复杂度。本节主打DDD中的隔离其及优点。

  DDD中的划小和隔离机制分为四层:使用子域对问题空间进行划小、使用BC对解决方案空间进行划小、通过分层技术对BC进行分块、使用“聚合”对BC中的领域模型进行分组。前两项已经仔细盘点过;第三项的概念其实就是传统三层中的概念;第四项我们后面会详细介绍,简单来说就是对领域模型进行分组,任何时候都以组为单位进行领域模型的保存、修改或删除。

1、子域隔离

  这是第一层的隔离,他的作用就是把一个偌大的领域分成多块小的,每块给予不同的优先级并据此投入不同的资源,实际上这也是一种最为节省资源的系统建议方案。一般来说IT都是成本中心不背收入的,可是胡乱花钱也会让你被老板怼。这一层次隔离的目标是业务,人、钱投入策略的隔离是一个方面;最重要的是对于领域范围的确认:哪些属于目标业务,哪些和业务无关,可以在子域设计过程中对此两者进行确认与隔离。

2、BC隔离

  BC的隔离是一种物理上的隔离。即便是单体系统中,如果遵守DDD实践标准,虽然部署的时候都在一起,但系统内部使用了比如Java中的包进行了隔离。他带来的优势我们之前也磨叨了一万多遍,至少就“易于扩展和维护”这一优势也值得你拥有。毕竟对于一个系统来说,建设上面花得钱可是没有维护花得多,又不是写“Hello, word”,一次编译部署就再不管了。这一层次的隔离事关系统前期的建设复杂度和后期的维护花销,需要花大精力研究。实际上,BC的设计过程也是您对团队进行建设的工作之一。我们之前说了,需要保证每个BC仅属于一个人或一个团队,这不就是对一个大的团队的人员和责任进行了划分了吗?您别忘了BC也是由子域推动设计的,而子域决定了资源的投入,您所做的就是对分配过来的资源做二次整合。通过BC驱动团队的划小建设是较为科学的方式,你也值得拥有。就我个人的管理经验来看,不太喜欢把高水平的多个人放在一起,容易搞事情。一般都是基于子系统进行划分,每个人负责一块,也别谁都不服谁。

3、分层隔离

  分层隔离估计您是较为熟悉的,就是三层架构中那个所谓的“层”。其主要对代码的责任进行了隔离,“责任单一”是核心标准。业务复杂度和非功能需求不同,使得每个BC的架构模式及分层方式也不同。这个层面其实也特别考验管理者的能力,因为从“层”开始,就需要建立严格的开发规范:层的名称叫什么、层间访问限制是什么、每个层的责任是什么等……。相关的规范网上也有很多,比较推荐读一下阿里的编程规范范:《阿里巴巴Java开发手册》。我在这里以三层架构为例列举一些比较常见的问题(使用Java语言),看看您或您的马仔是否有过类似的问题。

  • 把缓存的操作放到Service层:缓存一般属于持久化的责任,尽管这里的持久化是在内存中。这个问题犯了责任不清的错误。
  • A包访问B包的DAO对象:没有作好访问限制,容易产生级联问题,后续作服务的拆分问题也比较大。
  • A包的DAO访问A包的Service:依赖关系不明确,出现反向依赖的情况。
  • Spring Web类项目中的RESTful层中,写入大量业务逻辑:业务逻辑分散,严重影响后续的扩展,应集中在Service中;同理,DAO中也不得出现非数据相关的业务逻辑。

  分层架构分为两种:严格分层,上层只能依赖其直接下层;松散分层:上层可以依赖其任意下层。这两种类型中,都不应该出现下层依赖上层的情况。如果您是三层模式,请使用严格分层架构;如果是ODD架构,除Service层外,其它层也使用严格分层。

4、聚合隔离

  聚合隔离将相关的领域模型组成一个个的工作单元,每个单元间独立工作,彼此间互为黑盒。这种隔离不仅仅是数据,还包括业务的层次,也就是所谓的达到业务一致性和数据一致性,是整个隔离级别中最小的单元。设计良好的聚合让业务更聚焦,不仅是开发阶段,后续维护起来也相当的方便。修改了一个聚合通常不会影响另外的,减少级联错误的风险。很多时候一些需求的变更,对开发而言就分分钟搞定了,不过您也别过于乐观,基于聚合的开发速度比较慢,他的优势体现在后续的需求变更中,属于晚熟的汉子。在管理上,请保证一个聚合只由一个人负责。

  DDD中的四种隔离理解起来相对简单,所以使用单独一章说明是为了对应我们前面所说的DDD的目标:高内聚、低耦合,让您了解这种目标的达成并非只是简单的使用一些面向对象编程就可以搞定的,那仅仅是一种低层次的解耦。

  下一节讲解架构,敬请期待……