code-simplification
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode Simplification
代码简化
Inspired by the Claude Code Simplifier plugin. Adapted here as a model-agnostic, process-driven skill for any AI coding agent.
灵感来自Claude Code Simplifier 插件。此处改编为适用于任何AI编码Agent的、与模型无关的、流程驱动型技能。
Overview
概述
Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass a simple test: "Would a new team member understand this faster than the original?"
在保留代码原有行为的前提下简化代码,降低复杂度。目标并非减少代码行数,而是让代码更易于阅读、理解、修改和调试。每一处简化都必须通过一个简单测试:"新团队成员理解这段代码的速度会比原代码更快吗?"
When to Use
使用场景
- After a feature is working and tests pass, but the implementation feels heavier than it needs to be
- During code review when readability or complexity issues are flagged
- When you encounter deeply nested logic, long functions, or unclear names
- When refactoring code written under time pressure
- When consolidating related logic scattered across files
- After merging changes that introduced duplication or inconsistency
When NOT to use:
- Code is already clean and readable — don't simplify for the sake of it
- You don't understand what the code does yet — comprehend before you simplify
- The code is performance-critical and the "simpler" version would be measurably slower
- You're about to rewrite the module entirely — simplifying throwaway code wastes effort
- 功能开发完成且测试通过后,但实现方式显得过于繁琐时
- 代码审查中发现可读性或复杂度问题时
- 遇到深度嵌套逻辑、过长函数或命名模糊的代码时
- 重构在时间压力下编写的代码时
- 整合分散在多个文件中的相关逻辑时
- 合并引入重复或不一致问题的代码变更后
不适用于以下场景:
- 代码本身已简洁易读——不要为了简化而简化
- 你尚未理解代码的功能——先理解再简化
- 代码对性能要求极高,"简化版"会导致可测量的性能下降时
- 你即将完全重写该模块——简化临时代码纯属浪费精力
The Five Principles
五大原则
1. Preserve Behavior Exactly
1. 完全保留原有行为
Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. If you're not sure a simplification preserves behavior, don't make it.
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?不要改变代码的功能——只优化其表达方式。所有输入、输出、副作用、错误行为和边缘情况必须保持一致。如果不确定某一简化操作是否能保留原有行为,请勿执行。
每次变更前请确认:
→ 该变更是否对所有输入都产生相同输出?
→ 该变更是否保持了相同的错误处理行为?
→ 该变更是否保留了相同的副作用和执行顺序?
→ 所有现有测试是否无需修改即可通过?2. Follow Project Conventions
2. 遵循项目约定
Simplification means making code more consistent with the codebase, not imposing external preferences. Before simplifying:
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 depthSimplification that breaks project consistency is not simplification — it's churn.
简化意味着让代码与代码库更一致,而非强加外部偏好。开始简化前:
1. 阅读CLAUDE.md / 项目约定文档
2. 研究相邻代码如何处理类似模式
3. 匹配项目的风格规范:
- 导入顺序和模块系统
- 函数声明风格
- 命名约定
- 错误处理模式
- 类型注解深度破坏项目一致性的简化不是简化——而是无意义的变更。
3. Prefer Clarity Over Cleverness
3. 清晰优先于巧妙
Explicit code is better than compact code when the compact version requires a mental pause to parse.
typescript
// 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';
}typescript
// 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);
}当紧凑代码需要额外思考才能解析时,显式代码优于紧凑代码。
typescript
// 不清晰:密集的三元表达式链
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';
}typescript
// 不清晰:包含内联逻辑的链式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. Maintain Balance
4. 保持平衡
Simplification has a failure mode: over-simplification. Watch for these traps:
- Inlining too aggressively — removing a helper that gave a concept a name makes the call site harder to read
- Combining unrelated logic — two simple functions merged into one complex function is not simpler
- Removing "unnecessary" abstraction — some abstractions exist for extensibility or testability, not complexity
- Optimizing for line count — fewer lines is not the goal; easier comprehension is
简化存在一种失败模式:过度简化。请注意以下陷阱:
- 过度内联——移除赋予概念名称的辅助函数会使调用处更难理解
- 合并无关逻辑——将两个简单函数合并为一个复杂函数并非简化
- 移除"不必要的"抽象——有些抽象是为了扩展性或可测试性而存在,并非为了增加复杂度
- 以行数为优化目标——更少的行数不是目的;更易理解才是
5. Scope to What Changed
5. 聚焦变更范围
Default to simplifying recently modified code. Avoid drive-by refactors of unrelated code unless explicitly asked to broaden scope. Unscoped simplification creates noise in diffs and risks unintended regressions.
默认只简化最近修改的代码。除非明确要求扩大范围,否则避免对无关代码进行顺带重构。无范围限制的简化会在差异对比中产生噪音,并可能导致意外的回归问题。
The Simplification Process
简化流程
Step 1: Understand Before Touching (Chesterton's Fence)
步骤1:先理解再修改(切斯特顿栅栏原则)
Before changing or removing anything, understand why it exists. This is Chesterton's Fence: if you see a fence across a road and don't understand why it's there, don't tear it down. First understand the reason, then decide if the reason still applies.
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?If you can't answer these, you're not ready to simplify. Read more context first.
在更改或移除任何内容之前,先理解其存在的原因。这就是切斯特顿栅栏原则:如果你看到道路上有一道栅栏却不理解它的用途,不要拆除它。先理解原因,再决定该原因是否仍然适用。
开始简化前,请回答:
- 这段代码的职责是什么?
- 哪些代码调用它?它调用哪些代码?
- 有哪些边缘情况和错误路径?
- 是否有定义预期行为的测试?
- 它为什么会被写成这样?(性能原因?平台限制?历史原因?)
- 查看git blame:这段代码的原始上下文是什么?如果无法回答这些问题,说明你还没准备好进行简化。先阅读更多上下文信息。
Step 2: Identify Simplification Opportunities
步骤2:识别简化机会
Scan for these patterns — each one is a concrete signal, not a vague smell:
Structural complexity:
| Pattern | Signal | Simplification |
|---|---|---|
| Deep nesting (3+ levels) | Hard to follow control flow | Extract conditions into guard clauses or helper functions |
| Long functions (50+ lines) | Multiple responsibilities | Split into focused functions with descriptive names |
| Nested ternaries | Requires mental stack to parse | Replace with if/else chains, switch, or lookup objects |
| Boolean parameter flags | | Replace with options objects or separate functions |
| Repeated conditionals | Same | Extract to a well-named predicate function |
Naming and readability:
| Pattern | Signal | Simplification |
|---|---|---|
| Generic names | | Rename to describe the content: |
| Abbreviated names | | Use full words unless the abbreviation is universal ( |
| Misleading names | Function named | Rename to reflect actual behavior |
| Comments explaining "what" | | Delete the comment — the code is clear enough |
| Comments explaining "why" | | Keep these — they carry intent the code can't express |
Redundancy:
| Pattern | Signal | Simplification |
|---|---|---|
| Duplicated logic | Same 5+ lines in multiple places | Extract to a shared function |
| Dead code | Unreachable branches, unused variables, commented-out blocks | Remove (after confirming it's truly dead) |
| Unnecessary abstractions | Wrapper that adds no value | Inline the wrapper, call the underlying function directly |
| Over-engineered patterns | Factory-for-a-factory, strategy-with-one-strategy | Replace with the simple direct approach |
| Redundant type assertions | Casting to a type that's already inferred | Remove the assertion |
扫描以下模式——每种模式都是具体信号,而非模糊的代码异味:
结构复杂度:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 深度嵌套(3层及以上) | 控制流难以追踪 | 将条件提取为守卫语句或辅助函数 |
| 长函数(50行及以上) | 承担多个职责 | 拆分为多个功能单一、命名清晰的函数 |
| 嵌套三元表达式 | 需要脑力解析 | 替换为if/else链、switch语句或查找对象 |
| 布尔参数标志 | | 替换为选项对象或拆分函数 |
| 重复条件判断 | 多处出现相同的 | 提取为命名清晰的谓词函数 |
命名与可读性:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 通用名称 | | 重命名以描述内容: |
| 缩写名称 | | 使用完整单词,除非缩写是通用的( |
| 误导性名称 | 名为 | 重命名以反映实际行为 |
| 解释"是什么"的注释 | | 删除注释——代码本身已足够清晰 |
| 解释"为什么"的注释 | | 保留这些注释——它们承载着代码无法表达的意图 |
冗余性:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 重复逻辑 | 多处出现相同的5行以上代码 | 提取为共享函数 |
| 死代码 | 不可达分支、未使用变量、注释掉的代码块 | 删除(确认确实是死代码后) |
| 不必要的抽象 | 无价值的包装器 | 内联包装器,直接调用底层函数 |
| 过度设计的模式 | 工厂的工厂、只有一种策略的策略模式 | 替换为简单直接的实现方式 |
| 冗余的类型断言 | 转换为已推断出的类型 | 移除断言 |
Step 3: Apply Changes Incrementally
步骤3:逐步应用变更
Make one simplification at a time. Run tests after each change. Submit refactoring changes separately from feature or bug fix changes. A PR that refactors and adds a feature is two PRs — split them.
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 reconsiderAvoid batching multiple simplifications into a single untested change. If something breaks, you need to know which simplification caused it.
The Rule of 500: If a refactoring would touch more than 500 lines, invest in automation (codemods, sed scripts, AST transforms) rather than making the changes by hand. Manual edits at that scale are error-prone and exhausting to review.
每次只进行一处简化。每次变更后运行测试。将重构变更与功能或修复变更分开提交。 同时包含重构和新增功能的PR应拆分为两个PR。
对于每一处简化:
1. 进行变更
2. 运行测试套件
3. 如果测试通过 → 提交(或继续下一处简化)
4. 如果测试失败 → 回滚并重新考虑避免将多处简化合并为一个未测试的变更。如果出现问题,你需要知道是哪一处简化导致的。
500行规则: 如果重构会修改超过500行代码,请使用自动化工具(codemods、sed脚本、AST转换)而非手动修改。手动处理这种规模的代码容易出错,且审查难度大。
Step 4: Verify the Result
步骤4:验证结果
After all simplifications, step back and evaluate the whole:
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?If the "simplified" version is harder to understand or review, revert. Not every simplification attempt succeeds.
完成所有简化后,退一步评估整体效果:
对比简化前后:
- 简化后的版本是否真的更易于理解?
- 是否引入了与代码库不一致的新模式?
- 代码差异是否清晰且易于审查?
- 队友是否会批准此变更?如果"简化版"更难理解或审查,请回滚。并非所有简化尝试都能成功。
Language-Specific Guidance
特定语言指导
TypeScript / JavaScript
TypeScript / JavaScript
typescript
// 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;
}typescript
// 简化:不必要的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
Python
python
undefinedpython
undefinedSIMPLIFY: Verbose dictionary building
简化:冗长的字典构建
Before
简化前
result = {}
for item in items:
result[item.id] = item.name
result = {}
for item in items:
result[item.id] = item.name
After
简化后
result = {item.id: item.name for item in items}
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")
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)
undefineddef 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)
undefinedReact / JSX
React / JSX
tsx
// 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.tsx
// 简化:冗长的条件渲染
// 简化前
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>;
}
// 简化:通过中间组件传递属性
// 简化前——考虑context或组合是否能更好地解决此问题。
// 这需要判断——标记出来,不要自动重构。Common Rationalizations
常见合理化借口
| Rationalization | Reality |
|---|---|
| "It's working, no need to touch it" | Working code that's hard to read will be hard to fix when it breaks. Simplifying now saves time on every future change. |
| "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count. |
| "I'll just quickly simplify this unrelated code too" | Unscoped simplification creates noisy diffs and risks regressions in code you didn't intend to change. Stay focused. |
| "The types make it self-documenting" | Types document structure, not intent. A well-named function explains why better than a type signature explains what. |
| "This abstraction might be useful later" | Don't preserve speculative abstractions. If it's not used now, it's complexity without value. Remove it and re-add when needed. |
| "The original author must have had a reason" | Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's just the residue of iteration under pressure. |
| "I'll refactor while adding this feature" | Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history. |
| 借口 | 实际情况 |
|---|---|
| "代码能运行,没必要修改" | 难以阅读的可用代码在出现问题时也难以修复。现在进行简化能为未来的每一次变更节省时间。 |
| "行数越少越简单" | 1行嵌套三元表达式并不比5行if/else简单。简单性关乎理解速度,而非行数。 |
| "我顺便把这段无关代码也简化一下" | 无范围限制的简化会产生嘈杂的代码差异,并可能在你无意修改的代码中引入回归问题。保持专注。 |
| "类型注释已经自文档化了" | 类型注释记录结构,而非意图。命名清晰的函数比类型签名更能解释"为什么"。 |
| "这个抽象以后可能有用" | 不要保留推测性的抽象。如果现在没用,那就是无价值的复杂度。移除它,需要时再重新添加。 |
| "原作者肯定有理由这么写" | 可能有。查看git blame——应用切斯特顿栅栏原则。但累积的复杂度往往没有理由,只是在时间压力下迭代产生的残留。 |
| "我在添加功能时顺便重构" | 将重构与功能开发分开。混合变更更难审查、回滚,且在历史记录中更难理解。 |
Red Flags
警示信号
- Simplification that requires modifying tests to pass (you likely changed behavior)
- "Simplified" code that is longer and harder to follow than the original
- Renaming things to match your preferences rather than project conventions
- Removing error handling because "it makes the code cleaner"
- Simplifying code you don't fully understand
- Batching many simplifications into one large, hard-to-review commit
- Refactoring code outside the scope of the current task without being asked
- 简化操作需要修改测试才能通过(你很可能改变了代码行为)
- "简化版"代码比原代码更长、更难理解
- 按照个人偏好而非项目约定重命名
- 为了"让代码更简洁"而移除错误处理
- 简化你尚未完全理解的代码
- 将多处简化合并为一个大型、难以审查的提交
- 未经要求就重构当前任务范围外的代码
Verification
验证环节
After completing a simplification pass:
- All existing tests pass without modification
- Build succeeds with no new warnings
- Linter/formatter passes (no style regressions)
- Each simplification is a reviewable, incremental change
- The diff is clean — no unrelated changes mixed in
- Simplified code follows project conventions (checked against CLAUDE.md or equivalent)
- No error handling was removed or weakened
- No dead code was left behind (unused imports, unreachable branches)
- A teammate or review agent would approve the change as a net improvement
完成简化后:
- 所有现有测试无需修改即可通过
- 构建成功且无新警告
- 代码检查/格式化工具通过(无风格回归)
- 每一处简化都是可审查的增量变更
- 代码差异清晰——未混入无关变更
- 简化后的代码遵循项目约定(已对照CLAUDE.md或等效文档检查)
- 未移除或弱化错误处理
- 无残留死代码(未使用的导入、不可达分支)
- 队友或审查Agent会批准此变更,认为其是净改进