Loading...
Loading...
Compare original and translation side by side
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的、与模型无关的、流程驱动型技能。
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 depth1. 阅读CLAUDE.md / 项目约定文档
2. 研究相邻代码如何处理类似模式
3. 匹配项目的风格规范:
- 导入顺序和模块系统
- 函数声明风格
- 命名约定
- 错误处理模式
- 类型注解深度// 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);
}// 不清晰:密集的三元表达式链
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);
}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?开始简化前,请回答:
- 这段代码的职责是什么?
- 哪些代码调用它?它调用哪些代码?
- 有哪些边缘情况和错误路径?
- 是否有定义预期行为的测试?
- 它为什么会被写成这样?(性能原因?平台限制?历史原因?)
- 查看git blame:这段代码的原始上下文是什么?| 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 |
| 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 |
| 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行以上代码 | 提取为共享函数 |
| 死代码 | 不可达分支、未使用变量、注释掉的代码块 | 删除(确认确实是死代码后) |
| 不必要的抽象 | 无价值的包装器 | 内联包装器,直接调用底层函数 |
| 过度设计的模式 | 工厂的工厂、只有一种策略的策略模式 | 替换为简单直接的实现方式 |
| 冗余的类型断言 | 转换为已推断出的类型 | 移除断言 |
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对于每一处简化:
1. 进行变更
2. 运行测试套件
3. 如果测试通过 → 提交(或继续下一处简化)
4. 如果测试失败 → 回滚并重新考虑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?对比简化前后:
- 简化后的版本是否真的更易于理解?
- 是否引入了与代码库不一致的新模式?
- 代码差异是否清晰且易于审查?
- 队友是否会批准此变更?// 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;
}// 简化:不必要的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;
}undefinedundefinedundefinedundefined// 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.// 简化:冗长的条件渲染
// 简化前
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或组合是否能更好地解决此问题。
// 这需要判断——标记出来,不要自动重构。| 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——应用切斯特顿栅栏原则。但累积的复杂度往往没有理由,只是在时间压力下迭代产生的残留。 |
| "我在添加功能时顺便重构" | 将重构与功能开发分开。混合变更更难审查、回滚,且在历史记录中更难理解。 |