skills/organizing-by-usage/SKILL.md
当用户规划项目结构、重构模块目录、判断文件是否应合并或拆分、评估抽象是否过度设计、质疑类名是否贴切命名、希望按"谁在用它"(使用关系)而不是按技术文件类型来组织代码时使用。
npx skillsauth add cruldra/skills organizing-by-usageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
核心洞察:文件应该和它的使用方聚在一起。
两层决策原则,都是同一个洞察的体现:
第二层比第一层更容易出错,也更需要判断工具。本 skill 的大部分篇幅是第二层。
src/
├── core/ # 跨子系统共享内核(配置、DB、日志、鉴权、事件总线)
├── customers/ # 客户子系统
│ ├── models.py
│ ├── schemas.py
│ ├── repositories.py
│ ├── services.py
│ ├── routes.py
│ └── tasks.py
├── courses/ # 课程子系统
└── allocation/ # 分配引擎子系统
不要把 models/、services/、repositories/、routes/、tasks/ 这类目录铺在项目根下。它的后果:一个功能散在 5-7 个目录里、修改一个需求要跨层跳、新成员看不到业务边界。
只有同时满足以下几条才构成独立子系统:
不是子系统划分依据:
子系统内部文件越加越多,开始出现这种文件:
xxx_middleware.py、xxx_factory.py、xxx_manager.py、xxx_translator.pyutils.py、helpers.py、common.py如果这些文件实际上只被一个文件 import,它们是"孤儿辅助文件",是组织方式失败的信号。
遇到一个"可疑文件" A,决定它该独立存在还是合进别处:
Q1. A 在生产代码里有几个运行时使用者?
Q2. 合进去会造成循环依赖吗?
Q3. 合并后的新文件能用一句话说清职责吗?
| 原状 | Q1 使用者 | Q2 循环 | 决策 |
|------|----------|--------|------|
| exec_ssc_tool_factory.py(构造 exec_ssc 工具) | 1 个:agent.py | — | 合进 agent.py |
| sse_translator.py(LangGraph 事件 → SSE 翻译) | 1 个:services.py | — | 合进 services.py |
| token_manager.py(JWT 管理) | 2 个:agent.py(SessionExpired)+ services.py(实例化) | 合进 services.py 会循环(services 已依赖 agent) | 合进更基础的 agent.py |
| tools/exec_ssc.py + tools/ui_events.py + tools/__init__.py | 都只被 agent.py 用 | — | 拍平为单文件 tools.py |
原则:models.py 只存真正的数据库表定义(SQLAlchemy / Django ORM)。Pydantic BaseModel 无论它是:
都应该放 schemas.py,而不是 models.py。
判断:这个类会不会被 Alembic / Django migration 用来生成 DDL?
models.pyschemas.py子系统内部,优先用单文件,只在真的装不下时才拆目录。
拆目录的触发条件:
如果你只是因为"文件看起来有点长"就拆 tools/、utils/、helpers/,大概率是在制造前面说的"孤儿辅助文件"。
类名借用了框架/模式术语,但代码里实际没遵循那个范式:
| 反模式 | 说明 |
|--------|------|
| XxxMiddleware 但没继承任何 Middleware 基类,也没实现中间件钩子 | 只是借了"中间层"的语义 |
| XxxFactory 但只有一个 make_xxx() 方法,还常驻一堆状态 | 其实是普通对象 |
| XxxService 但全是静态方法 | 应该是模块级函数 |
| XxxManager 但只有 get/set 两个方法 | 应该是简单封装或直接用原始类型 |
ExecSscMiddleware(没继承 AgentMiddleware)→ ExecSscToolFactory(它确实在构造工具)UserService(全是静态方法)→ user_repository 或直接用模块级函数当你犹豫"是否要加一层抽象"时,问三个问题:
这个抽象提供的钩子 / 方法,在当前代码里实际用上了几个?
这个类存在的唯一原因是"测试方便"吗?
这个基类是为"未来可能扩展"准备的吗?
| 场景 | 不该用 | 应该用 |
|------|--------|--------|
| 请求级数据注入到单例工具 | AgentMiddleware(只为了一个工具) | ContextVar + 闭包 |
| 应用启动时装配一次 | Factory 类 | 直接 inline 到启动代码 |
| 同样的逻辑两个入口(生产 + 测试) | 继承 + 多层抽象 | 一个类暴露两个方法 |
出现下列任一症状时,先停下手,怀疑组织方式有问题:
*_manager.py / *_factory.py / *_translator.py 这类)models/、services/、routes/ 等技术类型目录customers/services/ 下又有 services.py)models.py(除非它同时是 SQLAlchemy 模型)做完结构设计或重构后,自检:
models.py 里只有真正的 ORM 表定义当用户让你组织代码或重构时,按此优先级动作:
先问自己"这是第一层还是第二层问题"
用三问法判断合并/拆分,不要凭"名字看起来像不像"
命名反映实际角色。如果名字借用了基类术语但代码里没继承 / 没实现那个范式,主动建议改名
默认选轻量方案。抽象不够用时再升级,不要先上重抽象
怀疑"孤儿辅助文件"。只被一处用的文件,合进使用方
Pydantic BaseModel 默认进 schemas.py,除非它是 SQLAlchemy 模型
不要默认生成 models/ services/ routes/ 这类根级目录,除非用户明确要求保留旧结构
testing
智能体 UAT 验收测试技能。用于验证智能体在真实场景下的表现是否满足预期。支持任意智能体框架(langchain、langgraph、deepagents、crewai 等)。触发词:测试智能体、验收测试、agent test、UAT
tools
Use when you need to create a Gitea issue, update its spec/plan markers, read or merge an issue's state JSON, or post a PR review comment in a repo that uses the spx CLI (superpowers-vscode workflow).
development
Use when implementing, modifying, refactoring, or reviewing code and the agent must follow explicit coding standards for simplicity, readability, maintainability, testability, project conventions, and minimal safe changes.
development
Use when integrating the deepagents SDK into a Python project — creating agents, configuring backends, adding subagents, middleware, memory, or skills. Also use when debugging deepagents agents or choosing between StateBackend, FilesystemBackend, and LocalShellBackend.