封面图:开启代理后流畅展示

在 Martin Fowler 的 《重构》一书的首页里有一句古老的工程谚语:

“if it works, don't fix it?”

一、为什么要重构?

当时我们的智能仓储核心系统(WES)面临三个关键痛点 :

  1. 领域边界模糊、迭代困难,比如说单据调度业务部分逻辑存在于两个系统里面;
  2. 二是核心链路是 “黑盒”,数据不一致、故障定位难,年均故障工单过万;
  3. 三是公司在扩张期,尤其是海外项目(日本、东南亚、美国等)交付压力大,原有系统支撑不了多区域业务需求。所以启动了全业务分阶段重构,目标是提升系统稳定性、可维护性,支撑海外项目交付。

二、我们重构阶段历程是怎样的?

其实主要分为三个大版本:2.9、2.10、21.11

  • 2.9 版本:WES 收拢了单据调度业务,将单据调度业务从 WCS 上浮到 WES
  • 2.10 版本:WES 将货架到人系统与料箱到人系统合并为一套系统,并支持多库区混合调度。
  • 2.11 版本又分为 8 个小版本,从 2.11.1 到 2.11.8,从 2.11.1 到 2.11.6 做了核心链路的梳理和重构,2.11.5 到 2.11.6 围绕核心链路做了许多补充,2.11.7 到 2.11.8 做了一些代码优化与性能优化。

三、重构的具体方法与策略

1、重构前的准备:

  • 需求与业务梳理:我们做了类似事件风暴的会议,团队内的人都聚在会议室里,上午开会交流历史业务,下午写文档,最后梳理出了几百份文档和图表,基本上把核心链路都梳理清楚了。
  • 技术选型:我们没有大改技术架构,核心框架基本上维持了 SpringCloud 这一套,MySQL 从 5.7 升级到 8.0,RocketMQ 从 4.3 升级到 4.9,引入了 XXL-JOB和动态线程池,后期我写了一个数据一致性组件以及任务流转树监控系统。

2、重构中原则和步骤:

  • 模块化与解耦,领域划分:WES 这边主要负责单据调度和实操相关的内容
  • 渐进式重构:按业务模式迭代,一次新增一个主业务模式,尽量小步快跑。
  • 代码规范与可维护性:基本上按照阿里巴巴 Java 开发规范,本地使用阿里巴巴规约插件,远程使用 Sonar 扫描
  • 所有的大于一天工时的需求都要写dev design,组内阅读或评审。
  • 开发流程包括:需求评审、技术设计文档评审、测试用例评审、代码评审、研发自测、测试同学测试、仿真压测、现场真车测试、现场真车压测

四、我负责了哪些事情?

业务上:

  • 独立负责了 2.9 的理货单据调度业务上浮,包括表迁移,代码迁移,与下游团队沟通并确定数据交互形式。
  • 参与了 2.10 版本的系统合并,比如货架到人在线拣选与料箱到人在线拣选,做了一些表结构的共用,比如出库单表、出库单明细表、出库作业单表、出库作业单明细表,但是对于任务表依旧是分开的,考虑到任务涉及到调度实体,也就是料箱、料格和货架,混用一张表,会增加理解成本,并且单业务模式,会造成许多空字段,显得有些冗余。
  • 核心负责了 WES 多种业务模式的调度链路,比如料箱到人的组箱、上架链路,出库的全链路,理货的上架、下架链路,全盘的全链路。

技术上:

  • 业务数据监控:从0 到 1 独立负责了任务流转树监控系统开发与维护。
  • 核心链路节点的数据一致性保障:从0 到 1 独立负责了数据一致性组件的开发与维护。
  • 系统性能优化与瘦身:通过解决JVM内存泄漏、清理无用代码、优化慢查询与缓存、重构代码坏味道(如长方法、循环内DB操作)等措施,使死锁、锁超时、计算错误等线上顽疾基本归零。
  • 设计模式:通过提取公共抽象、应用模板方法等设计模式,对大量重复代码进行整合与重构,提升了代码复用性和可维护性。
  • 参与接入了 XXL-JOB 和动态线程池框架。