写点什么

架构师的十八般武艺:领域建模

作者:agnostic
  • 2022 年 10 月 05 日
    上海
  • 本文字数:2047 字

    阅读完需:约 7 分钟

这次我们聊一下领域建模。领域建模是对我们要解决的业务问题的概念化分析,是业务架构的重要组成部分,也是系统模型设计的基础。

在领域建模领域,有大量的理论和资料,比如 DDD 就是领域建模很好的方法论和实践。本文我们不对 DDD 做详细的论述,有兴趣的同学可以自行去了解和学习。本文我们重点放在一些关于领域建模实践过程中的感悟和思考。


综合大量在支付和资金业务中的领域建模实践,我们大致有如下感悟:

领域模型是现实世界的映射;领域模型和 API 密切相关;根对象非常重要;值对象值得关注;模型间映射弱势方迁就强势方。


领域模型是现实世界的映射

这个感悟很容易理解,领域模型就是对现实的业务进行分析的工具,所以领域模型理应就是现实世界的映射,而不应该生造一些模糊的概念。

例如,在做主体间资金方案的设计时,第一版通过资金服务和资金通路来抽象所有的跨主体之间的资金行为。通过不同的资金服务来确定核算关系,通过不同的资金通路来定义资金在账户间的调拨关系。但是,这种模型非常抽象,也很难和现实世界进行对应;留给了业务方(配置工程师)过多的选择,导致资金服务和资金通路的不断膨胀。

在第二版,我们先分析了现实世界中主体间资金方案的本质。首先,主体间会发生资金行为,取决于主体间会有一个受托和委托关系。其次,核算方案和业务相关。再次,主体间的资金行为,根据我们的业务管理模式,对于不同的主体开设了不同的银存,所以会存在资金的调拨关系。所以在第二版,我们首先确定主体间的业务关系以及委托受托关系,其次实例化主体对应于本次业务和委托关系的银存体系。有了这两点,我们就最终确定了调拨关系和核算方案。

经过这次升级,原先非常灵活的资金服务和资金通路的定义,就固化为了提现、支付、收单、代发、代扣等明确的业务关系和各类主体、银存的实体定义。业务可以非常容易的定义和产出资金方案,并固化为系统行为。


领域模型和 API 密切相关

首先,API 目前非常重要,有一种说法:API are eating the world,所有的 IT 能力都可以通过 API 的方式暴露出来给第三方使用,所以 API 的定义目前基本上是产品设计的 1st priority 的工作和产出。

同时,目前 Restful 基本上是 API 的主流设计模式。Restful 我们可以理解为模型+CURD。所以,领域模型的设计理念直接影响了 API 的设计理念。

例如,在外汇 API 的设计过程中,我们第一版本是将我们的外汇平台看作是一个交易的系统,所以主要的服务就是报价和交易。在 API 的设计上,也就是 quoting 和 make transaction。在这个模型下,用户需要理解币种对、买卖方向(BID/OFFER)、tenor(TOD/TOM/SPOT 等)等复杂的外汇概念。

在第二版外汇 API 设计过程中,我们将外汇平台视为一个支撑各类场景中币种和时间错配的流动性提供方。所以,我们的 API 设计对外只是暴露了业务类型、原始币种/目标币种、清算周期/打款周期等和业务场景相关的概念,使用方会非常简便的使用我们的 API。

未来第三版的外汇 API,我们也可以将外汇平台看作是一个基于敞口的流动性提供方,对外暴露和敞口相关的买/卖币种、敞口期限、敞口风险偏好等。


根对象非常重要

这一点非常好理解。根对象做到领域模型的根,我们可以基于根对象进行幂等、并发控制等。所以,根对象粒度的大小就非常关键,如果根对象的粒度过大,系统的并发度就会比较低。如果根对象的粒度过小,幂等和并发控制就比较容易被打破,系统的复杂度就会比较高。

在实践过程中,请求就显得粒度过细,应该将相关的请求,比如 auth/capture,withdraw/reject/refund 关联在一起,以 transaction 的维度定义根对象。

其次,不同的域可能有不同的根对象,比如资金域,一次支付交易,一次提现就会作为一个根对象。而在金融交换域,一次和机构的交互才会作为根对象存在。

最后我们不会将一次批处理作为根对象。对于批处理,我们可以记录每条记录的执行状态,批可以部分成功,可以进行断点续传模式的重试。


值对象值得关注

immutable 的值对象,也是对客观世界的抽象。值对象的使用,会简化和固化我们的领域模型,所以大家一定不同忽视对值对象的定义。


模型间映射弱势方迁就强势方

不同域之间的模型由于不同域的业务视角不同,在抽象的理念上会有一定的差异。所以,跨域模型之间必然存在一定的映射需求。到底由谁去处理这种映射,往往是架构方案和架构决策中 argue 最多的地方。

在我们的实践过程中,首先,不要引入第三方做映射。所以像 ESB、BPM choreograph 这些东西,就实在没有存在的必要。“若无必要,勿增实体”(Non sunt multiplicanda entia sine necessitate)。

其次,越底层的越通用的领域,越不适合做这种模型转换。比如支付域不适合理解收单模型进行转换;资金域不适合理解行业的模型进行转换。

再次,服务被广泛使用的域不适合理解调用方的模型进行转换。比如资产交换的模型会被余额、积分、营销、渠道等多域进行使用,所以应该由使用方的各域理解资产交换模型进行转换。

最后,广播类的消息服务,原则上由接收方理解模型做转换。比如动账消息,会被账单、流动性、行业等多个域使用,由各方去理解并映射为本域的模型。

总之,弱势方迁就强势方。


发布于: 刚刚阅读数: 4
用户头像

agnostic

关注

还未添加个人签名 2019.02.14 加入

还未添加个人简介

评论

发布
暂无评论
架构师的十八般武艺:领域建模_领域建模_agnostic_InfoQ写作社区