Code Organizer - 代码整理与项目重构技能
概述
本技能用于对 Python 项目进行系统性整理和重构(默认通用风格,根据具体项目类型自动适配)重要原则:始终先生成整理建议,等待用户批准后再执行任何文件修改
⚠️ 避免过度工程化 - 核心约束
整理/重构到最佳实践。所有优化措施均由用户主动选择,绝不默认执行
🔄 两轮确认流程(必须严格执行)
每次执行整理任务前,必须经过两轮用户确认,不可跳过:
第一轮:策略选择
-
扫描项目,评估规模(文件数、模块数、项目类型)
-
根据评估结果,向用户展示
可选策略列表
并给出推荐:
| 策略级别 | 适用场景 | 包含的整理措施 | | ------------ | ------------------------------------- | ------------------------------------------------------------ | | 轻量清理 | 单脚本、实验性代码、临时项目 | 无用代码清理、空目录删除、明显命名问题修复 + 简要文档 | | 标准整理 | 小型工具、数据处理管道、原型项目 | 轻量清理 + 命名规范 + import 排序 + 代码格式 + 类型标注 + 规范注释 + 标准文档 | | 深度重构 | 可发布的小库、API 服务、完整 pipeline | 标准整理 + 目录结构重组 + src layout + init.py + 配置参数化 + 测试覆盖 + 分层架构 + 详细文档 | | 全面重构 | 团队项目、商业产品级应用 | 深度重构 + DDD 设计 + 完整测试套件 + pyproject.toml + 完整文档 + 代码质量检查 |
-
向用户说明推荐级别及理由,等待用户确认或调整策略级别
第二轮:方案确认
- 基于用户选择的策略级别,生成详细的整理方案,包括:
- 具体的目录结构调整(如涉及)
- 每个需要修改的文件及修改类型
- 预计可移除的无用代码/依赖
- 新增的文件或配置
- 等待用户明确确认后方可开始执行
判断原则:
- 对于深度学习实验/数据处理原型项目:如果核心是跑通流程而非工程化,优先推荐轻量或标准策略
- 用户的策略选择是最终决定,推荐仅供参考
- 任何超出用户选择策略范围的优化,都不执行
工作流程
⚠️ 重要:防中断架构设计
核心原则:使用并行子代理拆分任务,避免单会话超时导致的中断 对于复杂项目重构(超过个文件需要修改),必须采用以下模式:
# 错误做法:串行执行所有操作
for file in files_to_modify:
read(file) # 阻塞等待
edit(file) # 阻塞等待
# 正确做法:并行子代理 + 进度持久化
phases = [
{"id": "phase-a", "task": "创建目录结构"},
{"id": "phase-b", "task": "移动文件到对应目录"},
{"id": "phase-c", "task": "更新所有 import 路径"},
{"id": "phase-d", "task": "统一变量命名和类型提示"},
{"id": "phase-e", "task": "生成三个文档文件"}
]
for phase in phases:
spawn_sub_agent(phase["id"], phase["task"]) # 并行启动
Phase 1: 扫描与策略选择(第一轮确认)
由主会话执行,轻量级操作
- 扫描项目 - 了解当前目录结构、代码规模、模块依赖关系
- 使用
exec或background=true模式进行耗时操作(如 robocopy, tree)
# 推荐:后台执行长时间任务
cmd /c "robocopy E:\\LPR E:\\LPR_backup /MIR" > backup.log 2>&1 &
- 评估项目概况 - 统计以下信息:
- 文件数量、模块数量、项目类型(深度学习/Web/API/CLI/数据处理等)
- 当前存在的问题(目录混乱、命名不一致、代码重复、注释缺失等)
- 提出策略选择(第一轮确认) - 向用户展示:
- 项目概况摘要
- 四个策略级别及其包含的整理措施(见上方策略表)
- 推荐策略及理由
- 等待用户确认或调整策略级别
Phase 1.5: 方案制定(第二轮确认)
基于用户选择的策略级别,生成详细整理方案。
- 列出具体变更:
- 目录结构调整详情(如涉及)
- 每个需要修改的文件及修改类型
- 预计可移除的无用代码/依赖
- 新增的文件或配置
- 代码风格统一的具体规范
- 等待用户明确确认后方可进入执行阶段
Phase 2: 执行修改(并行子代理)
在收到明确批准后,按以下顺序通过 sub-agents 并行执行
# 主会话根据用户选择的策略级别选择任务
strategy = user_selected_strategy # "轻量清理" | "标准整理" | "深度重构" | "全面重构"
tasks = {
# === 所有策略都适用 ===
"code-cleanup": "清理无用代码和空目录",
# === 标准整理及以上 ===
"style-unify": "代码风格统一(格式/命名/import/类型/注释)" if strategy in ["标准整理", "深度重构", "全面重构"] else None,
# === 深度重构及以上 ===
"create-structure": "创建目录结构/.gitignore" if strategy in ["深度重构", "全面重构"] else None,
"move-files-phase1": "移动核心脚本到对应目录" if strategy in ["深度重构", "全面重构"] else None,
"config-extract": "配置参数化" if strategy in ["深度重构", "全面重构"] else None,
"add-tests": "补充单元测试" if strategy in ["深度重构", "全面重构"] else None,
# === 全面重构 ===
"quality-check": "代码质量与设计规范检查" if strategy == "全面重构" else None,
"generate-docs": "生成三份文档" if strategy == "全面重构" else None,
}
tasks = {k: v for k, v in tasks.items() if v is not None} # 过滤掉不适用的任务
# 分批启动子代理(避免 token 溢出)
batch_size = 3 # 每批最多 3 个子代理
for i in range(0, len(tasks), batch_size):
batch = tasks[i:i+batch_size]
for task_id, task_desc in batch.items():
sessions_spawn(
agentId="main",
label=task_id,
task=f"""执行代码整理任务:{task_desc}
注意事项:
1. 使用相对路径操作文件
2. 每个子代理只负责自己的任务
3. 完成后将结果写入进度文件 memory/organize-progress.json
4. 如果任何步骤失败,记录错误并继续其他步骤
输出格式:
{{\"status\": \"success|failed\", \"task\": \"{task_id}\",
\"files_modified\": [...], \"errors\": [...]}}""")
A. 目录结构调整(子代理任务,深度重构及以上策略)
轻量/标准策略:保持现有结构,不做目录重组 深度重构及以上:
project-root/
├── src/ # 源代码
│ └── package_name/ # 主包
├── tests/ # 测试代码(可选)
├── configs/ # 配置文件(可选,参数 >3 时建议)
├── scripts/ # 辅助脚本、CLI 工具
├── docs/ # 项目文档(仅中型以上)
└── ...
根据项目类型可调整:
- Web/API 应用 -
src/app/routes.py,src/app/services/ - 数据处理项目 -
src/pipeline/,data/,notebooks/ - 深度学习项目 -
models/,trainers/,experiments/
B. 代码风格统一(子代理任务,标准整理及以上策略)
轻量清理策略跳过此步骤 - 标准整理及以上策略执行以下全部规则:
B1. 代码格式规范
- 行长限制:单行不超过 88 字符(Black 默认)或 120 字符(Ruff 推荐)
- 缩进:空格(Python PEP 8 标准),禁止混用 Tab 和空格
- 空行:顶层定义之间 2 空行,类方法之间 1 空行,函数内逻辑块之间可 1 空行
- 行尾:不保留多余空白字符,文件末尾保留一个换行符
- 引号:统一使用双引号
"(字符串内容含双引号时使用单引号') - 运算符周围:二元运算符两侧各一个空格(
a + b),一元运算符紧贴操作数(-x) - 逗号后:跟一个空格(
[1, 2, 3]) - 工具推荐:使用 Black 或 Ruff format 自动格式化
B2. 命名规范
- 模块/包名:
snake_case,简短描述性(data_loader.py,user_service/) - 类名:
PascalCase(DataLoader,UserService) - 函数/方法:
snake_case,动词开头(fetch_user(),validate_input()) - 变量:
snake_case,语义化命名(user_list而非ul,parsed_records而非data) - 常量:
UPPER_SNAKE_CASE(MAX_RETRIES = 3,API_BASE_URL) - 私有成员:前导下划线(
_internal_cache,__private_method) - 布尔变量:
is_/has_/can_/should_前缀(is_valid,has_permission) - 避免:单字母变量(除
i/j/k循环索引和数学公式外)、缩写(usr为user)
B3. Import 排序
遵循三段式分组 + 组内字母序:
# 1. 标准库
import os
import sys
from pathlib import Path
# 2. 第三方库
import numpy as np
import requests
from flask import Flask
# 3. 本地模块
from .config import Settings
from .models.user import UserModel
from utils.helpers import format_date
- 优先使用绝对导入,避免相对导入(模块移动时不会自动更新)
- 每组之间空一行
- 组内按字母顺序排列
- 从每个模块做具体导入(
from .models.user import UserModel),而非import models.user - 工具推荐:使用 Ruff(
I规则)或 isort 自动排序
B4. 类型标注
- 函数签名:所有公共函数必须标注参数类型和返回类型
def fetch_user(user_id: int, include_deleted: bool = False) -> User | None:
...
- 类属性:在
__init__或类体中声明类型
class DataProcessor:
batch_size: int = 32
shuffle: bool = True
- 集合类型:使用具体泛型(
list[str]而非list,dict[str, int]而非dict) - 可选类型:使用
X | None(Python 3.10+)或Optional[X] - 联合类型:使用
A | B(Python 3.10+)或Union[A, B] - 复杂返回:使用
typing.TypeAlias定义类型别名 - 不强求:内部工具函数、一次性脚本、lambda 表达式可省略
B5. 规范注释
注释哲学:注释是"必要的恶"。优先选择重命名而非写注释
必须添加注释的情况:
- 解释意图(why),而非描述做了什么(what)
- ✅ "使用 Adam 优化器因为收敛更快"
- ❌ "遍历列表"(代码已自解释)
- 法律条款/许可声明
- 警告副作用(并发注意事项、全局状态修改、网络 I/O)
- 不透明的第三方库行为解释
- 临时方案标记(
# TODO:,# HACK:,# FIXME:)
Docstring 规范(公共函数/类必须):
def process_data(records: list[Record], batch_size: int = 32) -> list[Batch]:
"""将记录列表分批处理
对输入记录进行过滤、转换和分批,返回处理后的批次列表
Args:
records: 原始记录列表
batch_size: 每个批次的记录数,默认 32
Returns:
处理后的批次列表,每个批次包含最多 batch_size 条记录
Raises:
ValueError: 当 records 为空或 batch_size 小于 1 时
"""
类 Docstring:
class DataProcessor:
"""高效处理并分批输入记录
处理记录的过滤、转换和分批操作,设计为可子类化
以支持自定义处理管道
Attributes:
batch_size: 每批次记录数(默认 32)
shuffle: 每个 epoch 是否打乱数据集
num_workers: 数据加载的并行工作线程数
Example:
>>> processor = DataProcessor(batch_size=64, shuffle=True)
>>> for batch in processor:
... print(len(batch))
"""
行内注释规范:
- 放在代码上方(非右侧),复杂逻辑前留空行
- 以大写开头,句号结尾,完整句子
- 与代码保持相同缩进级别
#后跟一个空格
禁止:
- 冗余注释(递增 i:"i += 1")
- 过时的注释(代码已改但注释未更新)
- 注释掉的代码块(应 git 历史追踪,不用注释保留)
C. 代码清理
- 移除未使用的 import 和变量
- 合并重复功能
- 标记过时的依赖
D. 冗余代码清理(新增)
深入分析并优化:
- Dead Code Detection - 检测死代码
- 从未调用的函数/类
- 条件分支中永远不会执行的代码路径
- 被注释掉的遗留代码块
- 残余目录清理 - 删除重构后留下的空目录和旧文件:
- 识别并删除空目录:原算法目录(重构迁移后遗留的空子目录应在清理阶段移除)
- 移动或移除原始输入数据:如测试样本、演示文件等,根据项目原则放入 data/ 目录或删除
- 清理
.idea/,__pycache__/:确保所有 IDE 缓存、Python 字节码被排除在版本控制外 - 确认无重复文件:避免新旧代码在同一目录下共存
- Duplicate Logic Removal - 消除重复逻辑
- 识别相似功能模块(如多个文件中的日志初始化)
- 提取为公共工具函数放入
utils/
- Legacy Code Marking - 标记过时依赖
- Python 2 兼容代码
- 已废弃的 API 调用
- 过时的第三方库版本
E. 配置参数化(深度重构及以上策略)
- 轻量/标准策略:不执行配置参数化。如果硬编码值不超过 3 个,保持 inline 即可
- 深度重构及以上策略或参数 >3 时:执行以下操作:
- Magic Number Extraction - 魔法数字提取
# 改进前(参数超过 2-3 个)
api_client = create_client(host="api.example.com", port=8080, timeout=30)
# 改进后 - 通过配置文件
config = load_config("configs/default.yaml")
api_client = create_client(config.api.host, config.api.port, config.api.timeout_seconds)
- YAML Configuration Structure - 标准配置格式
- Command Line Override - 命令行参数优先(仅适用于 CLI/工具脚本)
F. 单元测试补充(深度重构及以上策略)
- 轻量/标准策略:不强制编写单元测试。原型代码、一次性实验脚本不需要测试覆盖。如果确实有核心逻辑需要验证,只写最简单的 assert 检查即可
- 深度重构及以上策略:为核心逻辑添加测试用例
- Critical Path Coverage - 关键路径测试
- I/O 操作(文件读写、网络请求)
- 核心业务逻辑/算法处理
- 数据验证与转换流程
- Test Structure - 推荐测试结构
- Test Framework Selection - 推荐框架(pytest 优先)
- Minimum Test Coverage - 最低覆盖率要求 - 0%
Phase 3: 进度持久化与验证
每个子代理完成后必须写入进度文件
// memory/organize-progress.json (由主会话创建和维护)
{
"project": "E:\\LPR",
"started_at": "2026-04-28T00:00:00+08:00",
"phases": {
"create-structure": {"status": "completed", "files_created": [".gitignore"]},
"move-files-phase1": {"status": "in_progress"},
...
},
"resumable": true,
"last_checkpoint": "2026-04-28T00:05:00+08:00"
}
主会话在启动时检查进度:
- 如果存在
memory/organize-progress.json且包含未完成阶段 - 跳过已完成阶段,继续执行剩余任务 - 如果文件不存在或项目未开始 - 从头开始
Phase 3.5: 代码质量与设计规范检查(全面重构策略)
核心原则:仅在用户选择全面重构策略时执行深度代码质量检查
A. 函数设计规范
- 长度 - 理想 4-10 行,不超过两三层缩进;超过则拆分子函数
- 参数数量 - 1-2 个最佳,>5 应使用配置对象/数据类封装
- 布尔参数是代码气味 - 一个布尔参数暗示函数做了两件不同的事,应拆分为两个独立函数(DoS 原则)
- 命令 - 查询分离 (CQS) - 函数要么执行动作(Command),要么返回信息(Query),不能两者兼顾
B. OOP SOLID 六大原则
对每个类用以下自检问题检验:
- SRP (Single Responsibility) - 能否用 25 字以内描述其职责而不含 "if/and/or/but"?
- OCP (Open-Closed) - 能否扩展行为而无需修改源码(开闭原则)?
- LSP (Liskov Substitution) - 子类对象能否替换父类对象而不改变程序正确性?
- ISP (Interface Segregation) - 接口是否足够小,消费者不依赖他们不使用的方法?
- DIP (Dependency Inversion) - 高层模块是否依赖抽象而非具体实现?
C. 错误处理规范
- 异常优先于返回码 - 使用 try/except 替代检查特殊返回值
- 禁止返回或传递 None 表示"无" - Python 中应返回空列表
[]、空字典{}等;仅在语义上确实可能缺失时才用 Optional[Type] - 封装第三方 API - 将外部库调用包装在内部接口后,使代码可测试和 mock
D. 注释哲学
注释是"必要的恶"。优先选择重命名而非写注释。仅以下情况应添加注释:
- 解释意图(why),而非描述做了什么(what) - ✅ "使用 Adam 优化器因为收敛快";❌ "遍历列表"
- 法律条款 / 许可声明
- 警告可能的后果(如副作用、并发注意事项)
- 对第三方/外部库行为的不透明之处做解释
E. Google-style Docstring 模板
公共函数/方法必须添加,遵循以下格式:
def fetch_user(user_id: int, include_deleted: bool = False) -> User | None:
"""Fetch a user by ID with optional deleted flag."""
...
class DataProcessor:
"""Efficiently processes and batches input records.
This class handles filtering, transformation, and batching of data.
It is designed to be subclassed for custom processing pipelines.
Attributes:
batch_size: Number of records per batch (default: 32).
shuffle: Whether to shuffle the dataset every epoch.
num_workers: Number of parallel workers for data loading.
Example:
>>> processor = DataProcessor(batch_size=64, shuffle=True)
>>> for batch in processor:
... print(len(batch))
"""
F. 导入组织规则(Import Organization)
- 优先使用绝对导入 - 避免相对导入,因为模块移动时不会自动更新
- 标准库 - 第三方库 - 本地代码(三段式 + 空行分隔)
- 每组内部按字母顺序排列
- 从每个 import 组内做具体导入(如
from .models.resnet import ResNet50),而非import models.resnet
文档生成规范
所有 4 级策略均生成三份文档(README.md、MODIFICATIONS.md、NOTE.md),区别在于详尽程度
| 策略级别 | README.md | CHANGELOG.md | NOTE.md | | ------------ | ------------------------------------------- | ---------------------------------- | ------------------------------------ | | 轻量清理 | 1-2 句话的项目说明 | 仅列出修改的文件 | 1-2 句话的项目用途 | | 标准整理 | 标准模板(Features + Quick Start) | 列出修改类别和关键变更 | 标准模板(用途 + 快速开始 + 技术栈) | | 深度重构 | 完整模板(Features + 结构 + 配置 + 许可证) | 详细变更记录 + 验证清单 | 完整模板(含常用配置表) | | 全面重构 | 完整模板 + 架构图/流程图 | 详细记录 + 常见问题排查 + 验证清单 | 完整模板 + 注意事项 |
README.md - 用户面向文档
- 轻量清理 - 1-2 句话说明项目用途即可
- 标准整理 - 标准模板,包含 Features + Quick Start
- 深度重构 - 完整模板,包含 Features、Project Structure、Quick Start、Configuration、License
- 全面重构 - 完整模板,可额外包含架构图或流程图
# [项目名称]
[简短的项目描述 - 一句话概括项目目的]
## Features
- [功能 1]
- [功能 2]
- ...
## Project Structure
[新的目录结构树]
## Quick Start
```bash
pip install -r requirements.txt
python main.py --config configs/default.yaml
Configuration
[配置文件说明]
License
[许可证信息,如已知]
**要求**:简洁明了,面向最终用户或使用者
---
### CHANGELOG.md - 修改记录
- **轻量清理** - 仅列出修改的文件
- **标准整理** - 列出修改类别和关键变更
- **深度重构** - 详细变更记录 + 验证清单
- **全面重构** - 详细记录 + 常见问题排查 + 验证清单
```markdown
# Modifications Log
## Directory Restructuring
- Moved `model.py` to `models/definition.py`
- Created `utils/helpers.py` from scattered functions
- ...
## Code Style Changes
- Renamed variable `raw_data` to `parsed_records` (semantic naming)
- Added type annotations to [N] functions
- Reorganized imports in [N] files
- ...
## Cleanup
- Removed unused import: `os.path.join` (replaced by `pathlib`)
- Consolidated duplicate validation logic into `utils/validators.py`
- ...
## Comment Updates
- Added docstrings to [N] functions
- Standardized comment format across all files
## Troubleshooting Notes(常见问题排查)
### 问题 1: [错误描述]
**原因**: [根本原因分析]
**解决**: [解决方案步骤]
---
验证清单:
- [x] 所有 import 路径已更新
- [x] 类型提示已添加
要求:具体、可追溯,列出实际变更项。轻量策略可简化为文件列表
NOTE.md - 个人笔记(中文)
- 轻量清理 - 1-2 句话说明项目用途
- 标准整理 - 标准模板(用途 + 快速开始 + 技术栈)
- 深度重构 - 完整模板(含常用配置表)
- 全面重构 - 完整模板 + 注意事项
# [项目名称] 笔记
## 项目用途
[用一两句中文概括这个项目是做什么的、解决什么问题]
## 快速开始
```bash
# 安装依赖
pip install -r requirements.txt
# 基本使用示例
python main.py [options]
常用配置(按需调整)
| 配置项 | 说明 | | -------- | ------------------------------ | | [配置 A] | [默认值/建议范围] - [简要用途] | | [配置 B] | [默认值/建议范围] - [简要用途] |
技术栈
- [技术栈描述,如 Python + Flask / Node.js / etc.]
**要求**:保持精简(不超过一页),中文撰写,只包含核心使用信息。不要包含**修改记录、常见问题排查、代码改进说明等内容**
---
### ⚠️ 三文件不重叠原则
| 文件 | 侧重 |
|------|--------|
| README.md | **是什么 + 怎么用** - 面向外部用户 |
| CHANGELOG.md | **改了什么** - 变更历史记录 |
| NOTE.md | **项目概况** - 个人快速参考 |
避免内容重复:README 不记录修改细节,MODIFICATIONS 不解释功能用途,NOTE 不做详细技术文档
---
## 安全注意事项
1. **始终先分析再行动** - 不要擅自修改任何文件
2. **保留原始备份意识** - 如果用户要求,可建议创建 git 快照
3. **不做破坏性操作** - 不删除未确认的文件或代码
4. **尊重项目现有结构** - 除非有明显改进空间
---
## PyTorch / 深度学习项目特殊处理
针对深度学习项目的额外考虑(如适用):
- **模型文件**:`models/` 目录下按架构分类(如 `models/resnet.py`, `models/custom_net.py`)
- **数据**:`data/` 或 `datasets/`,区分预处理和原始数据路径
- **实验管理**:建立 `experiments/` 目录存放训练脚本、checkpoint、日志
- **配置优先**:将超参数(batch_size, lr, epochs 等)提取到 `configs/` YAML 文件
- **日志输出**:确保有统一的 logging 机制(建议用 Python stdlib `logging` 或 `loguru`)
## Web / API 应用特殊处理
针对 Web/API 项目的额外考虑:
- **路由组织** - FastAPI/Flask 按资源划分路由(`routes/users.py`, `routes/orders.py`)
- **中间件与鉴权** - 认证逻辑独立为 middleware 或 service
- **数据库迁移** - Alembic 或类似工具管理 schema 变更
## CLI / 数据处理项目特殊处理
针对命令行工具和 ETL 管道的额外考虑:
- **配置集中** - 配置文件 + argparse / Typer,确保参数可追溯
- **日志与进度** - rich / click 的进度条支持,便于长时运行的管道监控
---
## Python 项目结构规范(补充)
### A. __init__.py 作为公共 API 边界(深度重构及以上策略)
- **轻量/标准策略 / Flat Layout** - 通常不需要 `__init__.py`,也不需要 `__all__`
- **深度重构及以上且使用 src layout** -
- `__init__.py` 不应包含业务逻辑,仅用于重新导出子模块的公开接口
- 使用 `__all__` **显式声明**公共 API - 不在列表中的 symbol 视为私有
```python
# __init__.py
from .user_service import UserService
from .auth import AuthProvider
__all__ = ["UserService", "AuthProvider"]
- 消费者应
import package然后使用公开符号,而非直接import package.inner_module
B. src/ vs Flat Layout - 决策框架
| 特征 | src/ layout(推荐) | Flat layout |
| ------------ | ------------------------------------------------- | ---------------------------------------- |
| 适用场景 | 库、可发布项目、测试需要模拟包导入 | 简单脚本、一次性分发/Notebook |
| 优点 | 防止误用未安装包运行;pip install -e . 行为一致 | 结构简单,路径简单 |
| 缺点 | 多一层目录嵌套 | 开发时可能无意中导入本地模块而非安装的包 |
- 深度重构及以上策略 - 建议使用
src/layout:src/package_name/+tests/ - 轻量/标准策略 / Flat Layout - 保持扁平结构即可(如
main.py,utils.py,config.yaml) - 现有 flat 项目无需强制迁移,除非有明确的包隔离需求
C. Layered Architecture - 分层架构(全面重构策略)
- 轻量/标准/深度重构策略 - 不要强行拆分多层。保持现有结构或轻度重组即可
- 全面重构策略且涉及多模块交互时,按技术栈分层(从高层到低层),依赖只能单向向下:
api/ # FastAPI/Flask 路由、请求/响应模型
services/ # 业务逻辑入口点,调用 repositories
repositories/ # 数据访问层,与数据库/外部 API 交互
models/ # Pydantic 模型 / SQLAlchemy ORM
schemas/ # DTOs, input validation schemas
config/ # 配置加载、环境管理
- 每层只能
import下层模块,禁止跨层或反向导入 - 通过依赖注入(构造函数参数)而非全局实例来耦合层间关系
D. Domain-Driven Organization(DDD 风格,全面重构策略)
当项目复杂度较高且用户选择全面重构策略时,按业务域划分而非技术层:
users/ # 用户域
├── models.py # 领域模型
├── services.py # 领域服务
└── api.py # API 端点
orders/ # 订单域
...
shared/ # 跨域的公共基础设施(日志、缓存等)
- DDD 结构适用于团队多人协作的大型项目
- 轻量/标准/深度重构策略仍推荐传统的 layered architecture,避免过度工程化
E. 模块粒度 - "一个概念一个文件"(深度重构及以上策略)
- 拆分阈值:单个文件超过 300-500 行或处理多个不相关职责时应拆分为独立文件
- 文件命名:
snake_case、描述性强(如user_repository.py,而非repo.py) - 类名与文件名匹配:
UserService应放入user_service.py
F. 测试组织 - Co-located vs Parallel(深度重构及以上策略)
-
轻量/标准策略 - 不写单元测试
-
深度重构及以上策略
- 两种策略任选其一并在整个项目中保持一致:
| 策略 | 结构 | 适用场景 | | ---------------------- | ------------------------------------- | --------------------------------- | | Co-located(推荐) |
tests/test_<module>.py与源码同目录 | 小型项目、测试逻辑与实现紧密相关 | | Parallel directory |tests/镜像src/目录结构 | 大型项目、CI 需要独立运行所有测试 |
G. pyproject.toml - 工具链配置(全面重构策略,或发布为库时)
- 轻量/标准/深度重构策略 - 不需要。脚本直接运行即可
- 全面重构策略 / 需要发布到 PyPI 的项目:在根目录创建
pyproject.toml
[tool.ruff]
line-length = 120
target-version = "py311"
[tool.ruff.lint]
select = ["E", "W", "F", "I", "B", "UP", "SIM"]
# E/W: pycodestyle, F: Pyflask, I: isort, B: bugbear, UP: pyupgrade, SIM: simplify
[tool.ruff.lint.per-file-ignores]
"tests/**/*" = ["S101"] # allow assert in tests
"__init__.py" = ["F401"] # unused imports are re-exports by convention
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false # production code: true; tests: override to false
⚠️ 避免过度工程化 - 具体禁令
以下行为不应默认执行,仅在用户明确选择对应策略级别或明确提出需求时才执行:
- 不要为只有几个变量的脚本创建 YAML/TOML 配置文件 + argparse CLI - inline 参数更简单(除非用户选择深度重构及以上策略)
- 不要将简单的函数拆分成多个子函数以符合 4-10 行规则 - 保持逻辑完整性优先于行数限制(除非用户选择全面重构策略)
- 不要在扁平布局的项目中强制创建
__init__.py+__all__- 除非用户选择深度重构及以上策略 - 不要对只有一个类的文件做 SRP/OCP/LSP/ISP/DIP 分析 - OOP 原则只在存在继承和多态关系时才适用(除非用户选择全面重构策略)
- 不要为只有几个文件的深度学习/数据处理项目创建完整的分层架构或 DDD 结构 - 除非用户选择全面重构策略
- 不要在原型代码中强制要求单元测试和覆盖率阈值 - 除非用户选择深度重构及以上策略
- 不要对只有一两个使用者的内部工具生成 README + MODIFICATIONS + NOTE 三份文档 - 除非用户选择对应策略级别
- 不要将
main.py强行塞进src/package_name/的目录结构中 - src layout 只对库或大型应用有意义(除非用户选择深度重构及以上策略)
核心原则:优化是为了让人更容易理解和维护代码,不是为了达到最佳实践。如果改动让项目变得更复杂而不是更简单,那就做过头了。用户的策略选择是最终决定
Scan to join WeChat group