Files
2026-07-13 21:36:32 +08:00

844 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Clean Code Principles
# 整洁代码原则
## Core Principles
## 核心原则
### 1. Meaningful Names
### 1. 有意义的命名
**Variables**:
**变量**
```python
# BAD
d = 10 # What is 'd'?
t = time.time()
# GOOD
elapsed_days = 10
current_timestamp = time.time()
```
**Functions**:
**函数**
```python
# BAD
def process(data):
pass
# GOOD
def calculate_user_average_score(user_scores):
pass
```
**Classes**:
**类**
```python
# BAD
class Data:
pass
# GOOD
class CustomerOrderProcessor:
pass
```
**Boolean variables** - use predicates:
**布尔变量**——使用谓词:
```python
# BAD
flag = True
status = False
# GOOD
is_active = True
has_permission = False
can_edit = True
should_retry = False
```
---
### 2. Functions Should Do One Thing
### 2. 函数应该只做一件事
**BAD** - Multiple responsibilities:
**反面示例**——多重职责:
```python
def process_user_data(user):
# Validate
if not user.email:
raise ValueError("Email required")
# Transform
user.name = user.name.upper()
# Save to database
db.save(user)
# Send email
email_service.send_welcome(user.email)
# Log
logger.info(f"User processed: {user.id}")
```
**GOOD** - Single responsibility:
**正面示例**——单一职责:
```python
def validate_user(user):
if not user.email:
raise ValueError("Email required")
def normalize_user_data(user):
user.name = user.name.upper()
return user
def save_user(user):
db.save(user)
def send_welcome_email(email):
email_service.send_welcome(email)
def process_user_data(user):
validate_user(user)
user = normalize_user_data(user)
save_user(user)
send_welcome_email(user.email)
logger.info(f"User processed: {user.id}")
```
---
### 3. Keep Functions Small
### 3. 保持函数短小
**Guideline**: Aim for 10-20 lines per function.
**指导原则**:每个函数控制在 1020 行。
**BAD** - 100+ line function:
**反面示例**——超过 100 行的函数:
```python
def generate_report(users):
# 100 lines of mixed logic
# Filtering, sorting, formatting, calculations, file I/O
pass
```
**GOOD** - Extracted functions:
**正面示例**——提取后的函数:
```python
def generate_report(users):
active_users = filter_active_users(users)
sorted_users = sort_by_activity(active_users)
report_data = calculate_statistics(sorted_users)
formatted_report = format_report(report_data)
save_report(formatted_report)
def filter_active_users(users):
return [u for u in users if u.is_active]
def sort_by_activity(users):
return sorted(users, key=lambda u: u.activity_score, reverse=True)
```
---
### 4. DRY (Don't Repeat Yourself)
### 4. DRY(不要重复自己)
**BAD** - Duplication:
**反面示例**——重复代码:
```python
def calculate_student_grade(math_score, science_score):
if math_score >= 90:
math_grade = 'A'
elif math_score >= 80:
math_grade = 'B'
elif math_score >= 70:
math_grade = 'C'
else:
math_grade = 'F'
if science_score >= 90:
science_grade = 'A'
elif science_score >= 80:
science_grade = 'B'
elif science_score >= 70:
science_grade = 'C'
else:
science_grade = 'F'
return math_grade, science_grade
```
**GOOD** - Extract common logic:
**正面示例**——提取公共逻辑:
```python
def score_to_grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
return 'F'
def calculate_student_grade(math_score, science_score):
return score_to_grade(math_score), score_to_grade(science_score)
```
---
### 5. Avoid Magic Numbers
### 5. 避免魔数
**BAD**:
**反面示例**
```python
if age > 18:
can_vote = True
if len(password) < 8:
raise ValueError("Password too short")
```
**GOOD**:
**正面示例**
```python
VOTING_AGE = 18
MIN_PASSWORD_LENGTH = 8
if age > VOTING_AGE:
can_vote = True
if len(password) < MIN_PASSWORD_LENGTH:
raise ValueError(f"Password must be at least {MIN_PASSWORD_LENGTH} characters")
```
---
### 6. Error Handling
### 6. 错误处理
**BAD** - Bare except, silent failures:
**反面示例**——裸 except、静默失败:
```python
try:
result = risky_operation()
except:
pass # What went wrong?
```
**GOOD** - Specific exceptions, informative messages:
**正面示例**——具体异常、信息性消息:
```python
try:
result = risky_operation()
except ValueError as e:
logger.error(f"Invalid value: {e}")
raise
except ConnectionError as e:
logger.error(f"Connection failed: {e}")
# Retry or fallback logic
```
---
### 7. Use Early Returns (Guard Clauses)
### 7. 使用提前返回(卫语句)
**BAD** - Nested conditions:
**反面示例**——嵌套条件:
```python
def process_order(order):
if order is not None:
if order.is_valid():
if order.total > 0:
if order.customer.has_credit():
# Process order
return True
return False
```
**GOOD** - Early returns:
**正面示例**——提前返回:
```python
def process_order(order):
if order is None:
return False
if not order.is_valid():
return False
if order.total <= 0:
return False
if not order.customer.has_credit():
return False
# Process order
return True
```
---
### 8. Comment Why, Not What
### 8. 注释说明「为什么」,而非「是什么」
**BAD** - Obvious comments:
**反面示例**——显而易见的注释:
```python
# Increment i by 1
i += 1
# Loop through users
for user in users:
pass
```
**GOOD** - Explain non-obvious reasoning:
**正面示例**——解释非显而易见的理由:
```python
# Use binary search because list is always sorted
# and can contain millions of items
index = binary_search(sorted_list, target)
# Cache for 5 minutes to reduce database load
# during peak hours (based on profiling data)
@cache(ttl=300)
def get_popular_products():
pass
```
---
### 9. Keep Indentation Shallow
### 9. 保持缩进深度较浅
**BAD** - Deep nesting:
**反面示例**——深层嵌套:
```python
def process_data(items):
for item in items:
if item.is_valid():
if item.quantity > 0:
if item.price > 0:
if item.in_stock:
# Process
pass
```
**GOOD** - Use early returns, extraction:
**正面示例**——使用提前返回和提取:
```python
def process_data(items):
for item in items:
if not should_process_item(item):
continue
process_item(item)
def should_process_item(item):
return (item.is_valid() and
item.quantity > 0 and
item.price > 0 and
item.in_stock)
```
---
### 10. Consistent Formatting
### 10. 一致的格式化
**Use a formatter**: Black (Python), Prettier (JavaScript), gofmt (Go)
**使用格式化工具**Black (Python)、Prettier (JavaScript)、gofmt (Go)
**Consistency matters**:
**一致性很重要**
```python
# Pick one style and stick to it
# 选择一种风格并坚持使用
# Style 1
def foo(x, y, z):
return x + y + z
# Style 2
def foo(
x,
y,
z
):
return x + y + z
# Don't mix them randomly in the same file!
# 不要在同一个文件中随意混用!
```
---
## SOLID Principles
## SOLID 原则
### S - Single Responsibility Principle
### S——单一职责原则
**A class should have one, and only one, reason to change.**
**一个类应该只有一个、且仅有一个变更理由。**
**BAD**:
**反面示例**
```python
class User:
def __init__(self, name, email):
self.name = name
self.email = email
def save(self):
# Database logic
db.execute(f"INSERT INTO users...")
def send_email(self, message):
# Email logic
smtp.send(self.email, message)
```
**GOOD**:
**正面示例**
```python
class User:
def __init__(self, name, email):
self.name = name
self.email = email
class UserRepository:
def save(self, user):
db.execute(f"INSERT INTO users...")
class EmailService:
def send_email(self, email, message):
smtp.send(email, message)
```
---
### O - Open/Closed Principle
### O——开闭原则
**Open for extension, closed for modification.**
**对扩展开放,对修改关闭。**
**BAD**:
**反面示例**
```python
class PaymentProcessor:
def process(self, payment_type, amount):
if payment_type == "credit_card":
# Credit card processing
pass
elif payment_type == "paypal":
# PayPal processing
pass
# Adding new type requires modifying this function!
```
**GOOD**:
**正面示例**
```python
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def process(self, amount):
pass
class CreditCardPayment(PaymentMethod):
def process(self, amount):
# Credit card processing
pass
class PayPalPayment(PaymentMethod):
def process(self, amount):
# PayPal processing
pass
class PaymentProcessor:
def process(self, payment_method: PaymentMethod, amount):
payment_method.process(amount)
```
---
### L - Liskov Substitution Principle
### L——里氏替换原则
**Subclasses should be substitutable for their base classes.**
**子类应该可以替换其基类。**
**BAD**:
**反面示例**
```python
class Bird:
def fly(self):
print("Flying")
class Penguin(Bird):
def fly(self):
raise Exception("Penguins can't fly!")
```
**GOOD**:
**正面示例**
```python
class Bird:
def move(self):
pass
class FlyingBird(Bird):
def move(self):
self.fly()
def fly(self):
print("Flying")
class Penguin(Bird):
def move(self):
self.swim()
def swim(self):
print("Swimming")
```
---
### I - Interface Segregation Principle
### I——接口隔离原则
**Clients should not depend on interfaces they don't use.**
**客户端不应该依赖它们不使用的方法。**
**BAD**:
**反面示例**
```python
class Worker(ABC):
@abstractmethod
def work(self):
pass
@abstractmethod
def eat(self):
pass
class Robot(Worker):
def work(self):
print("Working")
def eat(self):
# Robots don't eat!
raise NotImplementedError
```
**GOOD**:
**正面示例**
```python
class Workable(ABC):
@abstractmethod
def work(self):
pass
class Eatable(ABC):
@abstractmethod
def eat(self):
pass
class Human(Workable, Eatable):
def work(self):
print("Working")
def eat(self):
print("Eating")
class Robot(Workable):
def work(self):
print("Working")
```
---
### D - Dependency Inversion Principle
### D——依赖倒置原则
**Depend on abstractions, not concretions.**
**依赖抽象,而非具体实现。**
**BAD**:
**反面示例**
```python
class MySQLDatabase:
def save(self, data):
pass
class UserService:
def __init__(self):
self.db = MySQLDatabase() # Tightly coupled
def save_user(self, user):
self.db.save(user)
```
**GOOD**:
**正面示例**
```python
class Database(ABC):
@abstractmethod
def save(self, data):
pass
class MySQLDatabase(Database):
def save(self, data):
pass
class PostgresDatabase(Database):
def save(self, data):
pass
class UserService:
def __init__(self, database: Database):
self.db = database # Depends on abstraction
def save_user(self, user):
self.db.save(user)
```
---
## Code Smells to Avoid
## 需要避免的代码坏味
### 1. Long Parameter List
### 1. 过长的参数列表
```python
# BAD
def create_user(name, email, phone, address, city, state, zip, country):
pass
# GOOD
class UserData:
def __init__(self, name, email, contact_info, address):
pass
def create_user(user_data: UserData):
pass
```
### 2. Primitive Obsession
### 2. 基本类型偏执
```python
# BAD
def calculate_shipping(width, height, depth, weight):
pass
# GOOD
class Dimensions:
def __init__(self, width, height, depth):
self.width = width
self.height = height
self.depth = depth
class Package:
def __init__(self, dimensions, weight):
self.dimensions = dimensions
self.weight = weight
def calculate_shipping(package: Package):
pass
```
### 3. Feature Envy
### 3. 依恋情结
```python
# BAD - Method in class A uses mostly data from class B
class Order:
def calculate_total(self, customer):
discount = customer.discount_rate
points = customer.loyalty_points
# Uses customer data extensively
pass
# GOOD - Move method to class B
class Customer:
def calculate_order_discount(self, order):
discount = self.discount_rate
points = self.loyalty_points
# Uses own data
pass
```
---
## Testing Best Practices
## 测试最佳实践
### 1. AAA Pattern (Arrange-Act-Assert)
### 1. AAA 模式(Arrange-Act-Assert
```python
def test_user_creation():
# Arrange
name = "Alice"
email = "alice@example.com"
# Act
user = User(name, email)
# Assert
assert user.name == name
assert user.email == email
```
### 2. One Assertion Per Test (guideline)
### 2. 每个测试一个断言(指导原则)
```python
# AVOID multiple unrelated assertions
def test_user():
user = User("Alice", "alice@example.com")
assert user.name == "Alice"
assert user.email == "alice@example.com"
assert user.is_valid()
assert user.created_at is not None
# PREFER focused tests
def test_user_name():
user = User("Alice", "alice@example.com")
assert user.name == "Alice"
def test_user_email():
user = User("Alice", "alice@example.com")
assert user.email == "alice@example.com"
```
### 3. Test Names Should Be Descriptive
### 3. 测试名称应具有描述性
```python
# BAD
def test_user():
pass
# GOOD
def test_user_creation_with_valid_email_succeeds():
pass
def test_user_creation_with_invalid_email_raises_error():
pass
```
---
## Refactoring Checklist
## 重构检查清单
When you see code that needs improvement:
当你看到需要改进的代码时:
1. **Is it tested?** If not, write tests first
2. **One change at a time** - Refactor incrementally
3. **Run tests after each change** - Ensure nothing breaks
4. **Commit frequently** - Small, focused commits
5. **Don't change behavior** - Refactoring should preserve functionality
1. **有测试吗?** 如果没有,先编写测试
2. **一次只改一处**——增量式重构
3. **每次修改后运行测试**——确保没有破坏任何功能
4. **频繁提交**——小而专注的提交
5. **不改变行为**——重构应保留原有功能
---
## Key Takeaways
## 关键要点
1. **Names matter** - Spend time choosing good names
2. **Functions should be small** - Aim for 10-20 lines
3. **One responsibility** - Each function/class does one thing well
4. **DRY** - Don't repeat yourself
5. **SOLID** - Follow the five SOLID principles
6. **Early returns** - Reduce nesting with guard clauses
7. **Comment why** - Not what (code shows what)
8. **Test** - Write tests, refactor with confidence
1. **命名很重要**——花时间选择好的名称
2. **函数应该短小**——目标是 1020 行
3. **单一职责**——每个函数/类做好一件事
4. **DRY**——不要重复自己
5. **SOLID**——遵循五大 SOLID 原则
6. **提前返回**——使用卫语句减少嵌套
7. **注释说明「为什么」**——而非「是什么」(代码本身就展示了是什么)
8. **测试**——编写测试,自信重构
**Remember**: Clean code is not about perfection—it's about making code easier to read, maintain, and extend!
**记住**:整洁代码不在于追求完美——而在于让代码更易读、更易维护、更易扩展!