实现领域驱动设计
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

面向服务架构

面向服务架构(Service-Oriented Architecture,SOA)对于不同的人来说具有不同的意思。这对于讨论SOA架构来说可能是一种挑战,因此我们最好能找到一些共同的基础,或者至少应该给出一些定义以便讨论。我们可以考虑由Thomas Erl[Erl]所定义的一些SOA原则。服务除了拥有互操作性外,还具有以下8种设计原则,如表4.1所示。

表4.1 服务设计原则

img

我们可以将这些原则和六边形架构结合起来,此时服务边界位于最左侧,而领域模型位于中心位置,如图4.5所示。消费方可以通过REST、SOAP和消息机制获取服务。请注意,一个六边形架构系统支持多种类型的服务端点(endpoint),这依赖于DDD是如何应用于SOA的。

img

图4.5 一个支持SOA的六边形架构,其中包括REST、SOAP和消息服务。

由于对于SOA的定义和SOA的价值存在不同的观点,即便你不同意图4.5也是可以理解的。Martin Fowler将这种情况称为“面向服务歧义”[Fowler,SOA]。因此,这里我不会试图消除对SOA的歧义理解,但我会讲到将DDD应用于SOA的一种方式,此时我主要关注SOA宣言[3]中出现的首要原则。

首先,让我们看看其中一位宣言贡献者[Tilkov,Manifesto]的观点。该贡献者的评论有助于我们理解SOA到底是什么:

SOA宣言给我的感觉是,我既可以将服务看作一系列的SOAP/WSDL接口,也可以将其看成为一组REST资源……本宣言并不试图给SOA下定义,而是找出我们都同意的SOA的价值和原则。

Stefan的评论是值得注意的,在某个问题上达成一致对我们是有帮助的。我们甚至可以在这一点上达成一致:业务服务可以由任意数目的技术服务来提供。

技术服务可以是REST资源、SOAP接口或者消息类型。业务服务强调业务战略,即如何对业务和技术进行整合。然而,定义单个业务服务与定义单个子域(2)或限界上下文是不同的。在我们对问题空间和解决方案空间进行评估时,我们会发现,此两者均包含有业务服务。因此,图4.5所示的只是单个限界上下文的架构,该限界上下文可以提供一系列的技术服务,包括REST资源、SOAP接口或者消息类型,而这些技术服务只是整个业务服务的一部分。在SOA的解决方案空间中,我们希望看到多个限界上下文,而不管这些上下文使用的是六边形架构还是其他架构。SOA和DDD均没有必要制定如何对技术服务进行设计和部署,因为存在很多种这样的方式。

在使用DDD时,我们所创建的限界上下文应该包含一个完整的,能很好表达通用语言的领域模型。在限界上下文(2)中我们已经提到,我们并不希望架构对领域模型的大小产生影响。但是,如果一个或多个技术服务端点,比如REST资源、SOAP接口或消息类型被用于决定限界上下文的大小,那么上述情况是有可能发生的,结果是将导致许多非常小的限界上下文和领域模型,这样的模型中很有可能只包含一个实体对象,并且该实体作为某个单一聚合的根对象而存在。

虽然这种方式在技术上具有优点,但是它却没有达到战略DDD所要求的目标。对于通用语言来说,这种方式会起分化破坏作用。而根据SOA宣言,非自然地分化限界上下文并不是SOA精神所在:

1. 业务价值高于技术策略

2. 战略目标高于项目利益

就像限界上下文(2)中所讲到的,技术组件对于划分模型来说并没有那么重要。

SaaSOvation的开发团队不得不上很困难但又很重要的一课——将通用语言作为驱动更适合于DDD。他们所有的3个限界上下文所反映的都是SOA的目标,包括SOA的业务服务和技术服务。

限界上下文(2)、上下文映射图(3)和集成限界上下文(13)中提到的3个示例模型分别表示了某个能很好反映通用语言的领域模型。每一个领域模型由一组SOA开放服务所包围,这些服务是满足业务目标的。