keep-it-simple
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseKeep It Simple
保持简洁
<purpose>
Claude loves elegant abstractions. User asks for a button, Claude builds a
component factory with theming support. The problem: abstractions have costs.
They obscure intent, add indirection, and often solve problems that never
materialize. This skill enforces YAGNI - You Aren't Gonna Need It.
</purpose>
<purpose>
Claude热衷于优雅的抽象。用户要一个按钮,Claude却构建了带主题支持的组件工厂。问题在于:抽象是有成本的。它们会模糊意图、增加间接性,而且往往解决的是从未实际出现的问题。这个原则强制遵循YAGNI——You Aren't Gonna Need It(你不会需要它)。
</purpose>
When To Activate
何时启用
<triggers>
- About to create a factory, builder, or abstract base class
- Proposing a config-driven solution
- Using phrases like "for flexibility" or "in case we need"
- Creating a utility for something done twice
- Adding parameters "for future use"
- Building infrastructure before the feature
</triggers>
<triggers>
- 即将创建工厂、建造者或抽象基类
- 提议采用配置驱动的解决方案
- 使用“为了灵活性”或“以防我们需要”这类表述
- 为仅做过两次的操作创建工具函数
- 添加“为未来使用”预留的参数
- 在功能开发前先搭建基础设施
</triggers>
Instructions
操作指南
The YAGNI Test
YAGNI测试
Before adding abstraction, answer honestly:
markdown
undefined在添加抽象前,诚实地回答以下问题:
markdown
undefinedComplexity Check
复杂度检查
I want to add: [describe the abstraction]
Because: [your justification]
Is this solving a problem we have TODAY?
- Yes, we have 3+ concrete cases now
- No, but we might need it later
If "might need later": Don't build it. Stop.
undefined我想要添加的抽象: [描述该抽象]
理由: [你的正当性说明]
这是否在解决我们当前就存在的问题?
- 是,我们现在已有3个及以上的具体案例
- 否,但我们以后可能需要
如果选“以后可能需要”: 不要构建它。立即停止。
undefinedThe Rule of Three
三次原则
Abstract when you have three concrete cases, not before:
| Situation | Action |
|---|---|
| 1 case | Just write it |
| 2 cases | Copy-paste is fine. Note the duplication. |
| 3 cases | Now consider abstracting |
// With 1 button: just make the button
<button class="blue">Save</button>
// With 2 buttons: copy-paste is fine
<button class="blue">Save</button>
<button class="red">Delete</button>
// With 3+ buttons: NOW consider a component
<Button color="blue">Save</Button>
<Button color="red">Delete</Button>
<Button color="gray">Cancel</Button>当你有3个及以上具体案例时再进行抽象,在此之前不要:
| 场景 | 操作 |
|---|---|
| 1个案例 | 直接编写代码 |
| 2个案例 | 复制粘贴即可,记录下重复的部分 |
| 3个及以上案例 | 此时再考虑抽象 |
// 1个按钮的情况:直接写按钮
<button class="blue">Save</button>
// 2个按钮的情况:复制粘贴没问题
<button class="blue">Save</button>
<button class="red">Delete</button>
// 3个及以上按钮的情况:此时再考虑组件
<Button color="blue">Save</Button>
<Button color="red">Delete</Button>
<Button color="gray">Cancel</Button>Abstraction Warning Signs
抽象的警示信号
Watch for these phrases in your thinking:
- "For flexibility..." → Flexibility for what? Do we need it?
- "In case we need to..." → We don't need to yet.
- "This could be configurable..." → Is anyone asking to configure it?
- "To support future..." → Future isn't asking for support.
- "For extensibility..." → Extend it when you need to.
Watch for these patterns:
- Factory that produces one type
- Config object with one option
- Abstract class with one implementation
- Utility function used once
- Parameters that are always the same value
留意你思考过程中的这些表述:
- “为了灵活性……” → 为了什么灵活性?我们真的需要吗?
- “以防我们需要……” → 我们现在并不需要。
- “这个可以做成可配置的……” → 有人要求配置它吗?
- “为了支持未来的……” → 未来并没有要求支持。
- “为了扩展性……” → 需要扩展时再去扩展。
留意这些模式:
- 只生成一种类型的工厂
- 只有一个选项的配置对象
- 只有一个实现的抽象类
- 只被使用过一次的工具函数
- 始终取相同值的参数
Simplest Solutions
最简解决方案
| Instead of | Try |
|---|---|
| Factory pattern | Direct instantiation |
| Abstract base class | Concrete class |
| Config-driven behavior | Hardcoded behavior |
| Dependency injection | Direct imports |
| Custom event system | Callbacks |
| Generic utility | Inline code |
| 替代方案 | 尝试方案 |
|---|---|
| 工厂模式 | 直接实例化 |
| 抽象基类 | 具体类 |
| 配置驱动行为 | 硬编码行为 |
| 依赖注入 | 直接导入 |
| 自定义事件系统 | 回调函数 |
| 通用工具函数 | 内联代码 |
When Abstraction IS Right
何时抽象才是正确的选择
Abstraction is warranted when:
- You have 3+ concrete, existing cases
- The pattern is stable (not still changing)
- The duplication is causing actual bugs
- You're building a library for others
在以下情况下,抽象是合理的:
- 你已有3个及以上具体的、已存在的案例
- 模式已稳定(不再变化)
- 重复代码已导致实际的bug
- 你正在为他人构建库
Output Format
输出格式
When resisting complexity:
markdown
undefined当拒绝复杂方案时:
markdown
undefinedKeeping It Simple
保持简洁
Considered: [the abstraction]
Rejected because: [only N cases / speculative / etc.]
Instead: [simpler approach]
When complexity is warranted:
```markdown原本考虑的方案: [抽象内容]
拒绝理由: [仅N个案例 / 过于理想化 / 等]
替代方案: [更简单的实现方式]
当复杂方案合理时:
```markdownAbstraction Justified
抽象合理性说明
Adding: [the abstraction]
Because: [3+ cases / causing bugs / stable pattern]
Cases: [list the concrete cases]
undefined将添加的抽象: [抽象内容]
理由: [3个及以上案例 / 已导致bug / 模式稳定]
案例: [列出具体案例]
undefinedNEVER
绝对禁止
- Build factories for single types
- Create abstract classes before concrete ones
- Add config options nobody asked for
- Build "infrastructure" before the feature
- Say "for future extensibility" as justification
- Create utilities for one-time operations
- 为单一类型构建工厂
- 在实现具体类前先创建抽象类
- 添加没人要求的配置选项
- 在开发功能前先搭建“基础设施”
- 以“为了未来扩展性”作为理由
- 为一次性操作创建工具函数
ALWAYS
必须遵循
- Start with the simplest thing that works
- Wait for three concrete cases before abstracting
- Prefer duplication over premature abstraction
- Let patterns emerge from real usage
- Ask "do we need this TODAY?"
- 从最简单的可行方案开始
- 等有3个具体案例后再考虑抽象
- 宁愿重复代码也不要过早抽象
- 让模式从实际使用中自然浮现
- 问自己:“我们现在真的需要这个吗?”
Example
示例
User: "Add a way to send notification emails"
Over-engineered approach:
NotificationFactory
├── EmailNotification
├── SMSNotification (might need later!)
├── PushNotification (could be useful!)
└── NotificationConfig
├── templates
├── retryPolicy
└── queueSettingsYAGNI approach:
python
def send_notification_email(user, subject, body):
email_service.send(
to=user.email,
subject=subject,
body=body
)Why simpler is better:
- User asked for email. Just do email.
- SMS and Push aren't requested. Don't build them.
- Config can be added when there's something to configure.
- If we need SMS later, we'll add it then.
The 5-line function solves the actual problem. The factory solves imaginary ones.
<failed-attempts>
What DOESN'T work:
- "Just in case": Building for cases that don't exist yet. They may never exist.
- "It's more elegant": Elegance is not a requirement. Working is a requirement.
- "This pattern is best practice": Best practices are context-dependent. A pattern for 100 cases is overkill for 1.
- Abstracting after 2 cases: You don't know the pattern yet. Wait for the third.
- Config files for one setting: Hardcode it. Add config when there are multiple settings to configure.
- "Future-proofing": You can't predict the future. Build for now.
- Dependency injection everywhere: Direct imports are fine. DI is for when you actually need to swap implementations.
- Generic utilities from day one: Write the specific code. Extract utility when you have 3+ uses.
- "Flexibility": Flexibility without a use case is just indirection.
- Building the platform before the product: Ship the feature. Build infrastructure when you need it.
用户需求: “添加发送通知邮件的功能”
过度工程的实现方式:
NotificationFactory
├── EmailNotification
├── SMSNotification(以后可能需要!)
├── PushNotification(可能有用!)
└── NotificationConfig
├── templates
├── retryPolicy
└── queueSettingsYAGNI原则下的实现方式:
python
def send_notification_email(user, subject, body):
email_service.send(
to=user.email,
subject=subject,
body=body
)为什么更简单的方案更好:
- 用户只要求了邮件功能,就只做邮件。
- SMS和推送功能并未被要求,不要去构建。
- 等有需要配置的内容时再添加配置。
- 如果以后需要SMS功能,到时再添加即可。
这个5行的函数解决了实际问题,而工厂模式解决的是想象中的问题。
<failed-attempts>
以下做法不可取:
- “以防万一”:为不存在的场景构建功能,这些场景可能永远不会出现。
- “这样更优雅”:优雅不是必须的,能正常工作才是。
- “这是最佳实践”:最佳实践是依赖场景的。适用于100个案例的模式,用在1个案例上就是过度设计。
- 在2个案例后就抽象:你还没摸清模式,等第三个案例出现再说。
- 为单个配置项创建配置文件:直接硬编码。等有多个配置项需要管理时再添加配置文件。
- “为未来做准备”:你无法预测未来,为当下构建即可。
- 到处使用依赖注入:直接导入就很好。只有当你真的需要切换实现时才用DI。
- 从第一天就构建通用工具:先写特定的代码,等有3次及以上使用场景时再提取成工具函数。
- “灵活性”:没有使用场景的灵活性只是间接性的体现。
- 在产品前先搭建平台:先发布功能,等需要时再构建基础设施。