同城售后系统退款业务重构心得 | 京东云技术团队
一、重构背景
1.1、退款
到家、小时购、天选退款有2套结构,代码逻辑混乱;
其中小时购、天选部分售后单是和平生pop交互退款,部分是和售后中台交互退款;并且兼容3套逻辑;
痛点:代码繁重,缺乏合理性的设计,后续迭代开发以及维护成本高,同时增加了系统的风险和不稳定性
1.2、金额计算
到家、小时购两套独立的逻辑结构计算,在此基础上针对退差和非退差又实现了2套逻辑;
针对商品件维度、商品行维度、售后单维度计算金额混乱,缺乏领域边界和分层设计;
痛点:售后单维度、商品行维度、拆分件维度金额计算混乱,代码缺乏层次结构;代码易读性、维护成本、后续扩展性存在问题
1.3、售后逆向账
售后单详情接口、申诉单详情接口,针对到家和小时购做了两套逻辑;
其中售后单详情接口针对小时购黑名单、小时购白名单、天选、到家退差、到家非退差做了5套逻辑处理;
并且这两个接口都是实时从拆分获取金额进行售后逆向拆分计算,可以直接从数据库中进行取值赋值,不需要进行售后单维度的拆分计算;
痛点:代码大量冗余、改动成本高、增加了系统的风险和不稳定性
二、重构思路和方案
2.1、重构思路
什么是重构呢?
名词:对软件内部结构的一种调整,目的是在不改变软件观察行为的的前提下提高其可理解性、降低其修改成本;
动词:使用一系列手法,在不改变软件可观察行为的前提下,调整其结构
重构的目的是使系统或代码更容易被理解、修改、迭代
重构秘诀:胆大心细
胆大(意味着有勇气和决心去改变和改进现有的代码。重构可能涉及对复杂的代码结构进行修改,甚至可能需要重写部分代码。胆大的开发者愿意面对这些挑战,相信通过改变可以带来更好的结果)
心细(指的是在进行重构时保持细致入微的思考和行动。这包括仔细分析代码的结构和逻辑,理解代码的功能和依赖关系,以及考虑每个重构步骤可能带来的潜在影响。心细的开发者会在重构过程中小心翼翼地处理每个细节,以确保代码的正确性和可维护性)
-
把握好重构时机:当我发现售后退款、金额计算等业务模块代码存在质量问题、可读性差、可维护性差或存在坏味道时,并且在项目需求排期并不紧张的情况下,是进行重构的好时机;
-
前期梳理很重要,先找到痛点 ;不宜长线作战,不宜和业务并行
-
明确出目标和价值:售后退款、金额计算重构后能提高开发效率、降低维护、开发成本等
-
确定重构的目标:首先要明确需要进行重构的代码块或功能,并明确重构的目标是什么。例如,可能需要提高代码的可读性、可维护性或性能。
-
分析代码坏味道:使用代码静态分析工具或手动检查代码,识别出可能存在的代码坏味道;例如退款业务中存在1000多行的类、600多行的方法,过多的变量参数、诸多重复代码等代码坏味道。
-
选择适当的重构技术:根据售后代码坏味道的种类和重构的目标,选择适当的重构技术。我采用的重构手法是:小规模重构–>大规模重构–>顶层设计模式;采用先小后大,从大到全的思路进行重构设计。小规模重构:提取方法、消除超大类或函数方法、提取类、重命名、合并重复代码等方法;大规模重构:采用的是分层、模块化、解耦、抽象可复用性等手法;设计模式:退款业务采用策略模式+抽象工厂;金额计算业务采用策略模式+抽象工厂+责任链模式
-
编写测试用例:在进行重构之前,编写适当的测试用例来验证重构后的代码的正确性。测试用例应该覆盖重构的代码块或功能的各种情况。
-
执行重构:根据选择的重构技术,逐步修改代码。确保每次修改后的代码仍然通过之前编写的测试用例。
-
运行测试用例:在每次重构之后,运行之前编写的测试用例,确保重构后的代码仍然正确。
-
重构后的代码评估:评估重构后的代码是否达到了预期的目标,例如是否提高了代码的可读性、可维护性或性能。
2.2、重构方案
2.2.1、重构前系统交互图

2.2.2、重构后系统交互图

退款业务强耦合到售后系统中,并且业务代码分散到各个业务层,严重缺乏系统的领域边界和分层设计,重构后退款业务逻辑不强依赖售后核心业务逻辑,做到可以独立部署。
2.2.3、重构前金额计算流程图

2.2.4、重构后金额计算流程图

将2套金额计算业务逻辑利用设计模式将其合并为1套金额计算业务逻辑,打造防腐层
2.3、重构设计类图
依据上述制定的设计方案流程图,我进行了UML类图的绘制,以下是关于金额计算业务模块的类图
2.3.1、抽象工厂+策略模式类图

2.3.2、责任链模式类图

三、系统稳定性保障
3.1、小步重构
将售后重构分成退款、金额计算、逆向账三个步骤,并在每个步骤之后运行测试用例。这样可以及时发现并修复引入的错误,避免错误在整个系统中蔓延
3.2、逐步验证
在每个重构步骤之后,进行系统的逐步验证。分批次进行上线灰度,灰度配置绝对隔离,不能复用。确保系统的各个部分在重构过程中都能正常运行,并与其他部分协调良好。
3.3、监控和性能测试
在重构完成后,进行系统的监控和性能测试,确保重构没有引入性能问题或影响系统的稳定性。如果发现问题,及时进行修复和优化。
3.4、团队代码审查和测试
在进行重构时,与团队成员进行合作,并进行代码审查。多个人的视角和经验可以帮助发现潜在的问题,并提供改进的建议;针对重构代码进行深度解刨,能更有效地保障重构的安全性。
重构业务及时通知测试人员,使测试人员能够评估到测试点,更加完善测试用例
3.5、灰度步骤
3.5.1、bcp持续比对校验

3.5.2、按照商家灰度
依据售后单量 小->中->大 的顺序逐步进行灰度切量,观察其退款、金额计算等售后单数据是否异常
四、重构成果
-
降低开发、维护成本
-
提升代码质量、系统稳定性
-
系统扩展性和灵活性的加强;
-
系统应用、业务边界定位更加清晰
-
统一和规范售后核心业务脉络,降低业务学习成本,提升开发效率
-
提升自己的技术能力、代码质量意识、问题解决能力、团队合作和沟通能力;经典著作《重构》这本书中有这么一段话:
一开始,我所做的重构都停留在细枝末节上。随着代码趋向简洁,我发现自己可以看到一些设计层面的东西了,这些是我以前理解不到的,如果没有重构,我达不到这种高度
五、code show
5.1、重构前金额计算
到家售后单金额计算service方法

京东售后单金额计算service方法
一个大的金额计算class类就有1000多行代码,每个方法中都有几百行代码,以下是到家售后单金额计算部分代码

5.2、重构后金额计算
到家和京东售后单金额计算用同一个接口才承接业务实现,并且使用策略+抽象工厂模式实现到家、小时购、天选业务的金额计算

策略模式获取金额拆分结果集

金额计算核心方法只有4步骤

其中金额计算的核心则采用的是责任链业务进行计算

在件维度、sku维度针对不同的业务又采用了责任链模式进行金额计算

六、参考文献
代码的坏味道: https://www.qinglite.cn/doc/87036476d565d55f9
《重构改善既有代码的设计》:[美]MartinFowler
《敏捷软件开发》:[美]RobertC.Martin
作者:京东零售 高凯
来源:京东云开发者社区 转载请注明来源
相关文章:
同城售后系统退款业务重构心得 | 京东云技术团队
一、重构背景 1.1、退款 到家、小时购、天选退款有2套结构,代码逻辑混乱; 其中小时购、天选部分售后单是和平生pop交互退款,部分是和售后中台交互退款;并且兼容3套逻辑; 痛点:代码繁重,缺乏…...
【计算机网络笔记】TCP连接管理(图解三次握手和四次挥手)
系列文章目录 什么是计算机网络? 什么是网络协议? 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能(1)——速率、带宽、延迟 计算机网络性能(2)…...
C++ 初阶 类和对象(中)
前言:C初阶系列,每一期博主都会使用简单朴素的语言将对应的知识分享给大家,争取让所有人都可以听懂,C初阶系列会持续更新,上学期间将不定时更新,但总会更的 目录 一、构造函数 1.1为什么要有构造函数&…...
【漏洞复现】Metinfo5.0.4任意文件包含漏洞复现
感谢互联网提供分享知识与智慧,在法治的社会里,请遵守有关法律法规 文章目录 1、蚁剑直接连接图片马2、读取敏感目录3、读取php源码4、执行PHP命令5、包含木马写Shell (图片马制作新方法) 以 metinfo_5.0.4为例 该环境的文件上传…...
【计算机网络实验/wireshark】tcp建立和释放
wireshark开始捕获后,浏览器打开xg.swjtu.edu.cn,网页传输完成后,关闭浏览器,然后停止报文捕获。 若捕获不到dns报文,先运行ipconfig/flushdns命令清空dns缓存 DNS报文 设置了筛选条件:dns 查询报文目的…...
STM32:I²C通信原理概要
一、IIC通信原理 IIC通信和串口通信有一定的相似之处,都有一根共地线和两根数据线。但是传递外部信息,串口有两根数据线可以进行双向通信,也就是全双工通信。而在IIC通信下,其中一条数据线是用于提供同步时钟脉冲的时钟线(SCL)&am…...
【开题报告】基于 Spring Boot 的在线预约导游系统的设计与实现
1.引言 在旅游行业中,导游起到了重要的作用,他们为游客提供了专业的旅游服务和相关信息。然而,传统的导游预约方式可能存在一些问题,如信息不透明、预约流程繁琐等。因此,我们计划开发一个基于 Spring Boot 的在线预约…...
如何使用ps制作ico图标文件
如何使用ps制作ico图标文件 Chapter1 如何使用ps制作ico图标文件Chapter2 ICOFormat.8bi(Photoshop Ico、Cur插件)的下载使用1. ICOFormat.8bi的作用2. ICOFormat.8bi使用 Chapter3 ps手机计算机图标教程,手绘设计精美手机APP软件图标的PS教程步骤 01 制…...
【Linux】logrotate实现“日志文件定时分割“
问题背景 项目部署的过程中,经常会需要查看程序的执行日志。我之前的做法都是用nohup ... > xxx.log 2>&1 &将日志保存到xxx.log文件中的。但是问题是,程序有时会运行很长时间,一直保存在一个文件里,文件会越来越大…...
Android可绘制资源概览(背景、图形等)
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。 目录 一、导读二、概览三、drawable 分类3.1 Bitmap fileXML …...
力扣2095.删除链表的中间节点(java快慢指针)
Problem: 2095. 删除链表的中间节点 文章目录 思路解题方法复杂度Code 思路 利用快慢指针,快指针每次走两步,慢指针每次走一步(循环退出条件是fast指针不为空同时fast.next不为空),但是我们容易发现这样到最后slow指针…...
【Vue-Element-Admin】table添加自定义索引
通过给 typeindex 的列传入 index 属性,可以自定义索引。该属性传入数字时,将作为索引的起始值。也可以传入一个方法,它提供当前行的行号(从 0 开始)作为参数,返回值将作为索引展示。 <el-table:data&q…...
0008Java安卓程序设计-ssm基于Android平台的健康管理系统
文章目录 **摘要**目录系统实现开发环境 编程技术交流、源码分享、模板分享、网课教程 🐧裙:776871563 摘要 首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,…...
Mac 禁用一些高占用cup的进程
什么是CrashReporter? CrashReporter在应用程序崩溃的任何时候都会运行,它旨在保存应用程序状态,以帮助开发人员找出应用程序崩溃原因。基本上,一个进程是启动、崩溃(并调用CrashReporter),然后…...
layui form表单 调整 label 宽度
这个可以调整所有label .layui-form-label {width: 120px !important; } .layui-input-block {margin-left: 150px !important; }情况是这样的,表单里有多个输入框,只有个别label 是长的,我就想调整一下个别长的,其它不变 <di…...
轻量封装WebGPU渲染系统示例<12>- 基础3D对象实体(源码)
当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/main/src/voxgpu/sample/PrimitiveEntityTest.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 细节请见:引擎系统设计思路 - 用户态与系统态隔离-CSDN博客 2. 高频调用与低频调用隔…...
[ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
业务需求:需要做到table表格中某些行数据不能被选中,比如在审核一些记录数据时,已经被审核的数据就不能再次提交审核,特别是批量多选的情况,列表中既有已经审核的,也有未审核的,只要求选中未审核…...
【PY】倒计时日历
大家有时候会不会觉得时间记不住呢?PY倒计时日历可以满足你。 main.py: from tkinter import Tk,Canvas from datetime import date,datetime def get_events():list_events[]with open(events.txt)as file:for line in file:lineline.rstrip(\n)curre…...
windows mysql安装
1、首先去官网下载mysql安装包,官网地址:MySQL :: Download MySQL Community Server 2:把安装包放到你安装mysql的地方,然后进行解压缩,注意,解压后的mysql没有配置文件,我们需要创建配置文件 配…...
【蓝桥杯省赛真题42】Scratch舞台特效 蓝桥杯少儿编程scratch图形化编程 蓝桥杯省赛真题讲解
目录 scratch舞台特效 一、题目要求 编程实现 二、案例分析 1、角色分析...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
