编程中的拐杖——是什么、原因及何时合理

作者: IT Sectr 发布日期: 2026-07-31 阅读时间: 7 分钟

“打补丁”或“用拐杖支撑”——意味着创建一个临时解决方案来解决问题,它可以修复bug或添加功能,但不能消除根本原因,也不符合项目的架构标准。拐杖在任何开发中都不可避免:截止日期、对系统的不完全理解以及外部限制迫使人们做出妥协决定。根据Refactoring Guru,实用拐杖与技术债务之间的关键区别在于决策的自觉性以及是否有消除计划。正确使用临时解决方案需要纪律和文档记录。

要点

  • 打补丁——编写临时解决方案,在不进行根本性修复的情况下关闭问题
  • 拐杖因截止日期、对系统的不完全理解或外部依赖而产生
  • 有意识的拐杖——有文档记录原因和消除计划的临时解决方案
  • 技术债务在拐杖未被修复且永远留在代码中时积累
  • 在打补丁之前,至少考虑一种替代方法

编程中的“拐杖”是什么

拐杖(crutch)——一种能工作但“仓促完成”的软件解决方案:它解决特定问题但不消除其原因,不遵循项目架构,并可能在环境发生最微小变化时崩溃。这个比喻很精确——就像真正的拐杖一样,这样的代码帮助“行走”,但不能治愈“腿”。

开发人员用拐杖“支撑”bug、版本不兼容、平台特性和紧急客户需求。典型的拐杖——拐杖条件:如果是iOS 15就添加间距,如果是华为就隐藏按钮。这样的检查会成倍增加,将代码变成由平台和版本分支构成的“千层饼”。

拐杖可能规模不同:从一行拐杖条件到整个中间层模块“修复”库的行为。重要的是要理解,拐杖并不总是坏事:在正确的人手中,它是允许按时发布产品的工具。问题始于拐杖永远留在代码中。

为什么会出现拐杖:原因和背景

主要原因是理想解决方案与项目实际限制之间的冲突。开发人员知道如何正确地做,但时间、金钱或技术限制不允许。结果产生了“只是能用”的折衷方案。

让我们看看开发人员有意使用拐杖的四个主要原因。理解这些原因有助于将拐杖视为需要管理的实用工具,而不是错误。

截止日期

最常见的原因。发布明天,bug仅在特定型号上重现,架构修复需要两周时间。拐杖条件需要一小时并关闭问题。发布后,团队承诺回来并正确重写。“没有什么比临时更永久的了”——正是关于这种拐杖。

版本不兼容

库A需要Android 12,但您的应用支持Android 10。解决方案——编写中间层来检查操作系统版本并选择执行路径。这是拐杖,因为更新库时中间层需要重写。但替代方案——放弃库或旧设备支持——可能更糟。

kotlin
// 用于API 29兼容性的拐杖
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    useModernApi()
} else {
    useLegacyFallback()
}

有bug的外部依赖

项目依赖的库包含bug,但其更新可能需要数周(需要PR、代码审查、发布)。与其等待,团队编写包装器来动态修补库的行为。修复后的库版本发布后,包装器被删除。如果不删除——这已经是架构问题。

对系统的不完全理解

遗留项目中的新开发人员不理解为什么代码按这种方式工作。他们不是去弄清楚,而是在现有条件之上添加新条件。这是最危险的拐杖类型,因为作者没有意识到这是拐杖。唯一的解决办法——代码审查和团队新成员的结对编程。

何时拐杖合理:实用方法

并非每个拐杖都是坏事。在实际开发中,代码绝对纯净是不可实现的,而且通常不切实际。实用方法承认临时解决方案是过程的一部分,但要求自觉性、文档记录和消除规划。当拐杖比纯粹的架构解决方案更快地解决业务任务时,它就是合理的。

合理拐杖的标准:解决特定问题,有所有者(谁负责删除它),并且存在重构计划。如果三个条件中至少有一个不满足,拐杖就变成技术债务。像TODO注释配合跟踪器中的ticket这样的工具——是最小限度的文档记录方式。

合理拐杖的例子

发布分支中的关键bug,需要在明天部署前关闭。纯粹解决方案需要架构重构,耗时两周。拐杖——添加nil检查并将修复作为热修复发送。合理条件:在跟踪器中创建了重构ticket,指定了负责人,拐杖用注释标记。两周后团队回到任务。

swift
// TODO: IT-1234 — 在AuthService重构后删除此拐杖
guard let userId = session.user?.id else {
    return Result.failure(.notAuthenticated)
}

如何区分临时拐杖与架构问题

有意识的拐杖与架构问题(技术债务)之间的界限通过两个参数划分:决策的自觉性和消除计划的存在。拐杖总是具有已知寿命的临时解决方案。技术债务——许多被忽视的拐杖的后果。

参数有意识的拐杖技术债务
意识团队知道这是临时解决方案没人记得为什么代码是这样的
文档有TODO、跟踪器中的ticket没有注释、链接、描述
消除计划指定了重构的sprint“总有一天我们会重写”
影响局部的,不妨碍新功能阻塞变更,拖慢开发

拐杖何时成为问题

当拐杖数量超过临界质量时,情况恶化。每个新拐杖都增加系统的“脆弱性”:一个地方的变更破坏另一个地方。结果开发变慢,bug成倍增加,新开发人员无法在没有作者帮助的情况下理解代码。此时拐杖不再是临时解决方案,而是架构问题。

拐杖危机的迹象

如果代码中有五个嵌套检查针对操作系统版本、设备制造商和特定库的存在——这不是拐杖,这是架构问题。如果一个修复的添加导致相邻模块出现三个回归——拐杖不再是局部的。如果代码审查因“又一个拐杖”而被定期拒绝——是时候计划重构了。

  • 同一个拐杖在三个或更多地方重复——是时候统一解决了
  • 拐杖存活超过三个sprint而没有消除计划——这已经是技术债务
  • 新开发人员不明白代码为什么这样工作——拐杖没有文档记录
  • 删除拐杖引发连锁反应错误——对拐杖的依赖已变得架构化

重构拐杖:策略与实践

重构拐杖——用架构上正确的方案替换临时解决方案的过程。这需要时间,因此需要优先级排序策略:并非所有拐杖都需要立即消除。好的策略——根据两个参数评估每个拐杖:该代码区域的变更频率和对用户的影响。

优先级排序策略

高优先级——经常变更的模块中的拐杖(业务逻辑、通用UI),它们拖慢开发并导致回归。中优先级——很少变更但可能影响用户的模块中的拐杖(支付处理、授权)。低优先级——遗留代码中的拐杖,稳定运行且不计划修改。

逐步消除过程

步骤1:清点——找到所有与拐杖相关的TODO和FIXME。步骤2:评估——确定哪些仍然相关。步骤3:规划——将拐杖重构安排到sprint中,从高优先级开始。步骤4:替换——实施纯粹解决方案,删除拐杖及其TODO注释。步骤5:验证——确保测试通过且没有回归。

bash
# 查找项目中所有TODO拐杖
grep -r "TODO\|FIXME\|HACK\|XXX" --include="*.kt" --include="*.swift" .

预防新拐杖

对抗拐杖的最佳方法是不无故创建它们。在编写拐杖之前,问自己三个问题:能否在合理时间内做出纯粹解决方案?是否有不是拐杖的替代方案?团队会有时间回来重写吗?如果至少有一个问题的答案是“不”——在“支撑”代码之前再想想。

常见问题解答

编程中“打补丁”是什么意思?

打补丁——编写临时解决方案来关闭问题但不消除其原因。代码能工作,但不符合项目架构,可能在变更时崩溃。

拐杖与技术债务有什么区别?

拐杖——有消除计划的有意识临时解决方案。技术债务——许多被遗忘的拐杖的后果。拐杖是局部的,债务是系统性的并阻塞开发。

代码中的拐杖何时合理?

当截止日期紧迫、纯粹解决方案需要时间且拐杖有文档记录(TODO注释和跟踪器中的ticket)时。条件:拐杖在可预见的未来有删除计划。

如何正确记录拐杖?

添加TODO或FIXME,包含ticket编号和正确解决方案的简要描述。示例:// TODO: IT-567 — 使用Factory pattern重写。没有ticket,拐杖会被遗忘。

如何重构有拐杖的代码?

对所有TODO进行清点,评估优先级,从经常变更的模块开始。用纯粹解决方案替换拐杖,删除注释并用测试检查。

总结

  • 打补丁——创建临时解决方案,在不消除根本原因的情况下关闭问题
  • 拐杖因截止日期、版本不兼容和对系统的不完全理解而产生
  • 有意识的拐杖——工具,无意识的——技术债务
  • 用TODO注释和跟踪器中的ticket记录每个拐杖
  • 忘记删除时,拐杖变成问题
  • 根据模块变更频率和对用户的影响确定重构优先级
  • 在创建拐杖之前问自己:有消除计划吗?

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读