dashboard-nanobot/design/code-structure-standards.md

326 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Dashboard Nanobot 代码结构规范(强制执行)
本文档定义后续前端、后端、`dashboard-edge` 的结构边界与拆分规则。
目标不是“尽可能多拆文件”,而是:
- 保持装配层足够薄
- 保持业务边界清晰
- 避免再次出现单文件多职责膨胀
- 让后续迭代继续走低风险、小步验证路线
本文档自落地起作为**后续开发强制规范**执行。
---
## 1. 总原则
### 1.1 先分层,再分文件
- 优先先把“页面装配 / 业务编排 / 基础设施 / 纯视图”分开,再决定是否继续拆文件。
- 不允许为了“看起来模块化”而把强耦合逻辑拆成大量碎文件。
- 允许保留中等体量的“单主题控制器”文件,但不允许继续把多个主题堆进一个文件。
### 1.2 领域内聚优先于机械拆分
- 代码拆分的第一判断标准是“是否仍属于同一业务域”,不是“是否还能再拆小”。
- 同一业务域内的读、写、校验、少量编排、少量派生逻辑,可以保留在同一个模块中。
- 如果拆分只会制造多层跳转、隐藏真实依赖、降低可读性,则不应继续拆。
- 真正需要拆分的场景是跨域、跨层、跨边界,而不是单纯文件偏长。
### 1.3 低风险重构优先
- 结构重构优先做“搬运与收口”,不顺手修改业务行为。
- 同一轮改动里,默认**不要**同时做:
- 大规模结构调整
- 新功能
- 行为修复
- 如果确实需要行为修复,只允许修复拆分直接引入的问题。
### 1.4 装配层必须薄
- 页面层、路由层、应用启动层都只负责装配。
- 装配层可以做依赖注入、状态接线、事件转发。
- 装配层不允许承载复杂业务判断、持久化细节、长流程编排。
### 1.5 新文件必须按主题命名
- 文件名必须直接表达职责。
- 禁止模糊命名,例如:
- `helpers2.py`
- `misc.ts`
- `commonPage.tsx`
- `temp_service.py`
---
## 2. 前端结构规范
### 2.1 目录分层
前端统一按以下层次组织:
- `frontend/src/app`
- 应用壳、全局路由视图、全局初始化
- `frontend/src/modules/<domain>`
- 领域模块入口
- `frontend/src/modules/<domain>/components`
- 纯视图组件、弹层、区块组件
- `frontend/src/modules/<domain>/hooks`
- 领域内控制器 hook、状态编排 hook
- `frontend/src/modules/<domain>/api`
- 仅该领域使用的 API 请求封装
- `frontend/src/modules/<domain>/shared`
- 领域内共享的纯函数、常量、类型桥接
- `frontend/src/components`
- 跨模块通用 UI 组件
- `frontend/src/utils`
- 真正跨领域的通用工具
目录分层的目标是稳定边界,不是把每一段逻辑都拆成独立文件:
- 同一页面域内强关联的视图、状态、交互逻辑,允许在同一模块内靠近放置
- 只有当某段逻辑已经被多个页面或多个子流程稳定复用时,才提炼到更高层级
- 禁止为了“文件更短”而把一个连续可读的页面流程拆成大量来回跳转的小文件
### 2.2 页面文件职责
页面文件如:
- `frontend/src/modules/platform/PlatformDashboardPage.tsx`
- `frontend/src/modules/platform/NodeWorkspacePage.tsx`
- `frontend/src/modules/platform/NodeHomePage.tsx`
必须遵守:
- 只做页面装配
- 只组织已有区块、弹层、控制器 hook
- 不直接承载长段 API 请求、副作用、数据清洗逻辑
- 如果一个页面本身就是单一业务域,并且逻辑连续可读,可以保留适量页面内状态与事件处理
- 不要求为了行数把本来紧密耦合的页面逻辑强拆到多个 hooks / sections / shared 文件中
页面文件目标体量:
- 行数只作为预警,不作为硬性拆分依据
- 先判断页面是否仍然属于单一业务域、是否能顺序读懂、依赖是否清晰
- 只有在页面同时承担多个子域、多个弹层流程、多个数据源编排时,才优先拆出页面控制器 hook 或区块装配组件
### 2.3 控制器 hook 规范
控制器 hook 用于承载:
- 页面状态
- 副作用
- API 调用编排
- 事件处理
- 派生数据
典型命名:
- `useNodeHomePage`
- `useNodeWorkspacePage`
- `usePlatformDashboardPage`
规则:
- 一个 hook 只服务一个明确页面或一个明确子流程
- hook 不直接产出大量 JSX
- hook 内部允许组合更小的子 hook但不要为了拆分而拆分
- 如果页面逻辑并不复杂,不要求必须抽出“页面总 hook”
- 只有当副作用编排、状态联动、接口交互已经影响页面可读性时,才值得抽成控制器 hook
控制器 hook 目标体量:
- 行数只作为风险提示
- 优先保证 hook 的流程连续、命名清晰、状态收口明确
- 如果继续拆分只会让调用链更深、上下文更难追踪,则不应继续拆
- 只有当 hook 明显同时承载多个子流程时,才按主题拆成子 hook 或把稳定复用逻辑提到 `shared`/`api`
### 2.4 视图组件规范
组件分为两类:
- 区块组件:例如列表区、详情区、摘要卡片区
- 弹层组件:例如 Drawer、Modal、Sheet
规则:
- 视图组件默认不直接请求接口
- 视图组件只接收已经整理好的 props
- 纯视图组件内部不保留与页面强耦合的业务缓存
- 不要求把所有小片段都抽成组件;只在存在明确复用、明显视觉区块、或能显著降低页面噪音时再拆组件
### 2.5 前端复用原则
- 优先提炼“稳定复用的模式”,不要提炼“碰巧重复一次的代码”
- 三处以上重复,优先考虑抽取
- 同域复用优先放 `modules/<domain>/shared`
- 跨域复用优先放 `src/components``src/utils`
- 如果抽取后的接口比原地实现更难理解,就不应抽取
- 不允许创建只有单个页面使用、但又被过度包装的“伪复用层”
### 2.6 前端禁止事项
- 禁止把页面做成“一个文件管状态、接口、弹层、列表、详情、搜索、分页”
- 禁止把样式、业务逻辑、视图结构三者重新耦合回单文件
- 禁止创建无明确职责的超通用组件
- 禁止为减少行数而做不可读的过度抽象
- 禁止为了满足结构指标,把单一页面域强拆成大量细碎 hooks、sections、shared 文件
- 禁止新增纯转发、纯包装、无独立语义价值的组件或 hook
---
## 3. 后端结构规范
### 3.1 目录分层
后端统一按以下边界组织:
- `backend/main.py`
- 仅启动入口
- `backend/app_factory.py`
- 应用实例创建
- `backend/bootstrap`
- 依赖装配、应用初始化、生命周期拼装
- `backend/api`
- FastAPI 路由层
- `backend/services`
- 业务用例与领域服务
- `backend/core`
- 数据库、缓存、配置、基础设施适配
- `backend/models`
- ORM 模型
- `backend/schemas`
- 请求/响应 DTO
- `backend/providers`
- runtime/workspace/provision 适配层
### 3.2 启动与装配层规范
以下文件必须保持装配层属性:
- `backend/main.py`
- `backend/app_factory.py`
- `backend/bootstrap/app_runtime.py`
规则:
- 只做依赖创建、注入、路由注册、生命周期绑定
- 不写业务 SQL
- 不写领域规则判断
- 不写长流程编排
### 3.3 Router 规范
`backend/api/*.py` 只允许承担:
- HTTP 参数接收
- schema 校验
- 调用 service
- 把领域异常转换成 HTTP 异常
Router 不允许承担:
- 多步业务编排
- 大量数据聚合
- 数据库表间拼装
- 本地文件系统读写细节
### 3.4 Service 规范
Service 必须按业务域内聚组织,而不是为了压缩行数而机械切碎。
允许的 service 类型:
- `*_settings_service.py`
- `*_usage_service.py`
- `*_activity_service.py`
- `*_analytics_service.py`
- `*_overview_service.py`
- `*_query_service.py`
- `*_command_service.py`
- `*_lifecycle_service.py`
Service 文件规则:
- 一个文件只负责一个业务域或一个稳定子主题
- 同一文件内允许同时包含该域内的查询、写入、校验、少量派生逻辑
- 同一文件内允许有私有 helper但 helper 只能服务当前域
- 只有当一个文件已经明显跨域,或者把 router/core/provider 的职责卷入进来时,才必须继续拆分
- 不允许为了“看起来更模块化”而创建纯转发、纯 re-export、纯别名性质的 service 层
Service 体量规则:
- 行数只作为预警信号,不作为机械拆分依据
- 优先判断是否仍然保持单一业务域、可顺序阅读、依赖方向清晰
- 如果一个文件虽然较大,但域边界稳定、跳转成本低、上下文连续,可以保留
- 如果一个文件即使不大,但已经跨域、跨层、混入无关职责,也必须拆分
### 3.6 Schema 规范
- `schemas` 只定义 DTO
- 不允许在 schema 中直接读数据库、读文件、发网络请求
- schema 字段演进必须保持前后端契约可追踪
### 3.7 Core 规范
`core` 只允许放:
- 数据库与 Session 管理
- 缓存
- 配置
- 基础设施适配器
不允许把领域业务塞回 `core` 来“躲避 service 变大”。
### 3.8 Provider 规范
`providers` 只处理运行时/工作区/部署目标差异。
不允许把平台业务逻辑塞进 provider。
---
## 4. 本项目后续开发的执行规则
### 4.1 每轮改动的默认顺序
1. 先审计职责边界
2. 先做装配层变薄
3. 再提炼稳定复用块
4. 最后再考虑继续细拆
### 4.2 校验规则
- 前端结构改动后,默认执行 `frontend` 构建校验
- 后端结构改动后,默认至少执行 `python3 -m py_compile`
- 如果改动触达运行时或边界协议,再考虑追加更高层验证
### 4.3 文档同步规则
以下情况必须同步设计文档:
- 新增一层目录边界
- 新增一个领域的标准拆法
- 改变页面/服务的职责划分
- 把兼容层正式降级为装配/导出层
### 4.4 禁止事项
- 禁止回到“大文件集中堆功能”的开发方式
- 禁止为了图省事把新逻辑加回兼容层
- 禁止在没有明确复用收益时过度抽象
- 禁止为了满足行数指标而把同一业务域强行拆碎
- 禁止在一次改动里同时重写 UI、重写数据流、重写接口协议
---
## 5. 当前执行基线2026-03
当前结构治理目标分两层:
- 第一层:主入口、页面入口、路由入口必须变薄
- 第二层:领域内部的 service / hook / overlays / sections 必须按主题稳定收口
后续所有新增功能与重构,均以本文档为准执行。