Fork me on GitHub

Qunar 技术 | 基于 DDD 思想的技术架构战略调整

图片

作者介绍 PROFILE
郑吉敏

2019年8月入职去哪儿网,机票目的地事业群技术总监、技术委员会委员、业务架构 SIG 负责人,负责酒店报价中心团队、业务架构组。

图片

2020 年金项奖评选中主导的“对内 DDD 对外 API 驱动的酒店报价业务重塑”项目获得了 CEO 特别奖。2021 年获得技术品牌最佳贡献奖,曾在 QCon、Top100、CSDI、SACC、MPD 等大会做过技术分享。

一、案例简述

2020年疫情对旅游行业影响特别大,公司层面做了组织架构调整,酒店业务侧发生了巨大的变化,新的业务团队在推进一些实际需求时遇到了新的产研效率问题,主要体现在产品每次要和多个技术团队合作、整体技术架构与业务出现脱节。

结合之前 DDD 落地的成功经验,酒店技术侧于2021年中旬主动发起了一次基于 DDD 思想的技术架构战略调整,涉及组织架构调整、系统架构调整等,并制定了一些核心技术方案的标准,本次重点介绍这次战略调整的确认及落地过程。最后基于这次战略调整,看康威定律及 DDD 思想发挥的作用。

二、案例背景及问题分析

1、背景

2020年初,全球爆发了新冠疫情,对旅游行业影响比较大。2020年5月份公司层面做了比较大的调整,首先成立了机票目的地事业群,机票和酒店作为两个公司最大的事业部从独立运营合并成到一个事业群,其次统一了服务、用户体验等团队,统一对事业群负责,同时制定了机酒交叉(可以简单理解为用户购买完机票后能购买酒店)的战略目标。

面对这些组织架构、业务架构调整,系统架构又该如何演进来支撑这些变化呢?带着这个思考,我们来看实际遇到的一些问题。

2、问题及表现

2.1 产品吐槽

  • 几乎每个需求要和多个技术团队沟通,合作麻烦
  • 很多需求的技术方案,经常需要升级才能达成共识

2.2 引申问题

  • 看似简单的需求,链路很长,总有团队即使没逻辑修改也要做透传的事情
  • 讨论技术方案时,不同团队对某个逻辑谁来实现意见不一致,本质是边界不够清晰

3、问题分析一

先来看一下主流程核心的交互图:

图片

(注:图中 List 代表列表页、Detail 代表详情页、Booking 代表预订页,Order 代表订单页)

通过上图的交互流程,我们可以总结出以下几个问题:

  • 所有核心流程都涉及的团队是报价团队,报价团队是后端团队,比较底层
  • 用户端跨页面交互统一需要在底层的报价团队完成
  • 底层修改,会带动整个链路跟着修改(典型的比如:基础数据新增字段)
  • 报价团队的定位是基于用户计算酒店房型、价格及实际的优惠细节,基础数据及相关逻辑并不想感知

4、问题分析二

继续看一下主流程核心团队及核心设计:

图片

通过上图,我们可以总结出以下几点:

  • 很多团队在自己的领域层上面都有应用层
  • 这些应用层,导致有些事情上下游团队都可以做
  • 很多事情,谁都能做的时候,就可能出现谁都不想做
  • “万金油”式架构,适合业务上升期,不适合稳定期

三、案例分析与规划

1、基于Explicit Architecture(清晰架构)分析

图片

上图来自国外顶级架构师 herberto graca 的博客(https://herbertograca.com/),融合了 DDD、洋葱架构、整洁架构、CQRS 的”清晰架构“,这个架构有很多优势,比如:

  • 从外向内,越向内越偏核心原则,核心原则相对稳定。核心原则就是常规的领域层,提供核心能力
  • 外层基于核心原则适配不同的业务场景,组装内层的能力。这里的外层就是常规的接口层到应用层,主要使用主动适配器模式,重点关注 BFF 及对内层能力的聚合
  • 内层不依赖外层,不受业务变化而变化,关注能力的扩展,完成核心策略实现
  • 边界明显,尤其是领域层与应用层之间
  • CQRS 机制,耦合度低,通过外层组装内层能力动态适配业务变化,扩展性高
  • ...

2、技术架构构想

结合清晰架构的特点来思考技术架构整体的调整策略

  • 核心思路:整体架构按照 DDD 分层架构来,严格区分应用层、领域层
  • 核心动作:包含核心领域的团队交出各自的“应用层”,统一交给下游网关团队,组成统一的应用层,这些团队负责的事情变成一个个核心领域

图片

3、技术架构调整规划

围绕上面的构想,整体架构图期望如下图所示:

图片

通过上面这个图可以明确几个关键点:

(1)明确战略调整核心

  • 突出核心领域,做大“大前台”(内部叫做主站,这里为了方便理解调整一下叫法)

(2)明确和之前的区别

  • 负责核心领域的团队聚焦可复用的能力,专注核心策略、玩法的改进
  • 负责应用层的团队聚焦业务识别与扩展,专注业务模型设计和组装下游能力
  • 业务收敛到一个团队,这个团队了解下游可提供的能力,能从全局看业务整体开展情况

4、优势劣势分析

围绕着上面的调整,分析一下优劣和劣势

(1)优势(偏向中台方向)

  • 减少影响团队:很多需求,产品只需要对接前台一个团队即可,即上文提到的“大前台”团队
  • 减少数据链路:主流程链路变短,设计技术方案、出问题定位及解决都更容易,典型的就是基础数据链路不再经过报价团队给到下游

这两点,在实际中都验证了确实可以起到产研提效作用。

(2)劣势及可能带来的问题

  • 短期内,已有的工作习惯发生变化:数据链路发生变化,需要多个团队配合落地,然后适应新的链路,同时要适应新的架构
  • 可能带来上游团队人员不稳定:这样势必会带来一些杂活完全交给大前台,如果一些人持续做些杂活或小需求,就可能出现人员不稳定的问题。这时候需要考虑找一些核心事情、做好业务建模等来改善

四、案例落地过程

1、系统架构调整

  • 应用归属团队调整
  • 已有逻辑归属调整

这里主要完成的是,将做“应用层”的应用及逻辑上交给大前台团队,先保证各自团队负责该负责的事情,让负责核心领域的团队实际主要负责领域的事情,其他交给大前台

2、组织架构调整

  • 组织架构按需调整:比如多个网关合并成大前台,同时借助一些需求完成一些人员交叉
  • 核心人员归属团队规划:这里主要是 review 一遍核心成员,看看适合领域团队还是大前台,必要时进行相关调整
  • HC 调整,招聘计划跟进:本次会按需为大前台团队增加 hc,同时加紧招聘节奏保证人员尽早就位,这样也可以避免个别成员不稳定对整体的影响程度
  • 成立业务架构组:监督及保证架构调整,同时避免之后的腐化

3、技术方案标准制定

3.1 数据回传标准化

  • SPU 维度:供应链 -> 基础数据(商家、酒店等信息) -> 大前台 -> 端

图片

  • SKU 维度:供应链 -> 报价(酒店房型及价格优惠,类比电商里的商品) -> 大前台 -> 端

图片

根据 SPU、SKU 数据回传标准进行链路治理:对比之前的链路,核心要对基础数据要一次完整的改造。我们首先对基础数据基于 DDD 思想做了一次领域划分,然后基于领域提供相关的对外 API 服务,然后直接对接大前台。大前台在拿走报价团队的应用层应用(内部应用名字叫 mprice),先将原服务合并到已有的应用层应用中,然后对接基础数据服务 API,从之前链路的 7 个应用直接降为 4 个应用,再加上一些串行操作并行化,不但链路缩短了,同时主流程响应时间降低了 25%,效果特别好。

3.2 请求处理标准化

3.2.1 方案制定

图片

上图是我们主流程计算用户支付价的几个核心过程。重点解释一下【商促】:基于用户画像打包,满足特定要求(比如特定的用户身份)的营销活动,拿到更低的底价,获得更高的利润。

接下来看一个实际问题:要过节了,业务侧希望放开某些商促限制,给所有用户使用,技术方案该如何设计?我们先来给出常规的两种技术方案:

  • 前台修改用户身份,其他团队不感知。 方案存在的问题:用户身份本质上并没有变化,这时查看用户身份是错的,其他链路会跟着受影响。
  • 报价团队识别场景,做特殊商促匹配。 方案存在的问题:报价正常提供能力,现在要提供的是定制化功能,和定位差别太大

常规的方案都有明显的问题,那么根本问题出在哪里呢?其实是标准做法里缺少对【场景】的应对!

我们结合下图聊一下业务场景中的身份和场景。

图片

内部做了多次讨论后,最终给出结论:

  • 身份: 任意时刻下描述用户(userid)不因此刻本身行为及外部条件影响的自身描述性质或特征的有限个数的标识
  • 场景: 谁(who)在何时(when)何地(where)发生了什么事件(what)产生了何种结果 or 情景(how)的标识

举几个例子,比如酒店新客、机酒用户都是定义为在一段时间内有过某些指定消费行为(买过酒店、买过机票等)的用户,通过 userid 可以直接得到明确的结果,这个属于身份;而异地面纱就属于场景,原因是对于明确 userid,假设常住地为北京,这个用户本次要去北京以外的地方,这样才能匹配上“异地”。这里要注意身份特征有限个数的限制,比如门店新客,对于一个用户而言,他是否是某个门店的新客正常也是明确的,但是我们有将近百万在线的门店,这时就不适合作为身份使用了,因为我们在使用 userid 去查询他的身份时,每个门店都列出来的代价太大,这种更适合拿着 userid + 门店去查询。

在我们的业务场景里,常规都是基于正常定义的身份进行标准计算,如果不能使用身份来匹配,就需要使用场景来解决。

基于对【身份】和【场景】的理解,针对前面的问题,我们给出更合理的方案:报价提供“强制使用指定商促能力”前台识别场景,组装使用新能力。 这样报价依旧关心能力的提升,前台依旧负责的是业务的适配及组装能力,核心是针对身份和场景的标准使用。

图片

补充说明一下,按照这样架构调整及技术方案执行后,从整体来看整个架构:

  • 领域层能实际暴露出能力,应用层最终暴露出去功能
  • 由于应用层可以按照需要组装能力,因此可以表现出很强的扩展性;对于领域层而言,专注能力的复用,因此更具稳定性
  • 应用层组装领域层能力,靠的是标准的身份和场景。要么基于标准身份使用常规能力,要么基于场景强制使用特殊能力
  • 功能是解决实际场景诉求的,变化快,因此需要提供很多接口去完成一些定制功能;能力是需要尽可能忽略场景的,这样才可能做到最大程度复用。要解决两者的冲突,就需要合理的使用身份和场景。

3.2.2 参数透传

日常开发我们经常会遇到这种情况,需要借助很多应用透传一个参数,给特别上游的应用使用,这种参数对链路上参与透传的团队和应用来说,没有任何业务逻辑处理,徒增开发工时,扰乱定义的 API。为了解决这个问题,公司内部业务研发和基础研发共同讨论确认开发一个新的通用组件:QShareData。各个应用可以基于请求把一些数据写入 QShareData 组件,对应的数据 id 跟随 trace 一起传递,链路上其他应用可以按需通过数据 id 获取其他应用写入组件的数据,减少一些无意义的透传。当然,这里面涉及一些权限、性能及合理使用等问题,需要结合实际做些要求和限制。

图片

五、案例总结

图片

首先,我们来回顾一下著名的康威定律 :设计系统的组织,其产生的设计等同于组织之内、 组织之间的沟通结构。康威定律成立说明组织架构与系统之间必须匹配,但未强调合理

接下来,我们再看一下** DDD 中的康威定律** ,它的核心是系统架构驱动组织架构。DDD 基于业务领域,回归业务,与业务匹配,更容易做到合理。

相信有些人会问:团队如何划分才能与业务匹配?本质是让 DDD 的制约因素成为 DDD 要改变的目标,这里总结两点:

  • 以 DDD 得到的业务领域模型为基础,审视与调整组织架构,进行团队的划分
  • 从业务领域结构出发形成网状组织架构,并在业务发生显著变化时保持组织架构的灵活性,反向使康威定律发挥作用

本文地址:https://www.6aiq.com/article/1648170246451
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出