一次重构不够,我们又推倒重来:电子面单架构的两次升级

一次重构不够,我们又推倒重来:电子面单架构的两次升级

摘要:本文完整复盘了多平台电子面单取号引擎从"能跑就行"的杂烩式大方法,到第一次策略模式雏形(已上线),再到当前流程编排+策略模式彻底解耦(含抖音接入)的两次架构升级历程。阐述了每次升级的动机、解决的问题、遗留的局限,以及最终带来的开发效率提升与线上风险降低。
📖 系列导航


很多架构重构做完就结束了。但我们的电子面单引擎,重构完上线后,发现接第二个平台时又卡住了。于是有了第二次重构。

这篇文章复盘这两次升级的全过程------不只是技术选型,更是对"什么时候该重构、什么时候该停手"的思考。


文章目录


一、老代码时代:一个方法统治所有

1.1 代码形态

最早期的电子面单取号逻辑,全部集中在一个超过 500 行的大方法中(getQiMenWaybill)。这个方法集请求构建、API调用、响应解析、持久化、异常标记于一身。

java 复制代码
// 伪代码:一个方法做了所有事
public void getWaybill(TocWmsPickTicket ticket) {
    // 100+ 行:构建奇门请求
    // 50+ 行:调用淘宝SDK
    // 100+ 行:解析响应JSON
    // 80+ 行:保存运单、绑定工作单
    // 50+ 行:异常处理
}

1.2 核心痛点

  • 新增平台必须改核心代码 :每接入一个平台(如从奇门扩展到抖音),都要在这个大方法中增加大量 if-else 分支,代码快速膨胀。
  • 一个平台改动影响所有平台:修改奇门的请求逻辑,可能误伤抖音的解析逻辑。
  • 测试需要全量回归:任何一个改动,都必须测试所有已接入平台,回归成本极高。
  • 配置硬编码:AppKey、Secret、Token、常量等散落各处。
  • 性能隐患:包裹循环内重复查询数据库。

🏭 设计模式视角 :这种"上帝方法"是典型的违反单一职责原则(SRP) 的反面教材------一个类承担了太多职责,任何一个维度(平台、快递、流程)的变化都会导致修改,维护成本随功能增长指数级上升。在《Java 23种设计模式:从踩坑到精通》系列中,我详细拆解了六大设计原则如何指导架构演进,欢迎延伸阅读。


二、第一次升级:策略模式雏形(已上线)

2.1 升级目标

将奇门平台的取号逻辑从"大方法"中解耦出来,为后续接入新平台打下基础。

2.2 核心改动

引入"模板方法+三层策略"的雏形架构,将取号流程抽象为固定的步骤,各平台的差异通过接口实现来隔离。

2.3 第一次升级后的静态结构

下图展示了第一次升级后的类关系:虽然有了策略接口和模板编排器,但策略实现类内部仍混杂了持久化和异常标记等逻辑,策略工厂也仅使用单维度 platformCode 作为路由 Key。

2.4 第一次升级的时序流程

从动态视角看,第一次升级已经建立起了"构建→调用→判断→解析"的标准流程骨架,但各步骤内部的职责划分尚不纯净。

2.5 解决的问题

维度 改造前 改造后
代码组织 500+ 行大方法 模板方法 + 策略接口,职责分离
奇门维护 与其他平台逻辑混杂 独立策略实现,可单独修改
代码复用 模板骨架复用
测试范围 全量回归 仅需测试变更平台

2.6 遗留的局限

第一次升级只完成了奇门一个平台的改造,当需要接入抖音时,以下问题暴露出来:

1. 策略工厂路由仅用单一编码

StrategyFactory 使用 platformCode 作为 Map Key,导致抖音普通和代发策略互相覆盖:

java 复制代码
requestMap.put("DY", new DouYinRequestStrategy());        // 普通
requestMap.put("DY", new DouYinDaiFaRequestStrategy());   // 代发(覆盖了上面)

2. 解析器混杂持久化逻辑

QiMenResponseParserDouYinResponseParser 内部都包含了 commonDao.storemarkTocAuditExceptionbindTocWorkDocAndWayBill 等非解析操作。新增平台时这些逻辑被复制粘贴,维护成本高。

3. 顺丰子母件逻辑未完全解耦

顺丰超过10件需要分批取号的逻辑,仍然部分散落在策略层,未彻底迁移到编排层。

4. 配置硬编码与常量散落

AppKey、Secret 硬编码在代码中,平台编码、上下文 Key 等魔法字符串散落各处。


三、第二次升级:流程编排+策略模式彻底解耦(当前)

3.1 升级动机

接入抖音平台时,第一次升级的局限集中爆发:策略路由覆盖、解析器越权、硬编码维护困难、常量散落导致修改遗漏。如果不彻底重构,后续接入京东、拼多多等十余个平台时,维护成本将呈指数级增长。

3.2 核心改动

1. 复合Key路由

引入 platformCode + "_" + platFormOriginal 复合 Key,与 ApiInvoker 路由规则统一。将 Key 构建方法收口到 TocWmsSourcePlatFormType.buildCompositeKey

java 复制代码
// 改造前:单维度,互相覆盖
requestMap.put("DY", new DouYinRequestStrategy());
requestMap.put("DY", new DouYinDaiFaRequestStrategy());

// 改造后:复合Key,各自独立
requestMap.put("DY_DEFAULT", new DouYinRequestStrategy());
requestMap.put("DY_DF", new DouYinDaiFaRequestStrategy());

2. 解析器职责净化

将持久化、异常标记、工作单绑定全部移出解析器,收口到 WaybillPersistence 和模板层。解析器只做纯数据转换。

3. 顺丰子母件逻辑归位

将分批取号逻辑从策略层迁移到 WaybillFetchTemplate.executeSFMoreTen 中,由编排层统一控制流程。

4. 前置校验体系

引入 LogisticsSupportable 接口,门面层在请求构建前校验平台是否支持指定快递公司。错误信息中文化,运营自助排错。

5. 性能优化

将包裹循环内的数据库查询提升到循环外一次性执行,通过 WaybillContext 透传结果。N包裹订单的查询次数从 N 降到 1。

6. 常量统一管理

将平台编码、上下文Key、快递公司编码等常量统一到 TocWmsSourcePlatFormTypeTocWmsExpressType 中,并增加编码到中文名称的映射方法。这一部分的详细内容见下一篇《平台常量和配置管理:从散落魔法字符串到集中管控》。

3.3 第一次升级 vs 第二次升级:核心差异

维度 第一次升级(策略模式雏形) 第二次升级(流程编排+策略解耦)
策略接口 定义了三个接口,但实现类内部混杂了持久化、异常标记等逻辑 策略实现类纯粹,只做请求构建/响应解析/异常判断
解析器 QiMenResponseParser 内部调用了 commonDao.storemarkTocAuditException 所有持久化和异常标记全部移出,解析器只做纯数据转换
工厂路由 单维度 platformCode 作为 Key,抖音普通和代发互相覆盖 复合Key platformCode + "_" + platFormOriginal,精确路由
持久化 散落在各解析器中,每个平台重复实现 统一收口到 WaybillPersistence,全平台复用
前置校验 引入 LogisticsSupportable 接口,门面层统一校验
子母件 部分逻辑散落在策略层 完全迁移到 WaybillFetchTemplate.executeSFMoreTen,编排层统一控制
常量管理 散落各处 统一到 TocWmsSourcePlatFormTypeTocWmsExpressType
新增平台 需要修改工厂 + 复制解析器中的持久化代码 只需新增三个纯策略类 + 注册配置

3.4 第二次升级后的静态结构

下图展示了第二次升级后的核心类图。与第一次升级相比,最关键的三个变化是:策略实现类不再触碰持久化工厂路由升级为复合Key子母件逻辑完全由模板层控制

3.5 第二次升级后的时序流程

从时序图可以看到,解析器不再执行任何持久化操作,所有保存动作统一由 WaybillPersistence 在流程末端完成,异常标记也收口到了模板层的 markException 方法。


四、两次升级综合收益对比

维度 老代码 第一次升级 第二次升级
新增平台工作量 改核心代码,5-6天 新增3个策略类,3-4天 新增3个策略类+注册配置,1-2天
核心流程代码行数 500+行 约150行 约100行
代码复用率 <30% 约60% 约85%
数据库查询次数 包裹数×N次 包裹数×N次 1次
配置变更方式 改代码+重新部署 改代码+重新部署 改配置/数据库,分钟级生效
错误信息清晰度 "系统异常" 部分清晰 精确透传,自助排错
平台间影响 全量回归 工厂改动可能影响 完全隔离
独立部署能力 强耦合 强耦合 可拆分为微服务

五、当前架构全景


六、系列导航与参考

本篇文章是「电商多平台电子面单对接实战」的第十二篇(架构复盘篇),完整记录了电子面单取号引擎的两次架构升级历程。

系列文章目录


延伸阅读:Java 23种设计模式实战系列

本文中两次架构升级的核心推动力,是六大设计原则策略模式、模板方法模式、工厂模式的组合应用。在《Java 23种设计模式:从踩坑到精通》系列中,这些原则与模式有更体系化的拆解。如果你对以下问题感兴趣,推荐延伸阅读:

  • 策略模式 vs 模板方法模式:何时用策略替换算法,何时用模板固定骨架?
  • 工厂模式:简单工厂、工厂方法、抽象工厂,如何在架构演进中逐步升级?
  • 六大设计原则:开闭原则、单一职责、依赖倒置......它们如何指导每一次重构决策?

📖 《Java 23 种设计模式:从踩坑到精通》


七、一起交流,共同进步

架构演进从来不是一蹴而就的,第一次升级为第二次升级铺了路,第二次升级为未来十余个平台扫清了障碍。如果你也在做类似的架构重构,希望这个真实的演进历程能给你一些启发。

第一次重构教会我们"怎么拆",第二次重构教会我们"怎么拆得对"。架构演进从来不是一蹴而就,而是在正确的方向上逐步逼近。

  • 📌 关注我 :点击上方"关注",第一时间获取系列更新推送。
  • 💬 留言讨论:您在项目中有过"第一次重构后发现不够彻底,又进行了第二次升级"的经历吗?是什么驱动了第二次升级?欢迎在评论区分享。
  • 🔗 分享转发 :如果本文对您有帮助,请 点赞收藏分享,让更多同行看到。