keep-it-simple

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Keep 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
undefined

Complexity 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个及以上的具体案例
  • 否,但我们以后可能需要
如果选“以后可能需要”: 不要构建它。立即停止。
undefined

The Rule of Three

三次原则

Abstract when you have three concrete cases, not before:
SituationAction
1 caseJust write it
2 casesCopy-paste is fine. Note the duplication.
3 casesNow 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 ofTry
Factory patternDirect instantiation
Abstract base classConcrete class
Config-driven behaviorHardcoded behavior
Dependency injectionDirect imports
Custom event systemCallbacks
Generic utilityInline 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
undefined

Keeping It Simple

保持简洁

Considered: [the abstraction] Rejected because: [only N cases / speculative / etc.] Instead: [simpler approach]

When complexity is warranted:

```markdown
原本考虑的方案: [抽象内容] 拒绝理由: [仅N个案例 / 过于理想化 / 等] 替代方案: [更简单的实现方式]

当复杂方案合理时:

```markdown

Abstraction Justified

抽象合理性说明

Adding: [the abstraction] Because: [3+ cases / causing bugs / stable pattern] Cases: [list the concrete cases]
undefined
将添加的抽象: [抽象内容] 理由: [3个及以上案例 / 已导致bug / 模式稳定] 案例: [列出具体案例]
undefined

NEVER

绝对禁止

  • 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
    └── queueSettings
YAGNI 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.
</failed-attempts>
用户需求: “添加发送通知邮件的功能”
过度工程的实现方式:
NotificationFactory
├── EmailNotification
├── SMSNotification(以后可能需要!)
├── PushNotification(可能有用!)
└── NotificationConfig
    ├── templates
    ├── retryPolicy
    └── queueSettings
YAGNI原则下的实现方式:
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次及以上使用场景时再提取成工具函数。
  • “灵活性”:没有使用场景的灵活性只是间接性的体现。
  • 在产品前先搭建平台:先发布功能,等需要时再构建基础设施。
</failed-attempts>