实践开发:老系统新增字段我是如何用枚举优雅兼容历史数据的

背景:

最近在给一个 CRM 系统做升级,新增了一个字段:发票方向(invoiceDirection)。

一开始系统里的发票没区分红冲还是正常,只有一个字段:发票金额。

后来有红冲场景了,我那就简单的说一下红冲:

红冲 = 用一张「负数发票」来冲销一张已经开的正数发票,红冲是财务概念,这里不展开,知道它会导致金额为负就够了。

  • 正常开票

  • 红冲发票(简单理解为:用负数金额冲销原发票)

方案设计:

我最开始的方案(两行代码解决)

我当时的方案非常简单:

  • 金额 > 0:绿色

  • 金额 < 0:红色

前端区分一下展示就行了,两行代码就解决了。

老数据 0 影响,后端 0 改表

说实话,这个方案:简单、直接、完全够用。

if (column.property === 'invoiceMoney') {

const money = Number(row.invoiceMoney || 0)

return money > 0 ? 'xr-money green' : money === 0 ? 'xr-money gray' : 'xr-money red'

}

我到现在也觉得:在这个场景下,其实是 OK 的可能是我经验不足吧。

老大的原话大概意思是:

"颜色只是展示,必须加个字段必须明确区分是不是红冲。加字段。"这不是增加复杂度吗......

但没办法,谁让人家是老大呢 而且你还真不好反驳。

遇到的问题:

字段已经确定要加了,那真正的问题变成:

  • 这是一个 新增字段

  • 历史数据已经存在

  • 不可能全表 update

  • 也不能随便给默认值

如果处理不好,比不加还麻烦

最终方案:我用到了枚举了+兜底处理来处理就数据

  1. 用枚举定义业务边界:

  2. 读数据:不信任数据库,必须兜底

  3. 写数据:通过金额统一推导方向

这样做的好处:用枚举把"发票方向"的业务含义和判断规则集中管理,同时通过兜底逻辑兼容历史数据,避免魔法值扩散,让老系统升级更安全、更可维护。

最后我们在查询的时候做个兜底处理,因为老数据新的字段都是null 就根据发票金额做个兜底是正常开票还是红冲。

private void fillInvoiceDirectionIfAbsent(Map<String, Object> row) {

// 新字段已有值,直接使用

if (row.get("invoiceDirection") != null) {

return;

}

BigDecimal money = Convert.toBigDecimal(row.get("invoiceMoney"), BigDecimal.ZERO);

int direction = InvoiceDirectionEnum.fromMoney(money);

row.put("invoiceDirection", direction);

}

实现的结果:

结语:

这个字段本身,是不是一定非加不可?说实话,我现在依然觉得:不一定。用金额正负 + 前端颜色,

在当时的业务复杂度下,完全可以跑得通。但现实开发里经常是这样:

  • 需求不一定最优

  • 但你得让系统稳住

  • 让历史数据不受影响

  • 让后面接手的人少踩坑

所以最终选择了:

  • 用枚举把业务含义说清楚

  • 用兜底逻辑兼容老数据。

相关推荐
怒放吧德德4 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
雨中飘荡的记忆6 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
心之语歌8 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
华仔啊9 小时前
Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅
java·后端
ray_liang9 小时前
用六边形架构与整洁架构对比是伪命题?
java·架构
Ray Liang11 小时前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解11 小时前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
SimonKing15 小时前
OpenCode AI辅助编程,不一样的编程思路,不写一行代码
java·后端·程序员
FastBean15 小时前
Jackson View Extension Spring Boot Starter
java·后端
Seven9716 小时前
剑指offer-79、最⻓不含重复字符的⼦字符串
java