锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 默认分类
  3. M*N个策略造成类爆炸怎样重构?

M*N个策略造成类爆炸怎样重构?

0
  • 默认分类
  • 发布于 2024-09-23
  • 1 次阅读
黄健
黄健

背景

收到朋友针对他们遇到的具体问题写一篇文章的邀请,问题是这样的

朋友:

我们公司对接了M个三方服务  然后还有N种业务  实现用策略的话感觉有点类爆炸  也想不到什么好方法了  这也是早上刚接到一个重构支付的需求想到的   根据业务和供应商搞了太多策略实现了[晕]

我:

初步感觉应该用打造接入平台的方式解决

朋友:

开始的时候没有考虑到  代码一言难尽了 [捂脸]  谢谢谢老师

我从对话中分解出下面几个问题

1、理解重构、重写和重新架构

2、怎样做重构?

3、重构过程与业务支撑之间怎样平衡?

下面我针对这三个问题展开论述。

理解重构、重写和重新架构


重构是对代码和功能进行渐进式改进;重写是要摧毁它,重新构建;重新架构在大框架上做修改和再设计,具体每个实现模块可能是用原来的。


举个例子,搭积木。重构就是我用积木搭建了一个小马,发现小马某些部分不好看,我就把几块积木调整调整,让小马更好看;重写就是我用积木搭建了一个小马,发现自己搭建好了完全不喜欢,把积木推到了重新搭,既然是重新搭,搭好的东西和原来差距有多大就不好说了;重新架构就是我用积木搭建了一个小马,发现自己其实想要个小桥,没有必要全部推到重做,而是可以先画好设计图,然后直接把小马的四条腿拆下来做桥墩,脊背部分做一部分桥面,实在不能用的再拆下来重安装。


重构是小步跑的过程,如果对外提供的功能没有变化,这是稳妥的方法;重写往往伴随着功能上的升级,不然对于“我不知道这段代码是干什么用的但我不敢删”这种事情很难保证对外提供的功能没有变化。


重构和重写与修改量没有直接关系。有个哲学问题叫做“特修斯之船”,是说一艘船持续的在海上航行,船不断有部分老化或者坏掉进行替换,最终整艘船的所有部分都换过一遍,这时候船还是原来那艘船吗?


所以咱们不再纠结概念,统一用重构这个词,聚焦于怎么解决问题。

怎样做重构

首先需要对系统进行一个生命周期预估,包括:

  • 未来需求预判

  • 模块划分拆解

  • 总结历史问题

朋友说:“开始的时候没有考虑到  代码一言难尽了”,其实大可不必这样想。架构和代码不是设计出来的,是演进出来的。如果一开始要我做,一段时间之后,也很可能会遇到相同觉得非重构不可的情况。虽然我一定会做未来需求预判,但是现实往往会出现很多例外情况,让程序充满了妥协。

那针对朋友遇到的问题,怎么设计更合理呢?

支付重构

如果只是重构支付部分,我个人觉得相对容易。因为支付需要的要素比较好抽象,主要是下游支付渠道需要什么。自从有了网联,现在对接方也比较固定了。直接接网联或者微信支付、支付宝支付、拉卡拉…… 他们所需要的要素都差不多。因为它们都要接入网联完成国家监管的需求,所以要素主要看网联需要哪些要素。

当然,它们的签名方式可能会不同;调用的支付渠道地址不同;给支付渠道传递的时候入参组装方式也不同。甚至有的支付渠道还需要有特殊的步骤。这时候怎么抽象呢?

推荐“工作流”+策略模式。这是一种实现积木化的方式。定义一个统一接口,比如

class Executor {

      void execute(Task task);

}

task里放置所有的入参,以及每次执行时产生的,下游需要的中间数据。签名等流程各自实现此接口。这样就实现了自由组装的重用。

举个例子,下面“积木块”各自实现了自己的execute:

微信支付签名、微信支付入参组装、微信支付结果解析、支付宝支付签名、支付宝支付入参组装、支付宝支付结果解析、支付宝特殊处理、下游http调用(这里假设微信和支付宝都是http的post请求来调用的,这样发起调用来说两者只是请求地址和入参不同)

这时候可以组装微信支付流程:

List list = new List();

list.put(微信支付签名);

list.put(微信支付入参组装);

list.put(下游http调用);

list.put(微信支付结果解析);

for(Executor e :list) {

    e.execute(task);

}

同样可以组装支付宝支付流程:

List list = new List();

list.put(支付宝支付签名);

list.put(支付宝支付入参组装);

list.put(下游http调用);

list.put(支付宝支付结果解析);

list.put(支付宝支付特殊处理);

for(Executor e :list) {

    e.execute(task);

}

不同的流程只是list不同,这个list是可以时间配置化的,可以配置在配置文件中、甚至可以从数据库中读取。微信支付流程和支付宝支付流程是两种不同的策略,可以使用策略模式。入参选择哪种策略就用哪种策略执行。这样,各个流程之间没有干扰,积木块变更影响小还可以随意组合灵活性高。

整体重构

朋友的业务复杂性还不在于支付,而在于收单。解决方法就是文章开头提到的接入平台的方式。打造平台的关键不是技术,而是规范。自己制定规范。别人接入都要按照规范来。

这里有前提:公司自身的影响力。平台是底层自己需要有决策权,比如微信开放平台,想接入就要理解并使用他们的API。而因为微信基础在,必须按照人家说的来,这就是平台影响力。

在实际工作中,一般有两种情况。接入方自身也没有什么规范,本身就要求功能可用,这时候咱们自身有规范,对方比较容易接受。另外一种,对方是实力背景的大公司,也有自己的规范。这时候咱们处于弱势,要按照别人的规范来,可以使用上面支付重构的积木化方法进行进行组合。

重构过程与业务支撑之间怎样平衡?

在重构过程中一般会遇到两顶思考帽问题:一顶是需求的帽子,一顶是重构的帽子。有限的时间怎么分配呢?建议一开始就定好目标:什么阶段要重构到什么程度,然后分解工作。最后分摊到每天比如需要2小时时间。那么在需求开发时间评估的时候就要把这个时间扣掉。

重构做完,老逻辑迁移到新逻辑有风险。这时候我的建议是:

首先,把新功能当成重构结果的验金石。有新功能,先在新功能上验证新逻辑的正确性。因为新功能上线到上量有一个过程,初期出了问题影响也不会很大。

然后,老逻辑迁移需要灰度。可以一个业务一个业务的灰度迁移,也可以按照流量百分比进行迁移。

总结

最后总结一下对重构的几点建议:

1、小步快跑,稳步迭代

2、设计与代码的重构结伴而行

3、如果模块或者函数不能想到一个好名字,很可能是设计出了问题

4、每步要保证足够简单,想象随时可能会停止

标签: #知识库 257
相关文章
最全的办公楼智能化解决方案

最全的办公楼智能化解决方案 2024-10-16 08:40

办公楼综合体智能化如何建设?有哪些系统?近几年,办公楼智能化的项目越来越多,不少项目经理都参与其它,同事办公楼综合体也是弱电系统涉及的最多的项目之一,本期我们一起来看下,最全的办公楼项目智能化设计方案。

规范标准查询、下载网站 2024-10-12 16:41

我们在工作中经常需要用到各种各样的规范标准,这里给大家介绍一些免费查询和下载规范的网站,个人亲测可用。 标准查找查新网站 工标网: http://www.csres.com/ 中国国家标准化管理委员会:http://openstd.samr.gov.cn/bzgk/gb/index 全国标准信息公共

【计算机网络】网络层协议解析 2024-10-08 11:24

网络层的两种服务 IPv4 * 分类编址 划分子网 无分类地址 IPv4地址应用 IP数据报的发送和转发过程 * 主机发送IP数据报 路由器转发IP数据报 IPv4数据报首部格式 ICMP网际控制报文协议 虚拟专用网VPN与

FFmpeg教程(超级详细版) 2024-10-08 11:24

一、参考资料 通过ffmpeg把图片转换成视频 FFmpeg命令(一)、使用filter_complex命令拼接视频 FFmpeg 视频处理入门教程给新手的 20 多个 FFmpeg 命令示例 FFmpeg命令行转码

计算机网络:物理层 —— 数据的传输方式 2024-10-08 11:24

文章目录 * 传输方式 * 串行传输 * 串行传输方式 特点 应用 并行传输 * 特点 应用 网卡的串/并转换 同步传输 * 同步时钟频率的误差问题 特点 应用<

授权码机制 V2.1 2024-10-07 10:26

大家好,我是机灵鹤。 根据读者朋友们反馈的问题和建议,对 授权码 V2.0 版本做了一些优化。 优化内容主要解决了以下几个问题: 优化了授权机制中的时间校验逻辑,避免用户通过回调本地时间来绕过授权机制的问题。 封装和简化了授权接口,开发者可以更方便地接入到自己的程序中。

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.