代码之丑-隐式逻辑


本系列用来收集一些工作中常见的丑陋代码。

实例分析

起因

  1. 初始实现: 经验丰富的A同学封装了一个经典的安全除法函数:

    func SafeDivideFloat64(dividend, divisor float64) float64 {
     if divisor == 0 {
         return 0
     }
     return dividend / divisor
    }

    这个实现简洁明了,功能符合函数名称。

  2. 需求变更: B同事为满足特定需求,修改了函数实现:

    func SafeDivideFloat64(dividend, divisor float64) float64 {
        if divisor == 0 {
            return 0
        }
        return math.Round(dividend / 1000 * 1000 / divisor)
    }

    修改引入了舍入操作,改变了函数的基本行为。

  3. 命名问题: 虽然功能发生了变化,但函数名未作相应调整。理想情况下,应改名为如SafeDivideFloat64R3。

影响

  1. 广泛的使用范围
    • SafeDivideFloat64 函数在60多个文件中被使用,影响范围广泛。
  2. 精度问题
    • 单次使用:在接口返回时,影响相对可控。
    • 多次使用:在复杂计算中多次调用,可能导致精度累积误差。
    • 潜在风险:在大额计算或比例转换时,微小的精度差异可能引发严重的结果偏差。
  3. 认知和使用风险
    • 新同事认知盲点:
      • 容易忽视函数的隐含逻辑。
      • 可能误认为是简单的安全除法,忽略舍入操作。
    • 熟悉代码同事的潜在错误:
      • 在疲劳或压力下可能疏忽,误解函数行为。
    • 望文生义陷阱:
      • 函数名暗示简单除法,易导致错误假设。
      • 即使经验丰富的开发者也可能在快速浏览时误解。
  4. 长期维护挑战
    • 知识传递断层:随时间推移,了解修改原因的人员可能离开或遗忘细节。
    • 使用风险增加:由于知识传递不足,错误使用的可能性随时间增加。

处理方式

  1. 函数重命名与新函数实现
    • 将现有的 SafeDivideFloat64 重命名为 SafeDivideFloat64R3
    • 实现新的 SafeDivideFloat64 函数,保持原始的安全除法逻辑
  2. 废弃旧函数
    • 标记 SafeDivideFloat64R3 为废弃(deprecated)
    • 添加注释说明潜在风险和使用注意事项
    • 使用编译器警告或代码分析工具标记,便于识别需要替换的调用
  3. 新代码规范
    • 在新编写的代码中,严格使用 SafeDivideFloat64
    • 禁止在新代码中使用 SafeDivideFloat64R3
  4. 渐进式替换策略
    • 制定计划,逐步替换现有代码中的 SafeDivideFloat64R3 调用
    • 优先处理关键业务逻辑和高频调用的部分
  5. 文档和培训
    • 更新技术文档,清晰说明两个函数的区别和使用场景
    • 对团队进行培训,确保所有成员了解这一变更及其重要性

如果本文帮助到了你,帮我点个广告可以咩(o′┏▽┓`o)


评论
  目录