Vibe Coding 从用户故事到关系模型:先固定不变量,再让 AI 写表
用户故事只描述价值,不足以直接生成可靠 Schema。本文把参与者、生命周期、不变量、查询与删除语义整理成建模简报,再用迁移和反例测试约束 AI 产出的关系模型。
本文要点
- 主题聚焦:AI、Vibe Coding、TypeScript
- 适合人群:独立开发者、全栈工程师、AI 应用开发者
- 核心价值:快速理解背景、实践路径、常见误区和工程建议
“用户可以创建项目并邀请成员”看起来足够清楚,交给 AI 后却可能得到 users.projects jsonb、一张没有唯一约束的 members 表,或者允许邀请记录指向已删除项目的外键。问题不在 SQL 语法,而在用户故事省略了关系模型真正需要的语义:谁拥有谁、同一成员能否重复加入、邀请与成员是否是同一事物、删除项目后审计记录保留多久。
Vibe Coding 的正确起点不是“根据故事生成 Prisma Schema”,而是一份可质疑的建模简报。先参考数据库范式与反范式理解依赖关系,再把 AI 当作候选模型生成器,而不是事实补全器。
把一句故事拆成五类证据
第一类是参与者与租户边界。列出用户、组织、项目、外部邀请对象,并明确每个对象的身份来源。email 是联系方式还是邀请时的快照?用户注销后,成员关系是删除、匿名化还是保留?这些问题不回答,AI 往往会根据字段名自行假设。
第二类是生命周期。用状态表写出 invited -> accepted -> revoked 的合法迁移、操作者与时间。不要先创建一个随意的 status varchar;先判断状态是否属于邀请、成员或项目。需要追踪历史时,可结合数据库时态数据模式,区分当前事实与事件记录,避免每次状态变化都覆盖证据。
第三类是不变量。用接近数据库约束的语言表达,例如:
同一 project_id 下,user_id 最多有一个有效成员关系
待接受邀请必须有 normalized_email,已绑定用户后 user_id 不为空
项目 owner 必须同时是 active member
成员不能引用其他 tenant 的项目
把每条不变量标注为数据库约束、事务内检查或异步审计。能用 NOT NULL、CHECK、UNIQUE、FOREIGN KEY 表达的,不要只藏在生成的服务代码里。PostgreSQL 的约束文档也提醒:CHECK 不适合依赖其他行的动态条件;跨行规则通常需要唯一索引、外键或受控事务。
第四类是访问路径。列出真正需要回答的问题及排序方式:“按项目分页列出有效成员”“按邮箱查找未过期邀请”“展示用户最近访问的项目”。它们决定复合索引的列顺序,而不是“给每个外键都加索引”的机械提示。分页方案还应与数据库游标与 OFFSET的稳定排序要求一致。
第五类是保留与删除。分别写用户删除、项目删除、组织停用、邀请过期时的行为。CASCADE 方便,但可能把审计和计费依据一起抹掉;RESTRICT 更保守,却要求显式清理流程。让 AI 为每条外键输出删除矩阵,并说明选择依据,审查者才看得见风险。
让 AI 产出候选,而不是唯一答案
把建模简报、数据库版本和既有命名规范放进上下文,要求 AI 同时给出两个候选:规范化模型,以及针对已声明查询做有限冗余的模型。每个候选必须包含实体关系图、字段含义、约束、索引、删除策略和仍未回答的问题。禁止它凭空补全业务规则;未知项必须写成 OPEN QUESTION。
接着进行“反例回合”。输入重复邀请、邮箱大小写差异、两个请求同时接受邀请、owner 被移除、跨租户 ID、过期后重发等案例,让 AI 指出哪一层阻断。若答案只是“应用会校验”,就要求定位到事务和约束。涉及并发写入时,先读PostgreSQL 事务与隔离级别,不要把单请求测试当作并发证明。
模型获批后再生成迁移和 ORM 类型。迁移必须是唯一事实来源;生成的 TypeScript 类型不能反过来掩盖数据库可空性。枚举是否用数据库 enum,要考虑后续值变更成本;金额、时区时间、网络地址等字段应按语义选择原生类型,而不是统一用字符串。
用失败用例验收 Schema
为每条不变量至少准备一个能成功和一个必须失败的数据库测试。测试直接执行迁移后的数据库,而不只 mock repository:重复成员触发唯一冲突,孤儿项目被外键拒绝,非法状态被 CHECK 拒绝,删除策略与矩阵一致。再用属性测试生成不同操作顺序,验证任何可达状态都没有跨租户引用或多个 owner。
查询验收使用固定数据规模只检查计划形态,不声称虚构的耗时收益:确认关键过滤条件能使用预期索引、游标排序具有唯一结尾键、索引没有破坏唯一语义。索引的长期维护可参考数据库索引策略,但不要在不知道读写比例时让 AI 预建大量“可能有用”的索引。
最后保存建模决策记录:故事版本、开放问题、采用的候选、被拒绝方案、每条不变量的实现位置,以及迁移和测试链接。下一次故事变化时,先让 AI 从记录生成影响清单,再由开发者逐项确认受影响的约束、历史数据、API 和查询计划;未确认的项不能直接进入迁移。
用户故事会变,可靠的关系模型不是猜对一次,而是让每次变化都能追溯到受影响的约束、数据和查询。
Related