chore(backend): 落地 ADS 治理体系、升级日志并收录后端模板基线代码
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
# 项目开发实践指南(VIBECODING GUIDE)
|
||||
|
||||
> 本文档是基于"踩过的坑"沉淀下来的项目工作方式约定,适用于本仓库及后续所有同性质的项目。
|
||||
> 它的姊妹文件是 [`SELF_CONSTRAINTS.md`](./SELF_CONSTRAINTS.md) —— 那是 Agent 每次开工前必须自查的硬约束清单。
|
||||
> 本文回答 "为什么这么做";`SELF_CONSTRAINTS.md` 回答 "具体不许做什么"。
|
||||
|
||||
---
|
||||
|
||||
## 0. 三条核心教训(本指南的来由,优先级严格递减)
|
||||
|
||||
1. **版本控制必须从第 0 天开始。**
|
||||
不是 "等做出点东西再说",是写第一行代码之前先初始化仓库、写好 ignore 规则、提交一个空骨架。
|
||||
理由:高频改动 + 频繁推翻是 AI 协作的常态,没有版本控制兜底就等于在悬崖边裸奔。
|
||||
|
||||
2. **文档必须在写代码之前定下来。**
|
||||
需求、架构、路线图、开发规范、目录结构、命名规范、模块边界 —— 这些不是"做完之后补的",是"做之前定的"。
|
||||
理由:一旦上下文被代码细节占满,后续每个新会话都只能 freestyle,项目会朝不可逆的方向漂移。
|
||||
|
||||
3. **架构 > UI > 用户体验。**
|
||||
最致命的不是界面丑、不是体验差,而是模块互相纠缠到无法定位问题。
|
||||
一个出问题就能立刻指认 "是 X 模块的责任" 的项目,比一个好看但耦合一团的项目,存活率高一个数量级。
|
||||
理由:耦合一旦发生,AI 协作模式会迅速放大它 —— 因为每次新会话都看不全全貌,只会在原有耦合上继续添乱。
|
||||
|
||||
> 这三条的优先级是严格递减的:先有版本控制,再有文档,再谈架构;架构稳了之后才轮到 UI 和体验。
|
||||
|
||||
---
|
||||
|
||||
## 1. 项目启动 Checklist(Day 0)
|
||||
|
||||
下列每一项都必须在写第一行业务代码之前完成。顺序即优先级。
|
||||
|
||||
### 1.1 仓库与版本控制
|
||||
- [ ] 初始化版本控制并立即建立 ignore 规则(语言 / IDE / 系统三类至少齐全)
|
||||
- [ ] 提交一个 **空骨架 commit**(README + ignore 规则 + 空目录结构),作为"零点参照系"
|
||||
- [ ] 约定分支模型(最简:主干 + 短命的功能分支;不要等到分叉时才想)
|
||||
- [ ] 约定 commit message 风格(推荐 Conventional Commits,至少要求动词开头 + 一句话原因)
|
||||
|
||||
### 1.2 文档骨架(必须先于代码存在)
|
||||
在 `.project.agents/docs/context` 下建立以下文件,**哪怕只有大纲也比没有强**:
|
||||
|
||||
| 文件 | 角色 | 上下游关系 |
|
||||
|---|---|---|
|
||||
| `PRD.md` | 产品需求(要做什么) | 上游 |
|
||||
| `ARCHITECTURE.md` | 架构(怎么拆) | 上游 |
|
||||
| `ROADMAP.md` | 路线图(什么时候做哪一块) | 由需求 + 架构推导 |
|
||||
| `CONVENTIONS.md` | 开发规范(命名、目录、提交、风格) | 上游 |
|
||||
| 派生文档(实现 spec / 资产清单等) | 屏幕级实现 / 资产清单 | **派生**,由上游产生 |
|
||||
|
||||
**判断标准**:如果一个新会话的 Agent 只读需求 + 架构 + 开发规范就能正确开始一个任务 —— 文档就算合格。
|
||||
|
||||
### 1.3 Agent 协作配置
|
||||
- [ ] 在 `CLAUDE.md` 写明项目级规则(已有,保持更新)
|
||||
- [ ] 在本文件 + `SELF_CONSTRAINTS.md` 中固化经验
|
||||
- [ ] 在 `.project.agents/settings.json` 中配置必要的 hook / 权限(不要散落到根目录或全局)
|
||||
|
||||
---
|
||||
|
||||
## 2. 架构原则
|
||||
|
||||
### 2.1 三条硬规则
|
||||
|
||||
1. **单一职责到模块级**
|
||||
每个模块只回答一个问题。
|
||||
反例:"一个模块既管数据持久化,又管网络请求,又管 UI 状态" —— 这种模块必须拆。
|
||||
|
||||
2. **依赖方向单向**
|
||||
高层依赖低层,UI 依赖业务,业务依赖数据;**反向依赖一律禁止**,遇到就用接口/事件/回调倒置。
|
||||
依赖关系必须能画成一张**有向无环图(DAG)**,且这张图要在 `ARCHITECTURE.md` 里画出来。
|
||||
|
||||
3. **跨模块只走"接口契约"**
|
||||
模块 A 想用模块 B 的能力,只能通过 B 暴露的接口/协议,不能 reach into B 的内部实现。
|
||||
接口契约必须在 `ARCHITECTURE.md` 中显式声明(哪怕只是函数签名清单)。
|
||||
|
||||
### 2.2 判断架构是否健康的三个问句
|
||||
|
||||
随时可以用这三个问句自检:
|
||||
|
||||
1. **指认问题**:现在出 bug 了,我能否在 30 秒内指出"这是哪个模块的责任"?
|
||||
2. **替换实现**:如果要把模块 X 整体换掉(换数据库、换框架),改动是否能控制在 X 内部 + 一个接口适配层?
|
||||
3. **新增功能归属**:用户要加一个新功能,我能否立刻说出它"属于哪个模块、或需要新增哪个模块"?
|
||||
|
||||
任何一个回答不出来,架构就有问题,**先停下修架构,再写代码**。
|
||||
|
||||
### 2.3 反耦合纪律
|
||||
|
||||
- **不在新功能开发时顺手重构无关模块**(重构走单独 commit + 单独会话)
|
||||
- **不在 UI 层做业务判断**(UI 只接收状态、发送意图)
|
||||
- **不让数据模型自己跑业务逻辑**(模型类保持瘦,业务放 Service / UseCase)
|
||||
- **不要"为了少写一个文件"把两个模块塞进同一个文件**
|
||||
|
||||
---
|
||||
|
||||
## 3. 项目架构文档生成流程
|
||||
|
||||
这是从零到 `ARCHITECTURE.md` 的标准流程。每一步都有产出物,下一步必须基于上一步的产出物。
|
||||
|
||||
### Step 1 — 需求收敛(产出 `PRD.md`)
|
||||
- 列功能清单,按 **核心 / 增强 / 可选** 三档分类
|
||||
- 每个核心功能写一句 "用户故事"("作为 X,我想 Y,以便 Z")
|
||||
- **冻结 MVP 范围**:圈出 MVP 包含哪些核心功能,其余明确标 "Out of MVP"
|
||||
|
||||
### Step 2 — 领域建模(产出 `ARCHITECTURE.md` §1 领域模型)
|
||||
- 列出所有**名词实体**(用户、订单、会话…)
|
||||
- 标注每个实体的字段、关系、生命周期
|
||||
- 标记哪些是**持久化实体**,哪些是**瞬态状态**
|
||||
|
||||
### Step 3 — 模块划分(产出 `ARCHITECTURE.md` §2 模块清单)
|
||||
对照领域模型与需求功能清单,拆分模块。每个模块写一张卡片:
|
||||
|
||||
```
|
||||
## 模块名:<Name>
|
||||
- 职责:一句话
|
||||
- 不负责:明确写出"不做什么"(防止职责蔓延)
|
||||
- 输入:从哪些模块/外部来
|
||||
- 输出:暴露给谁
|
||||
- 关键类型/接口:列签名(不写实现)
|
||||
- 持有状态:有没有自己的状态?
|
||||
```
|
||||
|
||||
**经验**:如果一个模块的"不负责"写不出来,说明它的职责还没想清楚,回到 Step 2。
|
||||
|
||||
### Step 4 — 依赖图(产出 `ARCHITECTURE.md` §3 依赖图)
|
||||
- 画出模块间依赖箭头(推荐 Mermaid,纯文本可 diff)
|
||||
- **手动验证 DAG**:从任一节点 DFS 不应回到自己
|
||||
- 标出"接口边界":哪些依赖是接口注入,哪些是直接调用
|
||||
|
||||
### Step 5 — 路线图(产出 `ROADMAP.md`)
|
||||
按依赖图的拓扑顺序排开发节奏:
|
||||
- 先做被依赖最多的底层模块
|
||||
- 每个 milestone 必须能独立通过编译/构建并跑出某种"可见行为"
|
||||
- 写明每个 milestone 完成的"验收标准"(不是"做完了",是"做完了之后能演示什么")
|
||||
|
||||
### Step 6 — 开发规范(产出 `CONVENTIONS.md`)
|
||||
- 命名(类型 / 文件 / 目录 / 资产)
|
||||
- 代码风格(缩进 / 注释策略 / 错误处理边界)
|
||||
- 提交规范
|
||||
- 测试策略(哪些必须有测试,哪些不要求)
|
||||
|
||||
### Step 7 — 派生文档(产出实现 spec / 资产清单等)
|
||||
**只有上面 6 步都齐了,才能开始写派生文档**。
|
||||
派生文档必须显式引用上游章节("对应 `ARCHITECTURE.md` §2.3 的 XxxService 模块"),方便后续 diff 校验。
|
||||
|
||||
---
|
||||
|
||||
## 4. 文档变更协议
|
||||
|
||||
文档不是写完就锁死的,但变更必须**沿着上下游传播**:
|
||||
|
||||
| 变更点 | 必须同步更新 |
|
||||
|---|---|
|
||||
| 需求加/删/改功能 | 架构模块清单、路线图、派生文档 |
|
||||
| 架构调整模块边界 | 依赖图、开发规范(如有命名调整)、派生文档 |
|
||||
| 加新模块 | 架构 §2 + §3、路线图、开发规范(如新目录) |
|
||||
|
||||
**权威链**:`PRD.md > ARCHITECTURE.md > CONVENTIONS.md > 派生文档`。
|
||||
派生文档永远不能**反向**修改上游。如果在派生文档中发现矛盾,回去改上游,再让派生文档重新对齐。
|
||||
**代码与架构漂移 > 24 小时即违规。**
|
||||
|
||||
---
|
||||
|
||||
## 5. 实施日志(execution log)
|
||||
|
||||
写代码 / 执行路线图期间,**每完成一个可独立验收的"部分",必须在 `.project.agents/log` 写一份日志**。日志是给"下一个会话的我"看的 —— 让接手的会话能在不读所有代码的情况下知道:刚才完成了什么、哪些提交、下一步是什么。
|
||||
|
||||
### 5.1 何时写日志
|
||||
- 完成一个路线图 milestone
|
||||
- 完成一个 milestone 内独立可验收的子任务
|
||||
- 完成一次非平凡的重构 / bug 修复
|
||||
- 当前会话即将结束时(兜底,把上下文沉淀下来)
|
||||
|
||||
**判断标准**:如果这段工作下一个会话需要知道,就写。
|
||||
|
||||
### 5.2 日志文件命名
|
||||
`.project.agents/log/YYYY-MM-DD-<slug>.md`
|
||||
- `<slug>` = 简短动词 + 范围,kebab-case
|
||||
- 同日多份日志按写作顺序累积(不覆盖、不合并),文件名加序号后缀:`-1`、`-2`…
|
||||
|
||||
### 5.3 日志内容模板
|
||||
```markdown
|
||||
# <一句话标题:完成了什么>
|
||||
|
||||
- **日期**:YYYY-MM-DD
|
||||
- **关联**:路线图 M<N> / 子任务名 / 关联文档
|
||||
- **会话上下文**:(可选)本会话从哪开始接手的
|
||||
|
||||
## 做了什么
|
||||
- bullet 1
|
||||
- bullet 2
|
||||
|
||||
## 提交
|
||||
- `<short hash>` <commit subject>
|
||||
|
||||
(若本段未提交:明确写"未提交,工作树状态:…"并说明原因)
|
||||
|
||||
## 状态变更
|
||||
- 架构文档:是否动过?动了哪一节?
|
||||
- 需求/UI 文档:是否触发回归?
|
||||
- 测试:跑了什么,结果
|
||||
|
||||
## 下一步
|
||||
- 接下来要做的第一件事(具体到任务名)
|
||||
- 已知阻塞 / 待澄清项
|
||||
```
|
||||
|
||||
### 5.4 与提交的关系
|
||||
日志**不替代** commit message,commit message 仍按 `CONVENTIONS.md` 写;日志是提交的**索引与解释**。
|
||||
|
||||
### 5.5 不写日志的情况
|
||||
- 还没完成一个"可独立验收"的部分 —— 不要"写日志凑数"
|
||||
- 纯文档调整 —— commit 自身已足够说明
|
||||
- 实验性探索(最终被回滚的内容)—— 用 commit message 记录即可
|
||||
|
||||
---
|
||||
|
||||
## 6. 出问题时的排查流程
|
||||
|
||||
bug 来了不要直接钻进代码。按下列顺序:
|
||||
|
||||
1. **复现并定位现象**:能在哪个入口 / 哪个调用稳定复现?
|
||||
2. **回到架构图**:这个现象涉及哪些模块?沿着依赖图圈出可能责任方。
|
||||
3. **审查接口契约**:跨模块调用是否符合 `ARCHITECTURE.md` 中声明的接口?输入输出是否符合契约?
|
||||
4. **缩小到单模块**:把嫌疑缩小到一个模块后,再读该模块代码。
|
||||
5. **修复并回写经验**:如果发现是架构层面的漏洞,修完代码后**必须更新 `ARCHITECTURE.md` 或 `CONVENTIONS.md`**。
|
||||
|
||||
**反模式**:bug 一来就 grep 关键字、改一行试一下、再改一行试一下 —— 这是死亡螺旋,必须用流程压下去。
|
||||
|
||||
---
|
||||
|
||||
## 7. 反模式清单("看到这些立刻警觉")
|
||||
|
||||
- 出现语义为空的模块名(`Manager` / `Helper` / `Util` / `Common` / `Misc` / `Tools`)且行数 > 100 行
|
||||
- 一个文件 import 超过 10 个本地模块
|
||||
- 改一个 UI 改动需要动 3 个以上其他模块
|
||||
- 同一份业务逻辑在两个地方各写了一遍
|
||||
- PR 描述写"顺便修了 X"
|
||||
- 新增功能时发现"无处归属",于是塞进入口文件或主组件
|
||||
- 文档与代码不一致超过 24 小时
|
||||
- 出现没有在 `ARCHITECTURE.md` 中登记的新模块/新依赖方向
|
||||
|
||||
任何一条出现,**先停下来回到本指南或架构文档,不要继续往前推**。
|
||||
|
||||
---
|
||||
|
||||
## 8. 本项目当前阶段
|
||||
|
||||
> 本节随项目演进,不是规则的一部分。由 Agent 在每个 milestone 后更新。
|
||||
|
||||
<!-- 由 /ads:init(2026-08-19,Retrofit)填入:本项目为后端微服务模板,治理已入位。 -->
|
||||
- 当前状态:后端模板(`abacus.springboot.example`)已完成治理落地(Retrofit),分层以示例模块实际结构为准(api/controller/dao/esb/pi/impl/repository/wsi/config/util/vo);前后端共享约束单源化于工作区 `docs/`(`../../../docs/coding-standards.md`)。
|
||||
- 下一步合规动作:新业务模块按 `docs/coding-standards.md §5`(后端规范)与 §7(AI 生成工作流)开发;任何新增包、依赖方向或 SQL 变更先回写本仓库 `ARCHITECTURE.md` 与 `sql/` 约定,再写代码。
|
||||
Reference in New Issue
Block a user