关于 code-quality-principles
面向开发者的编码技能,通过原则说明和 Python、Rust、TypeScript 示例讲解 KISS、YAGNI 与 SOLID,适用于重构中的可读性和可维护性改进。
主要功能
- 01KISS、YAGNI 与 SOLID 指引
- 02按语言提供代码示例
- 03代码审查检查清单
- 04原则冲突处理建议
适用场景
- 01重构以提升可读性和可维护性
- 02审查代码是否存在不必要的复杂性
- 03权衡简洁方案与抽象设计
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ athola/ claude-night-market --skill code-quality-principles安装后在 Claude Code 中输入/code-quality-principles确认已加载。
详细介绍
代码质量原则
介绍 KISS、YAGNI 和 SOLID 原则,并提供特定语言的示例。
适用场景
- 提高代码的可读性和可维护性
- 重构期间应用 SOLID、KISS 和 YAGNI 原则
不适用场景
- 一次性脚本或仅运行一次的数据迁移
- 性能关键型代码,且有理由牺牲可读性
KISS(Keep It Simple, Stupid)
原则:避免不必要的复杂性。优先选择直观的解决方案,而不是巧妙的方案。
指南
| 优先选择 | 避免 |
|---|---|
| 简单的条件判断 | 用复杂正则表达式处理简单检查 |
| 明确的代码 | 魔法数字/字符串 |
| 标准模式 | 巧妙的捷径 |
| 直接的解决方案 | 过度抽象的层次 |
Python 示例
# Bad: Overly clever one-liner
users = [u for u in (db.get(id) for id in ids) if u and u.active and not u.banned]
# Good: Clear and readable
users = []
for user_id in ids:
user = db.get(user_id)
if user and user.active and not user.banned:
users.append(user)
Rust 示例
// Bad: Unnecessary complexity
fn process(data: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
data.iter()
.map(|&b| b.checked_add(1).ok_or("overflow"))
.collect::<Result<Vec<_>, _>>()
.map_err(|e| e.into())
}
// Good: Simple and clear
fn process(data: &[u8]) -> Result<Vec<u8>, &'static str> {
let mut result = Vec::with_capacity(data.len());
for &byte in data {
result.push(byte.checked_add(1).ok_or("overflow")?);
}
Ok(result)
}
YAGNI(You Aren't Gonna Need It)
原则:在功能真正需要之前,不要实现它。
指南
| 要做 | 不要做 |
|---|---|
| 解决当前问题 | 为假想的未来做准备 |
| 出现第 3 个使用场景时再添加 | 为 1 个使用场景创建抽象 |
| 删除无用代码 | 保留“以防万一”的代码 |
| 提供最小可行解决方案 | 过早优化 |
Python 示例
# Bad: Premature abstraction for one use case
class AbstractDataProcessor:
def process(self, data): ...
def validate(self, data): ...
def transform(self, data): ...
class CSVProcessor(AbstractDataProcessor):
def process(self, data):
return self.transform(self.validate(data))
# Good: Simple function until more cases appear
def process_csv(data: list[str]) -> list[dict]:
return [parse_row(row) for row in data if row.strip()]
TypeScript 示例
// Bad: Over-engineered config system
interface ConfigProvider<T> {
get<K extends keyof T>(key: K): T[K];
set<K extends keyof T>(key: K, value: T[K]): void;
watch<K extends keyof T>(key: K, callback: (v: T[K]) => void): void;
}
// Good: Simple config for current needs
const config = {
apiUrl: process.env.API_URL || 'http://localhost:3000',
timeout: 5000,
};
SOLID 原则
单一职责原则
每个模块/类都应该只有一个变更理由。
# Bad: Multiple responsibilities
class UserManager:
def create_user(self, data): ...
def send_welcome_email(self, user): ... # Email responsibility
def generate_report(self, users): ... # Reporting responsibility
# Good: Separated responsibilities
class UserRepository:
def create(self, data): ...
class EmailService:
def send_welcome(self, user): ...
class UserReportGenerator:
def generate(self, users): ...
开闭原则
对扩展开放,对修改关闭。
# Bad: Requires modification for new types
def calculate_area(shape):
if shape.type == "circle":
return 3.14 * shape.radius**2
elif shape.type == "rectangle":
return shape.width * shape.height
# Must modify to add new shapes
# Good: Extensible without modification
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self) -> float: ...
class Circle(Shape):
def __init__(self, radius: float):
self.radius = radius
def area(self) -> float:
return 3.14 * self.radius**2
里氏替换原则
子类型必须能够替换其基类型。
# Bad: Violates LSP - Square changes Rectangle behavior
class Rectangle:
def set_width(self, w):
self.width = w
def set_height(self, h):
self.height = h
class Square(Rectangle): # Breaks when used as Rectangle
def set_width(self, w):
self.width = self.height = w # Unexpected side effect
# Good: Separate types with common interface
class Shape(ABC):
@abstractmethod
def area(self) -> float: ...
class Rectangle(Shape):
def __init__(self, width: float, height: float): ...
class Square(Shape):
def __init__(self, side: float): ...
接口隔离原则
客户端不应依赖它们不会使用的接口。
// Bad: Fat interface
interface Worker {
work(): void;
eat(): void;
sleep(): void;
}
// Good: Segregated interfaces
interface Workable {
work(): void;
}
interface Feedable {
eat(): void;
}
// Clients only implement what they need
class Robot implements Workable {
work(): void { /* ... */ }
}
依赖倒置原则
依赖抽象,而不是具体实现。
# Bad: Direct dependency on concrete class
class OrderService:
def __init__(self):
self.db = PostgresDatabase() # Tight coupling
# Good: Depend on abstraction
from abc import ABC, abstractmethod
class Database(ABC):
@abstractmethod
def save(self, data): ...
class OrderService:
def __init__(self, db: Database):
self.db = db # Injected abstraction
快速参考
| 原则 | 要问的问题 | 警示信号 |
|---|---|---|
| KISS | “有没有更简单的方法?” | 用复杂方案解决简单问题 |
| YAGNI | “我现在需要这个吗?” | 为假想的使用场景构建功能 |
| SRP | “变更的唯一理由是什么?” | 类承担多项职责 |
| OCP | “能否在不修改的情况下扩展?” | 针对类型的 switch 语句 |
| LSP | “子类型能否替换基类型?” | 重写的方法带有副作用 |
| ISP | “客户端需要所有方法吗?” | 空方法实现 |
| DIP | “我依赖的是抽象吗?” | 业务逻辑中使用 new 关键字 |
原则冲突时的处理
- KISS 与 SOLID:对于小型项目,优先遵循 KISS。随着复杂性增加,再加入 SOLID 模式。
- YAGNI 与 DIP:在有 2 个或更多实现之前,不要添加抽象。
- 可读性与 DRY:宁可略微重复,也不要采用错误的抽象。
与代码审查的结合
审查代码时,请检查:
- 没有不必要的复杂性(KISS)
- 没有推测性功能(YAGNI)
- 每个类都只有单一职责(SRP)
- 没有上帝类(> 500 行)
- 依赖通过注入提供,而不是自行创建(DIP)
**验证:**运行 wc -l <file> 检查行数,并运行 rg -c "class " <file>(或 grep -c "class " <file>)统计每个文件中的类数量。
相关技能
imbue:karpathy-principles- “简洁优先”原则将 KISS、YAGNI 和 SOLID 融合为四项原则的综合体系,源自 Karpathy 对 LLM 编码陷阱的观察- 完整的关卡与技能联邦图请参阅
docs/quality-gates.md#skill-level-quality-gate-composition
退出标准
- 每项拟议的代码更改都已根据集成审查清单检查:没有不必要的复杂性(KISS)、没有推测性功能(YAGNI)、每个类仅承担一项职责(SRP)、没有超过 500 行的巨型类、依赖通过注入而非创建(DIP)
- 当 KISS 与 SOLID 冲突时,已记录解决方式:小型项目优先采用 KISS,随着复杂性增加再应用 SOLID 模式。明确说明选择,不得默默处理
- 对任何已修改文件运行
wc -l <file>;如果文件超过 500 行(巨型类阈值),则记录结果 - 除非作为测试的模拟边界,否则不引入只有一个实现者的新抽象
评论
支持 Markdown