en un clic
code-simplification
// 为清晰度简化代码。用于在不改变行为的前提下重构代码以提升清晰度;用于代码能运行但比应有状态更难阅读、维护或扩展时;用于审查已累积不必要复杂度的代码时。
// 为清晰度简化代码。用于在不改变行为的前提下重构代码以提升清晰度;用于代码能运行但比应有状态更难阅读、维护或扩展时;用于审查已累积不必要复杂度的代码时。
指导稳定的 API 和接口设计。设计 API、模块边界或任何公共接口时使用。创建 REST 或 GraphQL endpoint、定义模块之间的类型契约,或建立前后端边界时使用。
在真实浏览器中测试。构建或调试任何在浏览器中运行的内容时使用。当你需要通过 Chrome DevTools MCP 检查 DOM、捕获 console 错误、分析网络请求、分析性能,或用真实运行时数据验证视觉输出时使用。
自动化 CI/CD pipeline 设置。用于设置或修改构建和部署 pipeline 时;用于需要自动化质量门禁、在 CI 中配置 test runners,或建立部署策略时。
执行多维度代码审查。用于合并任何变更之前;用于审查自己、其他 agent 或人类编写的代码;用于在代码进入主分支前从多个维度评估代码质量。
优化 agent 上下文设置。当开始新会话、agent 输出质量下降、在任务之间切换,或需要为项目配置规则文件和上下文时使用。
指导系统化根因调试。当测试失败、构建中断、行为不符合预期,或遇到任何意外错误时使用。当你需要系统化地找到并修复根因,而不是猜测时使用。
| name | code-simplification |
| description | 为清晰度简化代码。用于在不改变行为的前提下重构代码以提升清晰度;用于代码能运行但比应有状态更难阅读、维护或扩展时;用于审查已累积不必要复杂度的代码时。 |
灵感来自 Claude Code Simplifier plugin。这里改编为一个模型无关、流程驱动的 skill,供任何 AI coding agent 使用。
通过降低复杂度来简化代码,同时精确保留行为。目标不是减少行数,而是让代码更容易阅读、理解、修改和调试。每次简化都必须通过一个简单测试:“新团队成员理解它会不会比理解原版本更快?”
不应使用的情况:
不要改变代码做什么,只改变它如何表达。所有输入、输出、副作用、错误行为和边界情况都必须保持一致。如果你不确定某个简化是否保留行为,就不要做。
ASK BEFORE EVERY CHANGE:
→ Does this produce the same output for every input?
→ Does this maintain the same error behavior?
→ Does this preserve the same side effects and ordering?
→ Do all existing tests still pass without modification?
简化意味着让代码更符合代码库,而不是强加外部偏好。简化之前:
1. Read CLAUDE.md / project conventions
2. Study how neighboring code handles similar patterns
3. Match the project's style for:
- Import ordering and module system
- Function declaration style
- Naming conventions
- Error handling patterns
- Type annotation depth
破坏项目一致性的简化不是简化,而是 churn。
如果紧凑写法需要停下来费力解析,那么显式代码就优于紧凑代码。
// UNCLEAR: Dense ternary chain
const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active';
// CLEAR: Readable mapping
function getStatusLabel(item: Item): string {
if (item.isNew) return 'New';
if (item.isUpdated) return 'Updated';
if (item.isArchived) return 'Archived';
return 'Active';
}
// UNCLEAR: Chained reduces with inline logic
const result = items.reduce((acc, item) => ({
...acc,
[item.id]: { ...acc[item.id], count: (acc[item.id]?.count ?? 0) + 1 }
}), {});
// CLEAR: Named intermediate step
const countById = new Map<string, number>();
for (const item of items) {
countById.set(item.id, (countById.get(item.id) ?? 0) + 1);
}
简化也有失败模式:过度简化。注意这些陷阱:
默认只简化最近修改过的代码。除非明确要求扩大范围,否则避免顺手重构无关代码。无边界的简化会制造 diff 噪音,并带来意外回归风险。
在修改或移除任何东西之前,先理解它为什么存在。这就是 Chesterton's Fence:如果你看到路上有一道栅栏,却不知道它为什么在那里,就不要拆掉它。先理解原因,再判断这个原因是否仍然成立。
BEFORE SIMPLIFYING, ANSWER:
- What is this code's responsibility?
- What calls it? What does it call?
- What are the edge cases and error paths?
- Are there tests that define the expected behavior?
- Why might it have been written this way? (Performance? Platform constraint? Historical reason?)
- Check git blame: what was the original context for this code?
如果回答不了这些问题,就还没准备好简化。先读更多上下文。
扫描这些模式。每一项都是具体信号,而不是模糊的 smell:
结构复杂度:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 深层嵌套(3+ 层) | 控制流难以跟随 | 将条件提取为 guard clauses 或 helper functions |
| 长函数(50+ 行) | 多个职责 | 拆分为命名清晰、职责聚焦的函数 |
| 嵌套三元表达式 | 需要 mental stack 才能解析 | 替换为 if/else 链、switch 或 lookup objects |
| Boolean parameter flags | doThing(true, false, true) | 替换为 options objects 或独立函数 |
| 重复条件判断 | 多处出现相同 if 检查 | 提取为命名良好的 predicate function |
命名和可读性:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 泛化命名 | data, result, temp, val, item | 重命名以描述内容:userProfile, validationErrors |
| 缩写命名 | usr, cfg, btn, evt | 除非缩写是通用的(id, url, api),否则使用完整单词 |
| 误导性命名 | 名为 get 的函数同时会修改状态 | 重命名以反映真实行为 |
| 解释 "what" 的注释 | // increment counter 写在 count++ 上方 | 删除注释,代码本身已经足够清楚 |
| 解释 "why" 的注释 | // Retry because the API is flaky under load | 保留它们,它们承载了代码无法表达的意图 |
冗余:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 重复逻辑 | 相同的 5+ 行出现在多处 | 提取为共享函数 |
| 死代码 | 不可达分支、未使用变量、注释掉的代码块 | 移除(确认它确实已死之后) |
| 不必要抽象 | 不增加价值的 wrapper | 内联 wrapper,直接调用底层函数 |
| 过度工程化模式 | Factory-for-a-factory、strategy-with-one-strategy | 替换为简单直接的方案 |
| 冗余类型断言 | 转换为已经能推断出的类型 | 移除断言 |
一次只做一个简化。每次变更后都运行测试。将重构变更与功能或 bug fix 变更分开提交。 一个既重构又添加功能的 PR,其实是两个 PR,应拆分。
FOR EACH SIMPLIFICATION:
1. Make the change
2. Run the test suite
3. If tests pass → commit (or continue to next simplification)
4. If tests fail → revert and reconsider
避免把多个简化打包成一个未经测试的变更。如果出现破坏,你需要知道是哪次简化导致的。
The Rule of 500: 如果一次重构会触及超过 500 行,就投入自动化(codemods、sed scripts、AST transforms),不要手工修改。这个规模的手工编辑容易出错,也很难审查。
完成所有简化后,退一步评估整体:
COMPARE BEFORE AND AFTER:
- Is the simplified version genuinely easier to understand?
- Did you introduce any new patterns inconsistent with the codebase?
- Is the diff clean and reviewable?
- Would a teammate approve this change?
如果“简化”后的版本更难理解或审查,就 revert。不是每次简化尝试都会成功。
// SIMPLIFY: Unnecessary async wrapper
// Before
async function getUser(id: string): Promise<User> {
return await userService.findById(id);
}
// After
function getUser(id: string): Promise<User> {
return userService.findById(id);
}
// SIMPLIFY: Verbose conditional assignment
// Before
let displayName: string;
if (user.nickname) {
displayName = user.nickname;
} else {
displayName = user.fullName;
}
// After
const displayName = user.nickname || user.fullName;
// SIMPLIFY: Manual array building
// Before
const activeUsers: User[] = [];
for (const user of users) {
if (user.isActive) {
activeUsers.push(user);
}
}
// After
const activeUsers = users.filter((user) => user.isActive);
// SIMPLIFY: Redundant boolean return
// Before
function isValid(input: string): boolean {
if (input.length > 0 && input.length < 100) {
return true;
}
return false;
}
// After
function isValid(input: string): boolean {
return input.length > 0 && input.length < 100;
}
# SIMPLIFY: Verbose dictionary building
# Before
result = {}
for item in items:
result[item.id] = item.name
# After
result = {item.id: item.name for item in items}
# SIMPLIFY: Nested conditionals with early return
# Before
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")
# After
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)
// SIMPLIFY: Verbose conditional rendering
// Before
function UserBadge({ user }: Props) {
if (user.isAdmin) {
return <Badge variant="admin">Admin</Badge>;
} else {
return <Badge variant="default">User</Badge>;
}
}
// After
function UserBadge({ user }: Props) {
const variant = user.isAdmin ? 'admin' : 'default';
const label = user.isAdmin ? 'Admin' : 'User';
return <Badge variant={variant}>{label}</Badge>;
}
// SIMPLIFY: Prop drilling through intermediate components
// Before — consider whether context or composition solves this better.
// This is a judgment call — flag it, don't auto-refactor.
| 合理化借口 | 现实 |
|---|---|
| “它能工作,没必要动” | 难读的可运行代码在出问题时也会很难修。现在简化,会节省未来每次修改的时间。 |
| “行数越少就越简单” | 一行嵌套三元表达式不比五行 if/else 更简单。简单性关乎理解速度,而不是行数。 |
| “我顺手快速简化一下这段无关代码” | 无范围的简化会制造嘈杂 diff,并给你本不打算修改的代码带来回归风险。保持聚焦。 |
| “类型让它自解释了” | 类型记录结构,不记录意图。命名良好的函数比类型签名更能解释 why。 |
| “这个抽象以后可能有用” | 不要保留投机性抽象。如果现在用不上,它就是没有价值的复杂度。移除它,需要时再加回来。 |
| “原作者一定有原因” | 也许。检查 git blame,应用 Chesterton's Fence。但累积复杂度往往没有原因,只是压力下迭代的残留。 |
| “我会一边加功能一边重构” | 将重构和功能开发分开。混合变更更难审查、回滚,也更难在历史中理解。 |
完成一次简化后: