code-simplification

code-simplification

热门

简化代码以提高清晰度。在重构代码以提升清晰度且不改变行为时使用。在代码能工作但比应有的更难阅读、维护或扩展时使用。在审查积累了不必要复杂性的代码时使用。

7.7万Star
0Fork
更新于 2026/7/3
SKILL.md
readonly只读
name
code-simplification
description

简化代码以提高清晰度。在重构代码以提升清晰度且不改变行为时使用。在代码能工作但比应有的更难阅读、维护或扩展时使用。在审查积累了不必要复杂性的代码时使用。

代码简化

灵感来源于 Claude Code Simplifier 插件。此处改编为模型无关、流程驱动的技能,适用于任何 AI 编码代理。

概述

通过降低复杂性来简化代码,同时保持行为完全不变。目标不是减少行数——而是让代码更易于阅读、理解、修改和调试。每次简化都必须通过一个简单的测试:“新团队成员能比原版更快理解这段代码吗?”

何时使用

  • 功能已工作且测试通过,但实现感觉比需要的更重时
  • 代码审查中标记出可读性或复杂性问题时
  • 遇到深层嵌套逻辑、长函数或命名不清晰时
  • 重构在时间压力下编写的代码时
  • 合并分散在多个文件中的相关逻辑时
  • 合并引入了重复或不一致的更改后

何时不使用:

  • 代码已经清晰可读——不要为了简化而简化
  • 你还不理解代码的作用——先理解再简化
  • 代码对性能至关重要,而“更简单”的版本会明显变慢
  • 你即将重写整个模块——简化将被丢弃的代码是浪费精力

五项原则

1. 精确保持行为

不要改变代码的功能——只改变其表达方式。所有输入、输出、副作用、错误行为和边界情况必须保持完全相同。如果不确定简化是否保持行为,就不要做。

每次更改前都要问:
→ 对于每个输入,是否产生相同的输出?
→ 是否保持相同的错误行为?
→ 是否保持相同的副作用和顺序?
→ 所有现有测试是否无需修改就能通过?

2. 遵循项目约定

简化意味着使代码与代码库更一致,而不是强加外部偏好。在简化之前:

1. 阅读 CLAUDE.md / 项目约定
2. 研究相邻代码如何处理类似模式
3. 匹配项目的风格:
   - 导入顺序和模块系统
   - 函数声明风格
   - 命名约定
   - 错误处理模式
   - 类型注解深度

破坏项目一致性的简化不是简化——而是折腾。

3. 清晰优于巧妙

当紧凑版本需要心理停顿来解析时,显式代码优于紧凑代码。

// 不清晰:密集的三元链
const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active';

// 清晰:可读的映射
function getStatusLabel(item: Item): string {
  if (item.isNew) return 'New';
  if (item.isUpdated) return 'Updated';
  if (item.isArchived) return 'Archived';
  return 'Active';
}
// 不清晰:链式 reduce 与内联逻辑
const result = items.reduce((acc, item) => ({
  ...acc,
  [item.id]: { ...acc[item.id], count: (acc[item.id]?.count ?? 0) + 1 }
}), {});

// 清晰:命名的中间步骤
const countById = new Map<string, number>();
for (const item of items) {
  countById.set(item.id, (countById.get(item.id) ?? 0) + 1);
}

4. 保持平衡

简化有一个失败模式:过度简化。注意这些陷阱:

  • 过度内联——移除给概念命名的辅助函数会使调用点更难读
  • 合并无关逻辑——两个简单函数合并成一个复杂函数并不更简单
  • 移除“不必要的”抽象——某些抽象是为了可扩展性或可测试性而存在,而非复杂性
  • 优化行数——更少的行数不是目标;更容易理解才是

5. 限定在变更范围内

默认只简化最近修改的代码。除非明确要求扩大范围,否则避免对无关代码进行路过式重构。无范围限制的简化会在差异中产生噪音,并可能导致意外的回归。

简化流程

第一步:先理解再动手(切斯特顿栅栏)

在更改或移除任何东西之前,先理解它为什么存在。这就是切斯特顿栅栏:如果你看到路上有一道栅栏,不明白它为什么在那里,不要拆掉它。先理解原因,再决定原因是否仍然适用。

在简化之前,回答:
- 这段代码的职责是什么?
- 谁调用它?它调用谁?
- 边界情况和错误路径是什么?
- 是否有测试定义了预期行为?
- 为什么可能这样写?(性能?平台限制?历史原因?)
- 检查 git blame:这段代码的原始上下文是什么?

如果你不能回答这些问题,你还没有准备好简化。先阅读更多上下文。

第二步:识别简化机会

扫描这些模式——每一个都是具体信号,而非模糊的气味:

结构复杂性:

模式 信号 简化
深层嵌套(3层以上) 难以跟踪控制流 将条件提取为卫语句或辅助函数
长函数(50行以上) 多个职责 拆分为专注的函数,使用描述性名称
嵌套三元表达式 需要心理堆栈来解析 替换为 if/else 链、switch 或查找对象
布尔参数标志 doThing(true, false, true) 替换为选项对象或单独的函数
重复的条件判断 多个地方出现相同的 if 检查 提取为命名良好的谓词函数

命名和可读性:

模式 信号 简化
通用名称 data, result, temp, val, item 重命名为描述内容:userProfile, validationErrors
缩写名称 usr, cfg, btn, evt 使用完整单词,除非缩写是通用的(id, url, api
误导性名称 名为 get 的函数同时修改状态 重命名以反映实际行为
解释“是什么”的注释 // increment countercount++ 之上 删除注释——代码已经足够清晰
解释“为什么”的注释 // Retry because the API is flaky under load 保留这些——它们承载了代码无法表达的意图

冗余:

模式 信号 简化
重复逻辑 多个地方出现相同的5行以上代码 提取为共享函数
死代码 不可达分支、未使用变量、注释掉的代码块 移除(确认确实已死后)
不必要的抽象 没有增加价值的包装器 内联包装器,直接调用底层函数
过度设计的模式 工厂的工厂、只有一个策略的策略模式 替换为简单的直接方法
冗余的类型断言 强制转换为已经推断出的类型 移除断言

第三步:增量应用更改

一次只做一个简化。每次更改后运行测试。将重构更改与功能或错误修复更改分开提交。 一个同时重构和添加功能的 PR 应该是两个 PR——分开它们。

对于每次简化:
1. 进行更改
2. 运行测试套件
3. 如果测试通过 → 提交(或继续下一个简化)
4. 如果测试失败 → 回滚并重新考虑

避免将多个简化批量放入一个未经测试的更改中。如果出现问题,你需要知道是哪个简化导致的。

500 行规则: 如果重构涉及超过 500 行,请投资自动化(codemods、sed 脚本、AST 转换),而不是手动进行更改。这种规模的手动编辑容易出错且审查起来很累。

第四步:验证结果

在所有简化之后,退后一步评估整体:

比较前后:
- 简化版本是否真正更容易理解?
- 你是否引入了与代码库不一致的新模式?
- diff 是否干净且可审查?
- 团队成员会批准这个更改吗?

如果“简化”版本更难理解或审查,请回滚。并非每次简化尝试都会成功。

语言特定指导

TypeScript / JavaScript

// 简化:不必要的 async 包装器
// 之前
async function getUser(id: string): Promise<User> {
  return await userService.findById(id);
}
// 之后
function getUser(id: string): Promise<User> {
  return userService.findById(id);
}

// 简化:冗长的条件赋值
// 之前
let displayName: string;
if (user.nickname) {
  displayName = user.nickname;
} else {
  displayName = user.fullName;
}
// 之后
const displayName = user.nickname || user.fullName;

// 简化:手动构建数组
// 之前
const activeUsers: User[] = [];
for (const user of users) {
  if (user.isActive) {
    activeUsers.push(user);
  }
}
// 之后
const activeUsers = users.filter((user) => user.isActive);

// 简化:冗余的布尔返回
// 之前
function isValid(input: string): boolean {
  if (input.length > 0 && input.length < 100) {
    return true;
  }
  return false;
}
// 之后
function isValid(input: string): boolean {
  return input.length > 0 && input.length < 100;
}

Python

# 简化:冗长的字典构建
# 之前
result = {}
for item in items:
    result[item.id] = item.name
# 之后
result = {item.id: item.name for item in items}

# 简化:嵌套条件与提前返回
# 之前
def process(data):
    if data is not None:
        if data.is_valid():
            if data.has_permission():
                return do_work(data)
            else:
                raise PermissionError("No permission")
        else:
            raise ValueError("Invalid data")
    else:
        raise TypeError("Data is None")
# 之后
def process(data):
    if data is None:
        raise TypeError("Data is None")
    if not data.is_valid():
        raise ValueError("Invalid data")
    if not data.has_permission():
        raise PermissionError("No permission")
    return do_work(data)

React / JSX

// 简化:冗长的条件渲染
// 之前
function UserBadge({ user }: Props) {
  if (user.isAdmin) {
    return <Badge variant="admin">Admin</Badge>;
  } else {
    return <Badge variant="default">User</Badge>;
  }
}
// 之后
function UserBadge({ user }: Props) {
  const variant = user.isAdmin ? 'admin' : 'default';
  const label = user.isAdmin ? 'Admin' : 'User';
  return <Badge variant={variant}>{label}</Badge>;
}

// 简化:通过中间组件进行属性透传
// 之前——考虑上下文或组合是否能更好地解决这个问题。
// 这是一个判断——标记它,不要自动重构。

常见合理化理由

合理化理由 现实
“它能工作,没必要动它” 能工作但难读的代码在出问题时难以修复。现在简化可以节省未来每次更改的时间。
“更少的行数总是更简单” 一行嵌套三元并不比五行 if/else 更简单。简单性关乎理解速度,而非行数。
“我顺便快速简化一下这个无关的代码” 无范围限制的简化会产生噪音差异,并可能导致你无意更改的代码出现回归。保持专注。
“类型使其自文档化” 类型记录结构,而非意图。命名良好的函数比类型签名更好地解释为什么
“这个抽象以后可能有用” 不要保留推测性的抽象。如果现在没用,它就是没有价值的复杂性。移除它,需要时再添加。
“原始作者一定有理由” 也许。检查 git blame——应用切斯特顿栅栏。但累积的复杂性往往没有理由;它只是压力下迭代的残留物。
“我会在添加这个功能的同时重构” 将重构与功能工作分开。混合的更改更难审查、回滚和在历史中理解。

红旗

  • 需要修改测试才能通过的简化(你可能改变了行为)
  • “简化”后的代码比原版更长且更难理解
  • 根据个人偏好而非项目约定重命名
  • 因为“让代码更干净”而移除错误处理
  • 简化你尚未完全理解的代码
  • 将多个简化批量放入一个大的、难以审查的提交中
  • 在没有被要求的情况下重构当前任务范围之外的代码

验证

完成一轮简化后:

  • [ ] 所有现有测试无需修改即可通过
  • [ ] 构建成功,无新警告
  • [ ] 代码检查/格式化通过(无风格回归)
  • [ ] 每次简化都是可审查的增量更改
  • [ ] diff 干净——没有混入无关更改
  • [ ] 简化后的代码遵循项目约定(对照 CLAUDE.md 或等效文件检查)
  • [ ] 没有移除或削弱错误处理
  • [ ] 没有留下死代码(未使用的导入、不可达分支)
  • [ ] 团队成员或审查代理会批准该更改,认为其是净改进