1. 神秘命名,比天书还难懂
变量叫 a、函数叫 do_stuff?这简直是给后来人挖坑。好的名字是自解释的文档。
# 坏味道
defcalc(a, b):
return a * b - a
# 清爽版
defcalculate_net_profit(revenue, cost):
return revenue - cost
2. 超长函数,一眼望不到头
一个函数超过50行?它肯定在偷偷干好几份工。赶紧拆!单一职责不是说说而已。
# 坏味道
defprocess_user_data(data):
# 验证...
# 清洗...
# 转换...
# 保存...
# 发邮件...
pass
# 清爽版
defvalidate_data(data): ...
defclean_data(data): ...
defsave_user(user): ...
3. 重复代码,Ctrl+C/V的诅咒
看到两段相似的代码?它们迟早会背叛你。把共同逻辑抽成函数,一改全改。
# 坏味道
discount_price = price * 0.9if user.is_vip else price
final_price = total * 0.9if user.is_vip else total
# 清爽版
defapply_vip_discount(price, user):
return price * 0.9if user.is_vip else price
4. 过度参数化,调用时手抖
函数参数超过3个?你的大脑CPU要过载了。试试用字典或数据类打包传入。
# 坏味道
create_report(title, author, date, format, style, lang, ...)
# 清爽版
from dataclasses import dataclass
@dataclass
classReportConfig:
title: str
author: str
date: str
# ...
create_report(config)
5. 巨型类,啥活都往里塞
一个类上千行?它已经膨胀成“上帝对象”了。按功能拆分成多个小而美的类。
# 坏味道
classUserManager:
defhandle_login(self): ...
defsend_email(self): ...
defgenerate_pdf(self): ... # 啊?
# 清爽版
classLoginService: ...
classEmailService: ...
classPDFGenerator: ...
6. 深层嵌套,if套if套if
代码缩进超过三层?恭喜你,进入了迷宫。尽早return或用卫语句(guard clauses)扁平化。
# 坏味道
if user:
if user.is_active:
if user.has_permission:
do_something()
# 清爽版
ifnot user:
return
ifnot user.is_active:
return
ifnot user.has_permission:
return
do_something()
7. 魔法数字/字符串,猜谜游戏
代码里到处是 if status == 3?没人知道3代表啥。用常量或枚举代替。
# 坏味道
if order.status == 2:
process_order(order)
# 清爽版
from enum import Enum
classOrderStatus(Enum):
PENDING = 1
CONFIRMED = 2
SHIPPED = 3
if order.status == OrderStatus.CONFIRMED:
process_order(order)
8. 异常处理,生吞不吭声
用空的 except:?这是在埋定时炸弹。要么处理,要么记录,别假装没事发生。
# 坏味道
try:
risky_operation()
except:
pass# 啊!错误消失了!
# 清爽版
import logging
try:
risky_operation()
except SpecificError as e:
logging.error(f"Operation failed: {e}")
raise# 或者做恰当的恢复
9. 过度工程,为了设计而设计
上来就搞工厂、策略、观察者?别让简单问题复杂化。YAGNI(你不会需要它)原则要牢记。
# 坏味道 (为一个简单的配置读取搞个抽象层)
classConfigReader(ABC):
@abstractmethod
defread(self): ...
classJSONConfigReader(ConfigReader): ...
# 清爽版
import json
defread_config(path):
with open(path) as f:
return json.load(f)
10. 忽略类型提示,动态一时爽
函数签名像谜语?加上类型提示吧。它不仅是文档,还能被工具检查,减少低级错误。
# 坏味道
deffetch_data(url, retries):
...
# 清爽版
from typing import Optional
import requests
deffetch_data(url: str, retries: int = 3) -> Optional[requests.Response]:
...