智商高的人怎么可能会情商低呢?只不过智商就可以解决问题,何必要用到情商呢?——良木
本章将介绍三个概念:
- 领域
- 子域
- 限界上下文
三个概念分别在《实现领域驱动设计》Vaughn Vernon的第二章和《领域驱动设计》-Eric Evans的著作的后半部分出现,其实我觉得只有先对这些概念有个大概的理解,后续的设计中才会更加合理使用。在其他著作里面,基本上都是 业务场景到DDD模型,而我想做的是从 DDD模型概念到业务场景,再从业务场景抽象出DDD模型。两种方式都有各自的好处,不展开讨论。
简单的领域(Domain)
平日的生活中,经常听到某某领域专家,例如考古领域专家等。这些领域都一个共通点,那就是有一个清晰的界限范围,而且专职于某些有关联的活动。在DDD中,领域和现实中的普意领域意义相差不大,无非就是DDD将这种领域概念模型化,将现实抽象到了模型中。领域具有三个特性:
- 有边界
- 有特定职责
- 有业务实体
当然我在学DDD时,曾经误认为领域是单一的,即一个领域对象的生命周期就可以负责整个业务的运转。但实际上,领域只是一个概念的抽象,是在软件设计过程中的设计大纲。领域并非是功能单一的,每个领域中可以包含多个子域,而子域又因为其所负责的具体事务的重要性不同,而划分为核心域,通用域,一般子域。
领域就可以理解为一个对象,我反复学习后发现,领域无非就是面向对象概念的一次升华而已。你可以简单的将领域理解为一个对象,以学校举例,校委会就是一个领域,你可以将这个校委会理解为一个对象。这个对象中包含很多子对象,例如教导处。这些子对象难道就不是子域了吗?其中重要的政委部,不就是核心域了吗?后勤部,不也是一个服务于大众(局限于校委会内的子域)的通用域了吗?直接将领域理解为面向对象中的 对象 是没有问题的,至少我是这么认为的。
难以理解的限界上下文(Bound Context)
限界上下文在DDD社区中有多种叫法,有的叫界限上下文,有的叫交互约束上下文等等。限界上下文无疑是整个DDD中最难理解的概念之一,因为他的定义最为模糊。参考智人作品,其对限界上下文的定义如下:
特定模型的划定适用性。边界上下文让团队成员对什么必须保持一致以及什么可以独立开发有一个清晰和共享的理解。
在《领域驱动设计》-Eric Evans著作中,其对限界上下文的定义如下(温馨提示,位置在第四部分,14章,第二小节:模式-Bounded context):
明确的定义模型所应用的上下文。根据团队的组织、软件系统的各个部分的用法以及物理表现(代码和数据库模式)来设置模型边界。这些边界中严格保持模型的一致性,而不要受到边界之外的问题所干扰。这里边界就是限界上下文。
在《实现领域驱动设计》Vaughn Vernon著作中的第二章,也提出了界限上下文概念,但是这本书关于界限上下文的口水实在有点多,我就不介绍了。以下来自智人作品的例子:
认识一下 X 公司的开发人员 John。认识一下 Rita,她是同一家公司的会计师。John 在 IT 部门工作。丽塔在会计部门工作。IT 部门是一个有限的上下文。它有责任处理公司内所有与 IT 相关的事情。会计部门处理所有与会计相关的事情,包括工资单。两者都有非常精确的职责,并且它们的界限非常明确。 我不是在谈论他们在不同办公室的事实。他们有自己的内部组织、自己的内部规则、员工等。John 没有进入 Rita 的办公室修改工资单,Rita 没有进入 John 的办公室修改他的代码。他们可以,但这将是一个丑闻,因为如果他们这样做,他们将超越他们的界限. 如果 Rita 在会计软件(内部开发)中发现错误,她会致电 IT 部门进行处理。她没有启动 Visual Studio 并开始弄乱代码。这不是她的责任,她也不知道怎么做,即使她知道 VS 是 John 用来编写代码的程序。事实上,VS 在会计的电脑上会是一个很奇怪的软件。同样,工资单文件或发票在 IT 部门中也没有位置。 当然,当约翰遇到涉及工资单的问题时,他会要求丽塔调查一下。双方都尊重彼此的界限,并根据自己的责任行事。但是 IT 部门本身分为 2 个组:软件开发组和管理组。第一组实现功能并修复错误。第二组处理服务器。每个组也是一个有界上下文。他们有自己的责任和明确的界限。DBA 不会编写 C# 代码,John 不会弄乱服务器配置。每个人都按照自己的责任在自己的范围内行事。 所以,IT部门是BC。约翰是其模型的一部分。事实上,所有有意义的事情(开发人员、服务器等)都是 BC 的一部分,并且在其中应该是一致的(开发人员应该编写软件,而不是被问及发票)。这意味着 Rita 在 IT 中没有位置,她不应该处理任何与 IT 相关的事情。丽塔是卑诗省会计部的一员。她可能正在访问 IT 办公室,但她只是路过的访客,她对部门没有任何意义,也没有人希望她编写代码或充当开发人员。约翰可能会喜欢丽塔并在她的办公室里呆了一段时间,但这并不能使约翰成为一名会计师。 我们几乎看到那些 BC 有点自主,它们不重叠。此外,如果一个对象从一个 BC (X) 转到另一个 BC (Y),这并不意味着它现在是后者的一部分,它被视为一个对 Y 没有意义的简单对象。所以它们几乎是独立的,但是如何他们可以一起工作吗?我的意思是 IT 和会计必须时常一起工作。他们通过与合适的人交谈来做到这一点:)。当 Rita 需要新的软件功能时,她可以告诉 John,但 John 的经理(会见 Andrew)最终决定是否添加以及添加哪些功能。 当您想要新功能甚至修复一些错误时,Andrew 是您可以与之交谈的人。Andrew 是 IT 经理,他告诉 John(或 IT 部门的任何其他人)下一步该做什么。Rita 不能忽视 Andrew,因为这是 IT 部门的规则:由 Andrew 决定。你必须按照安德鲁想要的方式提出你的想法,否则他们会被拒绝。不用说,如果这些要求对 IT 没有意义,它们就会自动被拒绝。Andrew 是IT BC的反腐败层。没有什么可以超越他,什么都经过了,它适应了 IT 部门的内部组织。 这些例子很简单,但我们的代码呢?我们确实希望我们的 BC 解耦,因此 BC1 不应该知道 BC2。好吧,这个想法是一个 BC 不应该知道其他 BC 的内部结构,这两个可以使用公共对象 (DTO) 将消息直接传递给另一个或一个知道如何与两个 BC 通信的专用适配器。首选方法是通过领域事件(基本上是更高级别使用的观察者模式)。
说实话,在学习之初,看了上面这个例子,我也理解不了什么是限界上下文,直到我自己亲自结合公司大佬划分的DDD上下文之后,我才开始理解界限上下文到底是个什么玩意。从以上的例子可以看出,限界上下文有三个特点:
- 限界上下文约束了模型的工作范围,即一个模型必须在一个限界上下文之内
- 在限界上下文之内,必须使用通用语言
- 限界上下文交互需要使用DTO对象
限界上下文说白了就是约束范围用的,这是主要目的。至于范围之内要不要用通用语言,取决于系统。