code-quality-principles

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Table of Contents

目录

Code Quality Principles

代码质量原则

Guidance on KISS, YAGNI, and SOLID principles with language-specific examples.
提供KISS、YAGNI和SOLID原则的相关指导,以及各语言的示例。

When To Use

适用场景

  • Improving code readability and maintainability
  • Applying SOLID, KISS, YAGNI principles during refactoring
  • 提升代码的可读性与可维护性
  • 在重构过程中应用SOLID、KISS、YAGNI原则

When NOT To Use

不适用场景

  • Throwaway scripts or one-time data migrations
  • Performance-critical code where readability trades are justified
  • 一次性脚本或临时数据迁移任务
  • 性能优先的代码场景,此时可读性可以适当让步

KISS (Keep It Simple, Stupid)

KISS(保持简单,别搞复杂)

Principle: Avoid unnecessary complexity. Prefer obvious solutions over clever ones.
原则:避免不必要的复杂度。优先选择直观的解决方案,而非巧妙但晦涩的实现。

Guidelines

指导准则

PreferAvoid
Simple conditionalsComplex regex for simple checks
Explicit codeMagic numbers/strings
Standard patternsClever shortcuts
Direct solutionsOver-abstracted layers
推荐避免
简单条件判断用复杂正则处理简单检查
显式代码魔法数字/字符串
标准设计模式取巧的捷径
直接解决方案过度抽象的层级

Python Example

Python 示例

python
undefined
python
undefined

Bad: Overly clever one-liner

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]
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

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)
undefined
users = [] for user_id in ids: user = db.get(user_id) if user and user.active and not user.banned: users.append(user)
undefined

Rust Example

Rust 示例

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)
}
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)

YAGNI(你不会用到它)

Principle: Don't implement features until they are actually needed.
原则:除非确实需要,否则不要实现新功能。

Guidelines

指导准则

DoDon't
Solve current problemBuild for hypothetical futures
Add when 3rd use case appearsCreate abstractions for 1 use case
Delete dead codeKeep "just in case" code
Minimal viable solutionPremature optimization
建议做法避免做法
解决当前问题为假设的未来需求做开发
出现第三个用例时再添加只为一个用例创建抽象
删除无用代码保留“以防万一”的代码
最小可行解决方案过早优化

Python Example

Python 示例

python
undefined
python
undefined

Bad: Premature abstraction for one use case

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))
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

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()]
undefined
def process_csv(data: list[str]) -> list[dict]: return [parse_row(row) for row in data if row.strip()]
undefined

TypeScript Example

TypeScript 示例

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,
};
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 Principles

SOLID 原则

Single Responsibility Principle

单一职责原则

Each module/class should have one reason to change.
python
undefined
每个模块/类应该只有一个修改的理由。
python
undefined

Bad: Multiple responsibilities

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

Good: Separated responsibilities

class UserRepository: def create(self, data): ...
class EmailService: def send_welcome(self, user): ...
class UserReportGenerator: def generate(self, users): ...
undefined
class UserRepository: def create(self, data): ...
class EmailService: def send_welcome(self, user): ...
class UserReportGenerator: def generate(self, users): ...
undefined

Open/Closed Principle

开闭原则

Open for extension, closed for modification.
python
undefined
对扩展开放,对修改关闭。
python
undefined

Bad: Requires modification for new types

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

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

Liskov Substitution Principle

里氏替换原则

Subtypes must be substitutable for their base types.
python
undefined
子类必须能够替换其基类使用。
python
undefined

Bad: Violates LSP - Square changes Rectangle behavior

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

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): ...
undefined
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): ...
undefined

Interface Segregation Principle

接口隔离原则

Clients shouldn't depend on interfaces they don't use.
typescript
// 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 { /* ... */ }
}
客户端不应该依赖它不需要的接口。
typescript
// 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 { /* ... */ }
}

Dependency Inversion Principle

依赖倒置原则

Depend on abstractions, not concretions.
python
undefined
依赖抽象,而非具体实现。
python
undefined

Bad: Direct dependency on concrete class

Bad: Direct dependency on concrete class

class OrderService: def init(self): self.db = PostgresDatabase() # Tight coupling
class OrderService: def init(self): self.db = PostgresDatabase() # Tight coupling

Good: Depend on abstraction

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

Quick Reference

快速参考

PrincipleQuestion to AskRed Flag
KISS"Is there a simpler way?"Complex solution for simple problem
YAGNI"Do I need this right now?"Building for hypothetical use cases
SRP"What's the one reason to change?"Class doing multiple jobs
OCP"Can I extend without modifying?"Switch statements for types
LSP"Can subtypes replace base types?"Overridden methods with side effects
ISP"Does client need all methods?"Empty method implementations
DIP"Am I depending on abstractions?"
new
keyword in business logic
原则自问问题危险信号
KISS“有没有更简单的方式?”用复杂方案解决简单问题
YAGNI“我现在就需要这个吗?”为假设的用例做开发
SRP“它只有一个修改理由吗?”一个类负责多项工作
OCP“我能在不修改的情况下扩展它吗?”针对类型的switch语句
LSP“子类能替换基类使用吗?”重写的方法有意外副作用
ISP“客户端需要所有方法吗?”空方法实现
DIP“我依赖的是抽象吗?”业务逻辑中使用
new
关键字

When Principles Conflict

当原则发生冲突时

  1. KISS vs SOLID: For small projects, KISS wins. Add SOLID patterns as complexity grows.
  2. YAGNI vs DIP: Don't add abstractions until you have 2+ implementations.
  3. Readability vs DRY: Prefer slight duplication over wrong abstraction.
  1. KISS vs SOLID:小型项目中优先遵循KISS。随着复杂度提升,再引入SOLID模式。
  2. YAGNI vs DIP:除非有2个及以上实现,否则不要添加抽象。
  3. 可读性 vs DRY:宁愿接受轻微重复,也不要错误的抽象。

Integration with Code Review

与代码评审的结合

When reviewing code, check:
  • No unnecessary complexity (KISS)
  • No speculative features (YAGNI)
  • Each class has single responsibility (SRP)
  • No god classes (> 500 lines)
  • Dependencies are injected, not created (DIP)
Verification: Run
wc -l <file>
to check line counts and
grep -c "class " <file>
to count classes per file.
评审代码时,检查以下内容:
  • 无不必要的复杂度(KISS)
  • 无投机性功能(YAGNI)
  • 每个类只有单一职责(SRP)
  • 无上帝类(超过500行)
  • 依赖是注入的,而非直接创建的(DIP)
验证方法:运行
wc -l <file>
检查代码行数,运行
grep -c "class " <file>
统计每个文件中的类数量。