过度设计表现为类冗余、分层过深、装饰器堆叠、类型提示滥用;应优先用字典或dataclass,限制包层级和装饰器数量,用运行时检查替代复杂类型注解。

什么时候 class 是多余的
当你只需要存几个字段、调用一两次逻辑,却写了 5 个方法、3 层继承、还加了 __slots__ 和类型注解——大概率过头了。Python 的 dict、namedtuple、dataclass(不带 __post_init__ 或验证)往往更合适。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先写函数或字典,跑通逻辑再说要不要封装
- 如果只读结构,优先用
namedtuple或types.SimpleNamespace - 用
@dataclass时,避免一上来就加__eq__、__hash__、__repr__自定义——默认行为够用就别动 - 检查类里有没有超过 2 个非
__init__方法;有,就问一句:这些真不能拆成独立函数?
import 太深是不是设计坏了
看到 from project.src.services.user.auth.middleware.validators import EmailValidator 这种路径,不是路径长的问题,是模块职责模糊的信号。过度分层会让改一个邮箱校验逻辑,得跳 4 个文件、改 3 个 __init__.py。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 包层级不超过 3 层(如
app/feature/model.py),再深就该合并或重命名 - 每个包下
__init__.py暴露的符号不超过 3 个,否则说明接口边界没想清 - 避免 “utils”、“helpers”、“common” 这类筐型包——它们往往是设计断点的藏身处
- 运行
python -m pyclbr your_module看实际被引用关系,比目录结构更真实
装饰器堆叠到 5 层还在加新功能
@cache + @retry + @log_execution + @validate_input + @require_role —— 这不是优雅,是调试噩梦。每层都可能吞异常、改返回、干扰上下文。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 单个函数上装饰器别超 2 个;超过就提取成组合函数,比如
with_auth_and_retry(func) - 把日志、缓存、重试这些横切关注点,收口到统一的执行器(如
run_with_policy(func, policy="auth+cache")),而不是靠装饰器链 - 写装饰器前先问:这个逻辑是否在 3 个以上函数里重复?没达到就别抽象
- 用
functools.wraps是基本操作,但更关键的是:别让装饰器改变原函数签名——否则 IDE 补全和类型检查全失效
类型提示写满但运行时从不校验
写了 def process(items: List[Dict[str, Union[int, str]]]) -> Optional[Tuple[str, float]]:,结果传个 None 进去直接 AttributeError,类型提示根本没拦住任何问题。这时候类型系统成了幻觉安慰剂。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 如果不用
mypy或pyright做静态检查,就别写复杂类型——写items: list足够,省得误导自己 - 对关键入参做运行时轻量检查,比如
if not isinstance(items, (list, tuple)):,比堆类型提示实在 - 用
TypedDict代替嵌套Dict[str, ...],IDE 支持好,且能配合isinstance(obj, typing.TypedDict)(注意:运行时需用typing_extensions) - 别给私有函数加完整类型——它们本就不该暴露契约,加了反而拖慢迭代
真正难的不是识别过度设计,是敢删掉已经 merge 到 main 的那 200 行“很酷但没人看懂”的抽象代码。删之前没人拦你,删之后没人记得它存在过——这才是最常被忽略的现实。










