返回 Skill 列表
extension
分类: 其它无需 API Key

Code Organizer

代码整理与项目重构技能。当用户要求"帮我整理一下这个项目让代码结构更清晰"、"统一命名规范"或类似请求时,请主动使用此技能对 Python 项目进行系统性整理和重构(默认通用 Python 风格,根据具体项目类型如深度学习/Web/API/CLI 自动调整)。包括:目录结构重组、代码格式规范、命名规范、import 排序、类型标注、规范注释、OOP SOLID 原则检查、函数设计规范、错误处理规范、Google-style docstring、导入组织规则、分层架构/DDD 结构设计、init.py 公共 API、冗余代码清理、配置参数化、单元测试补充,以及生成项目文档。

person作者: user_8f9cac4ahubcommunity

Code Organizer - 代码整理与项目重构技能

概述

本技能用于对 Python 项目进行系统性整理和重构(默认通用风格,根据具体项目类型自动适配)重要原则:始终先生成整理建议,等待用户批准后再执行任何文件修改

⚠️ 避免过度工程化 - 核心约束

整理/重构到最佳实践。所有优化措施均由用户主动选择,绝不默认执行

🔄 两轮确认流程(必须严格执行)

每次执行整理任务前,必须经过两轮用户确认,不可跳过:

第一轮:策略选择

  1. 扫描项目,评估规模(文件数、模块数、项目类型)

  2. 根据评估结果,向用户展示

    可选策略列表

    并给出推荐:

    | 策略级别 | 适用场景 | 包含的整理措施 | | ------------ | ------------------------------------- | ------------------------------------------------------------ | | 轻量清理 | 单脚本、实验性代码、临时项目 | 无用代码清理、空目录删除、明显命名问题修复 + 简要文档 | | 标准整理 | 小型工具、数据处理管道、原型项目 | 轻量清理 + 命名规范 + import 排序 + 代码格式 + 类型标注 + 规范注释 + 标准文档 | | 深度重构 | 可发布的小库、API 服务、完整 pipeline | 标准整理 + 目录结构重组 + src layout + init.py + 配置参数化 + 测试覆盖 + 分层架构 + 详细文档 | | 全面重构 | 团队项目、商业产品级应用 | 深度重构 + DDD 设计 + 完整测试套件 + pyproject.toml + 完整文档 + 代码质量检查 |

  3. 向用户说明推荐级别及理由,等待用户确认或调整策略级别

第二轮:方案确认

  1. 基于用户选择的策略级别,生成详细的整理方案,包括:
  • 具体的目录结构调整(如涉及)
  • 每个需要修改的文件及修改类型
  • 预计可移除的无用代码/依赖
  • 新增的文件或配置
  1. 等待用户明确确认后方可开始执行

判断原则:

  • 对于深度学习实验/数据处理原型项目:如果核心是跑通流程而非工程化,优先推荐轻量或标准策略
  • 用户的策略选择是最终决定,推荐仅供参考
  • 任何超出用户选择策略范围的优化,都不执行

工作流程

⚠️ 重要:防中断架构设计

核心原则:使用并行子代理拆分任务,避免单会话超时导致的中断 对于复杂项目重构(超过个文件需要修改),必须采用以下模式:

# 错误做法:串行执行所有操作
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: 扫描与策略选择(第一轮确认)

由主会话执行,轻量级操作

  1. 扫描项目 - 了解当前目录结构、代码规模、模块依赖关系
  • 使用 execbackground=true 模式进行耗时操作(如 robocopy, tree)
 # 推荐:后台执行长时间任务
 cmd /c "robocopy E:\\LPR E:\\LPR_backup /MIR" > backup.log 2>&1 &
  1. 评估项目概况 - 统计以下信息:
  • 文件数量、模块数量、项目类型(深度学习/Web/API/CLI/数据处理等)
  • 当前存在的问题(目录混乱、命名不一致、代码重复、注释缺失等)
  1. 提出策略选择(第一轮确认) - 向用户展示:
  • 项目概况摘要
  • 四个策略级别及其包含的整理措施(见上方策略表)
  • 推荐策略及理由
  • 等待用户确认或调整策略级别

Phase 1.5: 方案制定(第二轮确认)

基于用户选择的策略级别,生成详细整理方案。

  1. 列出具体变更
  • 目录结构调整详情(如涉及)
  • 每个需要修改的文件及修改类型
  • 预计可移除的无用代码/依赖
  • 新增的文件或配置
  • 代码风格统一的具体规范
  1. 等待用户明确确认后方可进入执行阶段

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.pyuser_service/
  • 类名PascalCaseDataLoaderUserService
  • 函数/方法snake_case,动词开头(fetch_user()validate_input()
  • 变量snake_case,语义化命名(user_list 而非 ulparsed_records 而非 data
  • 常量UPPER_SNAKE_CASEMAX_RETRIES = 3API_BASE_URL
  • 私有成员:前导下划线(_internal_cache__private_method
  • 布尔变量is_/has_/can_/should_ 前缀(is_validhas_permission
  • 避免:单字母变量(除 i/j/k 循环索引和数学公式外)、缩写(usruser
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] 而非 listdict[str, int] 而非 dict
  • 可选类型:使用 X | None(Python 3.10+)或 Optional[X]
  • 联合类型:使用 A | B(Python 3.10+)或 Union[A, B]
  • 复杂返回:使用 typing.TypeAlias 定义类型别名
  • 不强求:内部工具函数、一次性脚本、lambda 表达式可省略
B5. 规范注释

注释哲学:注释是"必要的恶"。优先选择重命名而非写注释

必须添加注释的情况

  1. 解释意图(why),而非描述做了什么(what)
  • ✅ "使用 Adam 优化器因为收敛更快"
  • ❌ "遍历列表"(代码已自解释)
  1. 法律条款/许可声明
  2. 警告副作用(并发注意事项、全局状态修改、网络 I/O)
  3. 不透明的第三方库行为解释
  4. 临时方案标记# 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. 冗余代码清理(新增)

深入分析并优化:

  1. Dead Code Detection - 检测死代码
  • 从未调用的函数/类
  • 条件分支中永远不会执行的代码路径
  • 被注释掉的遗留代码块
  1. 残余目录清理 - 删除重构后留下的空目录和旧文件:
  • 识别并删除空目录:原算法目录(重构迁移后遗留的空子目录应在清理阶段移除)
  • 移动或移除原始输入数据:如测试样本、演示文件等,根据项目原则放入 data/ 目录或删除
  • 清理 .idea/, __pycache__/:确保所有 IDE 缓存、Python 字节码被排除在版本控制外
  • 确认无重复文件:避免新旧代码在同一目录下共存
  1. Duplicate Logic Removal - 消除重复逻辑
  • 识别相似功能模块(如多个文件中的日志初始化)
  • 提取为公共工具函数放入 utils/
  1. Legacy Code Marking - 标记过时依赖
  • Python 2 兼容代码
  • 已废弃的 API 调用
  • 过时的第三方库版本

E. 配置参数化(深度重构及以上策略)

  • 轻量/标准策略:不执行配置参数化。如果硬编码值不超过 3 个,保持 inline 即可
  • 深度重构及以上策略或参数 >3 时:执行以下操作:
  1. 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)
  1. YAML Configuration Structure - 标准配置格式
  2. Command Line Override - 命令行参数优先(仅适用于 CLI/工具脚本)

F. 单元测试补充(深度重构及以上策略)

  • 轻量/标准策略:不强制编写单元测试。原型代码、一次性实验脚本不需要测试覆盖。如果确实有核心逻辑需要验证,只写最简单的 assert 检查即可
  • 深度重构及以上策略:为核心逻辑添加测试用例
  1. Critical Path Coverage - 关键路径测试
  • I/O 操作(文件读写、网络请求)
  • 核心业务逻辑/算法处理
  • 数据验证与转换流程
  1. Test Structure - 推荐测试结构
  2. Test Framework Selection - 推荐框架(pytest 优先)
  3. 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"
}

主会话在启动时检查进度

  1. 如果存在 memory/organize-progress.json 且包含未完成阶段 - 跳过已完成阶段,继续执行剩余任务
  2. 如果文件不存在或项目未开始 - 从头开始

Phase 3.5: 代码质量与设计规范检查(全面重构策略)

核心原则:仅在用户选择全面重构策略时执行深度代码质量检查

A. 函数设计规范

  • 长度 - 理想 4-10 行,不超过两三层缩进;超过则拆分子函数
  • 参数数量 - 1-2 个最佳,>5 应使用配置对象/数据类封装
  • 布尔参数是代码气味 - 一个布尔参数暗示函数做了两件不同的事,应拆分为两个独立函数(DoS 原则)
  • 命令 - 查询分离 (CQS) - 函数要么执行动作(Command),要么返回信息(Query),不能两者兼顾

B. OOP SOLID 六大原则

对每个类用以下自检问题检验:

  1. SRP (Single Responsibility) - 能否用 25 字以内描述其职责而不含 "if/and/or/but"?
  2. OCP (Open-Closed) - 能否扩展行为而无需修改源码(开闭原则)?
  3. LSP (Liskov Substitution) - 子类对象能否替换父类对象而不改变程序正确性?
  4. ISP (Interface Segregation) - 接口是否足够小,消费者不依赖他们不使用的方法?
  5. DIP (Dependency Inversion) - 高层模块是否依赖抽象而非具体实现?

C. 错误处理规范

  • 异常优先于返回码 - 使用 try/except 替代检查特殊返回值
  • 禁止返回或传递 None 表示"无" - Python 中应返回空列表 []、空字典 {} 等;仅在语义上确实可能缺失时才用 Optional[Type]
  • 封装第三方 API - 将外部库调用包装在内部接口后,使代码可测试和 mock

D. 注释哲学

注释是"必要的恶"。优先选择重命名而非写注释。仅以下情况应添加注释:

  1. 解释意图(why),而非描述做了什么(what) - ✅ "使用 Adam 优化器因为收敛快";❌ "遍历列表"
  2. 法律条款 / 许可声明
  3. 警告可能的后果(如副作用、并发注意事项)
  4. 对第三方/外部库行为的不透明之处做解释

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)

  1. 优先使用绝对导入 - 避免相对导入,因为模块移动时不会自动更新
  2. 标准库 - 第三方库 - 本地代码(三段式 + 空行分隔)
  3. 每组内部按字母顺序排列
  4. 从每个 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

⚠️ 避免过度工程化 - 具体禁令

以下行为不应默认执行,仅在用户明确选择对应策略级别或明确提出需求时才执行:

  1. 不要为只有几个变量的脚本创建 YAML/TOML 配置文件 + argparse CLI - inline 参数更简单(除非用户选择深度重构及以上策略)
  2. 不要将简单的函数拆分成多个子函数以符合 4-10 行规则 - 保持逻辑完整性优先于行数限制(除非用户选择全面重构策略)
  3. 不要在扁平布局的项目中强制创建 __init__.py + __all__ - 除非用户选择深度重构及以上策略
  4. 不要对只有一个类的文件做 SRP/OCP/LSP/ISP/DIP 分析 - OOP 原则只在存在继承和多态关系时才适用(除非用户选择全面重构策略)
  5. 不要为只有几个文件的深度学习/数据处理项目创建完整的分层架构或 DDD 结构 - 除非用户选择全面重构策略
  6. 不要在原型代码中强制要求单元测试和覆盖率阈值 - 除非用户选择深度重构及以上策略
  7. 不要对只有一两个使用者的内部工具生成 README + MODIFICATIONS + NOTE 三份文档 - 除非用户选择对应策略级别
  8. 不要将 main.py 强行塞进 src/package_name/ 的目录结构中 - src layout 只对库或大型应用有意义(除非用户选择深度重构及以上策略)

核心原则:优化是为了让人更容易理解和维护代码,不是为了达到最佳实践。如果改动让项目变得更复杂而不是更简单,那就做过头了。用户的策略选择是最终决定