Files
saas-mbr/abacus.springboot.example/.project.agents/VIBECODING_GUIDE.md
T

12 KiB
Raw Blame History

项目开发实践指南(VIBECODING GUIDE

本文档是基于"踩过的坑"沉淀下来的项目工作方式约定,适用于本仓库及后续所有同性质的项目。 它的姊妹文件是 SELF_CONSTRAINTS.md —— 那是 Agent 每次开工前必须自查的硬约束清单。 本文回答 "为什么这么做";SELF_CONSTRAINTS.md 回答 "具体不许做什么"。


0. 三条核心教训(本指南的来由,优先级严格递减)

  1. 版本控制必须从第 0 天开始。 不是 "等做出点东西再说",是写第一行代码之前先初始化仓库、写好 ignore 规则、提交一个空骨架。 理由:高频改动 + 频繁推翻是 AI 协作的常态,没有版本控制兜底就等于在悬崖边裸奔。

  2. 文档必须在写代码之前定下来。 需求、架构、路线图、开发规范、目录结构、命名规范、模块边界 —— 这些不是"做完之后补的",是"做之前定的"。 理由:一旦上下文被代码细节占满,后续每个新会话都只能 freestyle,项目会朝不可逆的方向漂移。

  3. 架构 > UI > 用户体验。 最致命的不是界面丑、不是体验差,而是模块互相纠缠到无法定位问题。 一个出问题就能立刻指认 "是 X 模块的责任" 的项目,比一个好看但耦合一团的项目,存活率高一个数量级。 理由:耦合一旦发生,AI 协作模式会迅速放大它 —— 因为每次新会话都看不全全貌,只会在原有耦合上继续添乱。

这三条的优先级是严格递减的:先有版本控制,再有文档,再谈架构;架构稳了之后才轮到 UI 和体验。


1. 项目启动 ChecklistDay 0

下列每一项都必须在写第一行业务代码之前完成。顺序即优先级。

1.1 仓库与版本控制

  • 初始化版本控制并立即建立 ignore 规则(语言 / IDE / 系统三类至少齐全)
  • 提交一个 空骨架 commitREADME + 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 日志内容模板

# <一句话标题:完成了什么>

- **日期**YYYY-MM-DD
- **关联**:路线图 M<N> / 子任务名 / 关联文档
- **会话上下文**:(可选)本会话从哪开始接手的

## 做了什么
- bullet 1
- bullet 2

## 提交
- `<short hash>` <commit subject>

(若本段未提交:明确写"未提交,工作树状态:…"并说明原因)

## 状态变更
- 架构文档:是否动过?动了哪一节?
- 需求/UI 文档:是否触发回归?
- 测试:跑了什么,结果

## 下一步
- 接下来要做的第一件事(具体到任务名)
- 已知阻塞 / 待澄清项

5.4 与提交的关系

日志不替代 commit messagecommit message 仍按 CONVENTIONS.md 写;日志是提交的索引与解释

5.5 不写日志的情况

  • 还没完成一个"可独立验收"的部分 —— 不要"写日志凑数"
  • 纯文档调整 —— commit 自身已足够说明
  • 实验性探索(最终被回滚的内容)—— 用 commit message 记录即可

6. 出问题时的排查流程

bug 来了不要直接钻进代码。按下列顺序:

  1. 复现并定位现象:能在哪个入口 / 哪个调用稳定复现?
  2. 回到架构图:这个现象涉及哪些模块?沿着依赖图圈出可能责任方。
  3. 审查接口契约:跨模块调用是否符合 ARCHITECTURE.md 中声明的接口?输入输出是否符合契约?
  4. 缩小到单模块:把嫌疑缩小到一个模块后,再读该模块代码。
  5. 修复并回写经验:如果发现是架构层面的漏洞,修完代码后必须更新 ARCHITECTURE.mdCONVENTIONS.md

反模式:bug 一来就 grep 关键字、改一行试一下、再改一行试一下 —— 这是死亡螺旋,必须用流程压下去。


7. 反模式清单("看到这些立刻警觉")

  • 出现语义为空的模块名(Manager / Helper / Util / Common / Misc / Tools)且行数 > 100 行
  • 一个文件 import 超过 10 个本地模块
  • 改一个 UI 改动需要动 3 个以上其他模块
  • 同一份业务逻辑在两个地方各写了一遍
  • PR 描述写"顺便修了 X"
  • 新增功能时发现"无处归属",于是塞进入口文件或主组件
  • 文档与代码不一致超过 24 小时
  • 出现没有在 ARCHITECTURE.md 中登记的新模块/新依赖方向

任何一条出现,先停下来回到本指南或架构文档,不要继续往前推


8. 本项目当前阶段

本节随项目演进,不是规则的一部分。由 Agent 在每个 milestone 后更新。

  • 当前状态:后端模板(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.mdsql/ 约定,再写代码。