code-simplification
简化代码以提高清晰度。适用于在不改变行为的前提下重构代码以提高可读性时。当代码可以运行、但阅读、维护或扩展起来比应有的难度更高时使用。当审查已积累不必要复杂度的代码时使用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
简化代码以提高清晰度。适用于在不改变行为的前提下重构代码以提高可读性时。当代码可以运行、但阅读、维护或扩展起来比应有的难度更高时使用。当审查已积累不必要复杂度的代码时使用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Manage git submodules for the learning-open-code mono-repo. Use when the user wants to: (1) Add a new git submodule — auto-detect or specify the category (open-ai-skills/open-sdd/open-ai-agent/open-ai-desktop/open-knowledge/open-productivity/open-java/open-trading/open-data), record the tracking branch in .gitmodules, clone the repo, and update README.md index. (2) Sync all existing submodules to their configured branches (git fetch + checkout branch + pull). (3) Update the root README.md with an up-to-date index of all synced projects grouped by category. (4) Initialize submodules after git clone — when open-*/ directories are empty or git submodule status returns nothing, guide through the full SOP (git submodule update --init --recursive [--remote]). Trigger keywords: submodule, git submodule, 子模块, add submodule, sync submodule, update submodule, submodule branch, README index, 更新索引, clone, init, 初始化子模块, submodule init, 拉取子模块.
对开源项目进行穷尽式教学文档生成——从宏观架构到微观实现的五层分级讲解,使用 Goal Loop 算法自主驱动完整代码覆盖。所有具体教学内容生成必须激活 `.agents/skills/teach/SKILL.md`。触发条件:用户要求"完整学习某个项目"、"生成项目架构文档"、"从入口到落地讲清楚每个功能"、"代码考古"、"源码分析"、或指定一个项目目录/仓库要求全面教学。
使用并行子 agent 为模块生成多个截然不同的接口设计。当用户想要设计 API、探索接口选项、比较模块形态,或提到 "设计两次" 时使用。
交互式 QA 会话,用户以对话方式报告 bug 或问题,agent 将其录入 GitHub Issue。在后台探索代码库以获取上下文和领域语言。当用户想要报告 bug、做 QA、以对话方式录入 issue,或提及 "QA session" 时使用。
通过用户访谈创建包含微小提交的详细重构计划,并将其录入 GitHub Issue。当用户想要规划重构、创建重构 RFC,或将重构分解为安全的渐进步骤时使用。
从当前对话中提取 DDD 风格的通用语言词汇表,标记歧义并提出规范术语。保存到 UBIQUITOUS_LANGUAGE.md。当用户想要定义领域术语、构建词汇表、固化术语、创建通用语言,或提到 "领域模型" 或 "DDD" 时使用。
| name | code-simplification |
| description | 简化代码以提高清晰度。适用于在不改变行为的前提下重构代码以提高可读性时。当代码可以运行、但阅读、维护或扩展起来比应有的难度更高时使用。当审查已积累不必要复杂度的代码时使用。 |
灵感来源于 Claude Code Simplifier 插件。在此适配为适用于任何 AI 编程 agent 的模型无关、流程驱动的技能。
通过降低复杂度来简化代码,同时精确保持原有行为。目标不是更少的行数——而是让代码更易于阅读、理解、修改和调试。每次简化都必须通过一个简单的检验:"新团队成员是否能比原始版本更快地理解这段代码?"
不适用场景:
不要改变代码的功能——只改变它的表达方式。所有输入、输出、副作用、错误行为和边界情况必须保持不变。如果不确定某个简化是否保持了行为,就不要做。
每次变更前自问:
→ 对于每个输入,是否产生相同的输出?
→ 是否保持相同的错误行为?
→ 是否保持相同的副作用和执行顺序?
→ 所有现有测试是否在不修改的情况下仍然通过?
简化意味着让代码与代码库更加一致,而不是强加外部偏好。在简化之前:
1. 阅读 CLAUDE.md / 项目约定
2. 研究邻近代码如何处理类似模式
3. 匹配项目的以下风格:
- import 顺序和模块系统
- 函数声明风格
- 命名约定
- 错误处理模式
- 类型注解深度
破坏项目一致性的简化不是简化——是折腾。
当紧凑版本需要思考才能解析时,显式的代码优于紧凑的代码。
// 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 中产生噪音,并带来意外的回归风险。
在变更或移除任何东西之前,先理解它为什么存在。这就是切斯特顿之栏:如果你在路中间看到一道围栏却不理解它为什么在那里,不要拆掉它。先理解原因,然后判断原因是否仍然成立。
简化之前先回答:
- 这段代码的职责是什么?
- 什么调用了它?它调用了什么?
- 边界情况和错误路径有哪些?
- 是否有定义其预期行为的测试?
- 它为什么会写成这样?(性能?平台约束?历史原因?)
- 检查 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 counter 在 count++ 上方 | 删除注释——代码已经足够清晰 |
| 解释"为什么"的注释 | // Retry because the API is flaky under load | 保留——这些承载了代码无法表达的意图 |
冗余:
| 模式 | 信号 | 简化方式 |
|---|---|---|
| 重复逻辑 | 相同的 5+ 行代码出现在多处 | 提取为共享函数 |
| 死代码 | 不可达分支、未使用的变量、被注释掉的代码块 | 移除(确认确实已死后) |
| 不必要的抽象 | 未增加任何价值的包装器 | 内联包装器,直接调用底层函数 |
| 过度设计的模式 | 工厂的工厂、只有一种策略的策略模式 | 替换为简单直接的方式 |
| 冗余的类型断言 | 强制转换为已经被推断出的类型 | 移除断言 |
一次只做一项简化。每次变更后运行测试。将重构变更与功能或 bug 修复变更分开提交。 一个既重构又添加功能的 PR 应该是两个 PR——将它们拆分。
每次简化:
1. 进行变更
2. 运行测试套件
3. 如果测试通过 → 提交(或继续下一个简化)
4. 如果测试失败 → 回退并重新评估
避免将多个简化批量合并成一次未测试的变更。如果出了问题,你需要知道是哪个简化引起的。
500 行规则: 如果某次重构需要触及超过 500 行代码,请投入自动化(codemod、sed 脚本、AST 转换)而非手工修改。这种规模的手工编辑容易出错,审查起来也令人疲倦。
所有简化完成后,退后一步整体评估:
对比前后:
- 简化后的版本是否真正更容易理解?
- 是否引入与代码库不一致的新模式?
- diff 是否干净且适合审查?
- 团队成员是否会同意这次变更?
如果"简化后"的版本更难理解或审查,请回退。并非每次简化尝试都能成功。
// 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.
| 借口 | 事实 |
|---|---|
| "已经能用了,不需要改" | 难以阅读但能工作的代码,在出问题时也难以修复。现在简化可以为你将来的每次变更节省时间。 |
| "行数越少越简单" | 1 行的嵌套三元表达式并不比 5 行的 if/else 更简单。简单关乎理解速度,而非行数。 |
| "我顺便把这段无关的代码也简化一下" | 未限定范围的简化在 diff 中产生噪音,并在你没打算改的代码中引入回归风险。保持专注。 |
| "类型定义已经足够文档化了" | 类型记录的是结构,不是意图。命名良好的函数比类型签名更好地解释了"为什么"。 |
| "这个抽象以后可能会用到" | 不要保留推测性的抽象。如果现在没用到,它只是没有价值的复杂度。移除它,需要时再加回来。 |
| "原作者肯定有原因" | 也许有。检查 git blame —— 应用切斯特顿之栏。但累积的复杂度常常没有原因,只是赶时间迭代的残留。 |
| "我顺便在加这个功能时重构一下" | 把重构和功能开发分开。混合的变更更难审查、更难回退、更难以在历史中理解。 |
完成一轮简化后: