谁应该做这件事 ?

背景

做一个项目的时候,遇到一个问题。如图所示,流程如下:

STEP1: 协议发起协议下单,下单成功后,获取 E 单号;

STEP2: 协议使用 E 单号调用代扣款服务;

STEP3: 代扣款服务将 E 单号转为 X 单号,然后使用支付收单服务,支付成功。

STEP4: 交易监听收单消息,进行支付回调处理。

问题来了:由于代扣款服务将 E 单号转为 X 单号,支付给交易的消息中,只有 X 单号。交易不识别 X 单号,报订单号非法。


讨论

直觉上会认为:交易应该拿到 X 单号对应的 E 单号,然后去进行后续处理。 要完成这个功能,确实可以这么做。但是,这样做合适吗?

角色的相对性与转换

在这个示例中,容易意识到:这里需要有一个流程的全局主导者,将协议下单、支付、完成的生命周期串联起来。

从业务上来说,这是个协议下单的业务,理论上,协议应该就是业务方; 从流程上看,协议方下单、调用扣款,做的也是控制流程的事情。 不过,协议方认为,自己只是协议服务,不应该关注这么多东西。

不过我觉得,角色定义是相对的,是可以在基础服务和全局流控之间转换的。比如交易,在下单流程中,交易就是主导者角色,调用商品、营销、支付、会员等,将交易相关的信息聚合起来落库,将整个购买流程串起来;但对于更上游的业务,比如微商城、零售、教育,交易又作为一个基础服务模块。

同理,协议方虽然也是一个基础服务,不应该关注支付、订单之类的事情,但在协议下单这个业务语境里,它应该担当一个流控主导者角色。

能做与应该做

在讨论问题时,常常会出现一些模糊边界,这个边界的每个服务模块都可以做,但是,—— 能做,就应该去做吗 ?

这里涉及到定位的问题。交易的定位是:订单的创建、订单的生命周期管理。协议也有自己的定位:处理会员与商家之间的关系。

看上去,对于这个示例,交易和协议的定位都不太适合去做这个事情。

通用能力

协议同学又提出了一个观点: 如果有业务方 A,B,C,也需要下单成功后代扣款能力,但不需要协议能力,是不是每个业务方都需要做相似的事情 ? 是否可以提炼为通用的能力 ?

好问题。 看上去,交易吃掉这块逻辑,无论对交易还是对业务方都有益。

仔细分析下。 通用能力,通常包含相同的部分和相异的部分。相同的部分可以复用,相异的部分则使用扩展点来实现。

在这个示例里:相同的部分显而易见:下单成功 -> 代扣款服务 -> 监听收单消息,将订单状态改为已支付。 一气呵成,多好 !

那么,有什么潜在的问题呢 ?

  1. 如果代扣款失败,该怎么处理 ?

  2. 如果支付成功后,业务方需要做一些处理,再修改订单状态,怎么办 ?

有人说,这两个问题都可以通过扩展点来实现呀!这里又衍生出两个话题。

过度设计

考虑系统的通用性和可扩展性是合理的,不过,是否要在最初就做的很完善呢 ? 通过扩展点的方式,看似可以完美支持这些功能,但是,如果后续很长一段时间并不需要类似能力,这个扩展点的设计和实现就容易变成一个复杂度高、可维护性低、成本高的过度设计的方案。

此外,交易核心流程依赖上游扩展点实现,基础服务依赖业务实现,是依赖的反模式,容易导致可靠性问题。 可见,扩展点虽然万能,却不能滥用。

复用模式

理想化的复用模式是:定义一个万能的流程,这个流程中有很多插槽,这些插槽都是扩展点,可以供上游实现和插入。

实际系统中,对于比较常用的核心的地方,会定义一些插槽。可是:是否插槽越多越细,支持的能力越灵活越好呢 ?

还有一种相对低级而有效的复用模式:就是提供一系列拼板,上游可以根据自己的需求去拼接自己的业务图景。

一种是在核心流程中插入许多细小的插槽,业务方可以插入自己的实现,来完成定制化的能力。但这种方式有个弊端: 插槽越多,就越难理解和维护;核心流程依赖业务方的实现越多,核心流程就可能越不稳定。

一种是基础服务方只提供基础拼板,由业务方自行根据需求去拼接。这种方式,业务方更灵活自由,但是也会有很多相似的东西要重复做。

你更倾向于哪一种呢 ? 是否有更好的方案来解决这个问题 ?

先例

遇到问题,寻找可供参考的先例也是一种办法。

比如零售,也遇到过类似问题。当时采取的办法就是: 零售去做一层收单号与订单号的转换,然后调用交易提供的支付回调服务,将订单状态更新为已支付。

先例是否能够用到当前场景下,也值得仔细思考。

成本衡量

有一个重要因素:实现成本和风险考量。

交易:需要调用代扣款服务的查询接口,做一层转换处理。 风险:由于交易订单量非常大,而真正需要调用代扣款服务接口的订单量很小,很可能导致:a. 95% 以上的订单都没必要调用这个接口; b. 代扣款服务容易被拉挂; c. 代扣款服务如果被拉挂,交易的核心流程的稳定性会受到严重影响。

协议:需要自己去调用代扣款服务查询接口,做一层转换,然后调用交易提供的支付回调服务,将订单状态更新为已支付。 风险:无。不过不可复用,而且看似不太适合协议的定位。

代扣款服务:做一层转换,将 X 单号转成 E 单号,然后透传给收单服务,收单服务发送跟之前一样的支付收单消息。风险 : 可能影响支付的一些原有的服务。

从实现成本和风险角度来看,协议更适合做这件事。


小结

在中大型项目中,常常会有一些由于模糊的系统边界而导致的“灰色功能区域”。每个毗邻“灰色区域”的系统,似乎都有权利去实现这个灰色功能区域。那么,谁应该做这件事呢 ? 这篇文章提出了一些基本的考量因素:

  • 在当前业务场景下,谁是流程的主控方 ?
  • 在当前业务场景下,谁拥有信息的解释权 ?
  • 系统的定位是怎样的 ?是否适合承接“灰色区域”的功能需求 ?
  • 在考虑通用能力的同时,是否有过度设计的嫌疑 ?
  • 实现方式是否容易理解、维护、可靠、稳定 ?
  • 采用何种复用的形式更适宜 ?
  • 实现成本和风险如何 ?
  • 是否有先例可以参考 ?

猜你喜欢

转载自www.cnblogs.com/lovesqcc/p/11932840.html