博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

程序设计:如何优雅地处理相似的业务数据

Posted on 2026-10-22 19:47  xuld  阅读(0)  评论(0)    收藏  举报

问题背景

业务中,经常需要处理很多相似的数据,这些数据的逻辑有的一样,有的不一样。

比如,聊天消息的数据:

[
    {kind: "文字", text: "..."},
    {kind: "图片", url: "..."},
    {kind: "图文", url: "...", text: "..."},
    {kind: "语音", url: "..."},
    {kind: "文件", url: "..."},
]

最简单粗暴的做法就是对每种数据写一个处理函数,但又发现某些数据类型的处理逻辑是一样的,如果分开写又会出现大量重复代码。

比如示例中,带 url 的数据都需要下载。

解决思路一

将处理逻辑封装成一个哈希表配置,查表解析,比如:

{
    "文字": data => { },
    "图片": data => { },
    "图文": data => { },
    "语音": data => { },
    "文件": data => { }
}

之后,根据数据的类型,从配置中提取针对它的处理函数,驱动流程执行。

数据通用的处理逻辑则放在配置外统一实现。

但这个思路的问题是只能提取统一的逻辑,并不能将某些相似的逻辑提取出来。

解决思路二

基于标记的统一配置,将所有数据按特性打上不同的标记,然后有相同标记的数据统一处理,比如:

if (hasText(data)){
    // ... 这里处理文字和图文
}

if (hasUrl(data)){
    // ... 这里处理图片、图文、语音、文件
}

这是思路一的改良版,支持批量处理相同特性的数据,规避了重复代码。

不过这个思路有两个隐藏的缺点:

1. 一个数据的处理流程被强行拆到了不同地方,很难清晰看出来完整的处理流。如果已知某类数据的处理结果有 BUG,很难定位是在哪个环节出错的。

2. 当需求变更时,原有的标记可能要调整,但调整标记后影响整个处理流程,对代码不熟的后来者大概率会选择跳过标记,直接根据类型作一些特殊处理,导致代码比较混乱。

使用标记的配置方式,看上去非常绝妙,但只有作者会当成非常优雅的设计,却会在接手者中成为难以维护的古老代码。

解决思路三

利用面向对象的多态,为不同的子类实现不同的函数,这个方案的问题是:无法解决某些数据共用一套业务逻辑的场景,因为类是单继承的。

解决思路四

我认为解决这类问题,最优雅的方式还是回归原始,强制分开处理不同的数据:

match (kind) {
   case "文字": 
        // 处理文字
   case "图片": 
        // 处理图片
   case "图文": 
        // 处理图文
   case "语音":
        // 处理语音
   case "文件": 
        // 处理文件
}

如果每个类型的处理逻辑比较复杂,可以拆分成不同的处理函数。

那将回到原点了,怎么避免重复的处理代码?

方案很简单:需要复用的逻辑提取成公共函数:

match (kind) {
   case "文字": 
        processText(data)
   case "图片": 
        processUrl(data)
   case "图文": 
        processText(data)
        processUrl(data)
   case "语音":
        processUrl(data)
   case "文件": 
        processUrl(data)
}

这样,每个数据的处理流程非常清晰,且可以随意修改,不影响其他数据类型。

如果新增一种数据类型,既可以复用已有的业务逻辑,又可以单独写。

全程没有黑魔法,也没有面向对象中复杂的概念,也不需要记忆各自配置、通用规则。

我认为这是首先应该采用的,最朴素却又最能解决问题的方案。