黑石贝莱德如何实现基于领域驱动的资产管理?


Alan Moore (Aladdin 首席架构师、技术研究员和董事总经理)描述了贝莱德在资产管理中使用领域驱动设计DDD,以及我们如何使用它来定制、扩展和调整 Aladdin 以满足客户的需求。

Aladdin 阿拉丁是一个统一投资管理流程的技术平台。它是一种有生命力的产品——不断进化、现代化和创新,以保持其在全球资产管理技术生态系统中的领先地位。

在设计和开发过程中,我们不断寻求确保随着阿拉丁功能的扩大和深化,我们可以进行大规模的创新--使用适合的技术、系统和技术,加强弹性和稳定性。

我们发现,应用领域驱动设计的做法,可以使我们在帮助其他机构进步、成长和扩大规模时,在如何提供、定制、扩展和调整Aladdin以满足客户的需求方面获得更多机会。这种做法也为我们的客户和第三方开发者提供了未来扩展和定制的机会。

在这篇文章中,我们将看看我们在实践中如何采用这种方法,以及它如何影响我们描述Aladdin及其功能的方式。

问题和挑战
Aladdin 的内容既广泛又深刻。

在广度上,它是一个巨大的功能套件,涵盖了资产管理的全部范围。我们面临的一个挑战是如何确保Aladdin的不同产品领域能够独立工作(以不同的速度)。了解相互关联的产品领域是应对这一挑战的关键。

在深度上,每个功能都有一个现代堆栈的支持,有助于确保平台层面的一致性和效率。这里的挑战是;如何在这个堆栈内进行创新,同时保持整个产品的稳定性和完整性。

经典的领域驱动设计
领域驱动设计(DDD)是一种主要的软件设计方法,根据领域专家的意见,对软件进行建模,使其与该领域相匹配。作为一种软件设计方法,DDD鼓励领域的首要重要性,以及建立一个充分描述领域及其交互的抽象系统的必要性。这些抽象概念使用与该领域相关的商业术语,而不是深奥的技术术语。简而言之,我们的想法是,商业用户、发起人和开发人员都使用一种共同的语言来描述该领域。

在思考如何将DDD应用于更广泛的Aladdin平台时,我们的想法是将Aladdin分解为一组领域,并在声明一个领域如何融入更广泛的产品套件时,确定每个领域所有者的期望。领域与其他领域有正式的供应/需求关系。

高层次的领域语言结构
在领域驱动的资产管理模型中,领域的概念被定义为适合更大领域组的能力分组。例如,"工资 "可以是 "财务 "领域组中的一个领域。对于Aladdin来说,"投资合规 "领域可以归类为 "Aladdin核心 "领域组的一部分。

Aladdin中的域的例子有哪些?如果我们了解一下典型的投资流程,清晰的业务能力边界就会很突出

  • 我们通过使用各种数据源(参考数据、风险分析、投资研究),加入一个投资组合(投资组合服务)并构建一个投资组合(投资组合管理)。
  • 构建投资组合的行为会产生需要进行合规性检查的订单(订单管理)(投资合规)。
  • 这些订单最终通过一个操作生命周期(投资操作)进行交易(交易管理)。
  • 可能有会计(会计),我们在投资组合中的头寸需要风险分析(风险分析)。
  • 我们可能希望通过这种风险的视角来管理我们的投资组合(风险分析)。

从一开始,很明显,一些领域之间存在着隐性的依赖关系。例如,如果没有明确定义什么是投资组合(投资组合服务),你就无法管理投资组合(投资组合管理)。还有一些领域是大多数Aladdin装置的核心--风险的纯粹计算和证券参考数据的管理。

我们也想用同样的领域驱动的方法来定义Aladdin所基于的基本平台。使用这种观点使我们能够将Aladdin平台视为一套相互关联的产品,提供产品领域所需的技术能力,包括基于操作的基本能力,如遥测。

在Aladdin中,资产管理中的许多业务流程跨越了多个领域。由于这种广泛性,有一个更高层次的领域来捕捉这些跨领域的流程,以及它们通过产品领域能力的实现。

深入了解域
如果Aladdin是由它的域和它们的关系定义的,那么一个域到底能做什么?我们需要正式说明一个域可以 "发布"(即向其他消费者提供)的组件类型,以便每个人都清楚一个域提供什么。这个域的文档在开发门户中使用,开发者可以用它来了解他们如何编写与给定域交互的组件。

领域实体
按照领域驱动的软件设计方法,我们希望领域能够定义并拥有他们的领域实体。举个例子,我们的 "投资组合服务 "领域拥有并管理Aladdin的 "投资组合 "领域实体。在这种以领域为中心的方法中,Aladdin产品套件中所有领域的领域实体集可以被认为是资产管理的一个明确的通用数据模型,特别是当与分析数据集相结合时。

领域读取API
随着对域所拥有的实体的定义和声明,拥有一个非常一致的API来从域外读取这些域实体是非常重要的。一致的命名、实现和行为有助于提供一种非常有效的、被充分理解的访问一个域的公共数据的方式。开发负担很低!

业务API
业务API是我们操作域实体并指示域做它们作为满足其能力的一部分而执行的工作的方式。业务API可以引用其他领域的实体,这种引用在各领域之间建立了明确的依赖关系。

领域事件
当领域实体被流程改变时,我们希望其他领域能够做出反应。这些变化由一个域可以发布的域事件来处理。例如,如果一个投资组合通过 "投资组合服务 "域中的某个过程被改变或添加,那么阿拉丁事件总线的任何订阅者都可以对该变化做出反应。领域事件通常是命令驱动的,即它们通常是通过调用一个命令来响应领域实体状态的变化而发布的。例如,一个 "预订订单 "的业务API将创建一个订单域实体并发布一个订单变更事件。

分析性数据集
域还可以向阿拉丁数据云发布更多的分析数据,域可以准确地声明它将发布的数据类型。

工作流程和步骤
为了提高性能和规模,我们希望领域能够通过定义步骤序列来异步协调活动,并将这些步骤组合成创新方式来创建工作流程。在Aladdin中,这些步骤可以在一个通用的计算结构上运行,可以根据需求进行扩展。我们发现最有趣的是,对于某些领域,一些步骤可以根据其输入和输出进行正式定义,这导致了定制和扩展方面的机会。


用户界面微前端
领域驱动的模型还允许我们明确定义和发布微前端,这些微前端可以与一个领域相联系,并使用其API和工作流程来执行和监控该领域的活动。然后,这些微前端可以跨域组合,以创造一种体验,捕捉更全面的基于角色的互动,这种互动可以根据客户安装的域来改变。

阿拉丁领域的CQRS
命令查询责任隔离(CQRS)是一种重要的技术,可以应用于领域驱动的设计。从域发布的工件中的读API和业务API的概念可以看出,我们在适当的地方采用了CQRS,因为相当数量的建模域实体需要复杂的修改行为,这些行为最好通过命令变更来体现,而且大多数用户对基于意图的变更通知感兴趣,而不是更通用的通知。

因此,我们希望 "认领一个订单 "并理解 "订单被认领",而不是 "认领一个订单 "并收到 "订单改变"。这与工作流程和任务协调模型相结合,帮助我们以有意义的、精确的事件方式来扩展和应对变化。


开发领域模型
领域驱动的设计方法还引入了一种新的纪律,在不断推进和改进更广泛的阿拉丁产品系列的过程中产生了有益的见解。

清晰的能力定义使我们能够看到无意中的功能重复,并引导我们找到正确的所有者(正确的领域),他们应该提供服务于能力的功能。最终,阿拉丁的领域模型创造了一种共享的语言,不同的利益相关者可以通过这种语言一起工作--改善理解,浮现出创新和增长的领域,并帮助每个人在一个复杂的产品领域中导航。

一个用户/开发者的领域
这个关于领域是什么以及它提供什么的正式定义,对于帮助阿拉丁的贡献者非常重要。贡献者是希望扩展或整合平台的客户或贝莱德开发人员和业务分析师--我们称这批人为公民开发者社区。他们帮助我们推动边缘工程,即我们允许工程之外的其他人向平台贡献代码。现在,一个领域的每一个外部接触点都可以在开发者门户中正式记录下来,而且相互作用和依赖关系都非常清楚。

结论
领域驱动的方法引入了一些形式化的东西,以记录领域的交互方式以及领域如何被增强和从外部消费。正式的定义不仅仅是为了管理阿拉丁这个产品--它为软件开发者和设计者提供了许多好处,并引入了足够的边界和契约,使创新能够大规模地发生。

我们还发现,围绕领域的通用语言,以及一个领域可以 "发布 "的组件类型的正式声明,在通过分解思维谈论复杂的产品时,对我们有所帮助。它使我们在定义领域之间的相互作用时,能够清楚地了解边界和清晰的定义。

这是我们继续推进Aladdin的功能集、其开放性以及使用不断发展和改进的技术和系统的方法之一。