系统设计:架构、数据、接口、模块边界先立住
学会写一页系统设计初稿:主资产、分层、边界与待定问题
这篇只解决一个问题:怎么写一页系统设计初稿#
上一章把 workspace、目录结构、命令入口这些协作界面先搭起来了。很多人走到这里,会自然冒出一个念头:
仓库骨架都有了,是不是可以让 AI 直接开写?
这时候最容易发生的,不是“AI 写不出来”,而是它写得太顺了。
比如一个退款审核后台,AI 很可能会顺手做出下面这些事:
- 先在服务层里塞一版临时状态对象。
- 后台页面直接读这版对象渲染列表。
- 报表任务把缓存表当成查询真源继续往外扩。
- 几轮 issue 之后,页面有了、接口有了、任务也能跑了,但退款状态到底以谁为准,反而越来越说不清。
这类问题的根子,不是实现太慢,而是实现之前缺了一张中间稿。
所以这一篇不打算再讲一堆“系统设计很重要”的正确话,它只解决一个动作:
在开写实现前,怎么写出一页系统设计初稿。
读完这一篇,手里应该有一张能继续往下做的草图这一页初稿不是总施工图,也不是完整架构说明书。
它只需要先回答六件事:
- 系统维护的主资产是什么
- 3 到 5 个分层和官方路径是什么
- 哪三条边界现在绝对不能乱越
- 哪些决策已经定了
- 哪些问题明确还没定
- 下一批 issue 应该从哪里继续拆
如果这一页还写不出来,后面的代码、Spec、Rules、Skills 都很容易一起漂。
这页初稿到底长什么样#
先别讲定义,先看成品骨架。
真正能用的一页系统设计初稿,长得大概就像下面这样:
# 系统设计初稿(v0)
## 1. 主资产
一句话:
不是:
## 2. 分层与官方路径
- 入口层:
- 应用层:
- 核心事实层:
- 投影层:
- 证据层:
官方路径:
## 3. 三条关键边界 / 禁止捷径
-
-
-
## 4. 已定决策
-
-
-
## 5. 待定问题
-
-
-
## 6. 下一批 issue 种子
-
-
- 这张表里,其实已经把“架构、数据、接口、模块边界”都压进去了:
| 模板里的哪一格 | 实际在检查什么 |
|---|---|
| 主资产 | 数据真源到底是什么 |
| 分层与官方路径 | 架构主线到底怎么走 |
| 关键边界 | 接口和跨层调用能不能乱绕 |
| 下一批 issue 种子 | 模块边界和改动落点清不清楚 |
所以这篇后面不再分四大章讲大道理,而是只讲一件事:
怎么把这六格按顺序填出来。
按顺序把这六块填出来#
1. 先写主资产#
要写什么:一句话写清系统真正维护的事实是什么,最好再补一句“它不是什么”。
最容易写错成什么:写成产品愿景、功能清单,或者把缓存、报表、搜索索引这类副产物写成主资产。
举个很常见的对照:
- 好写法:这个系统维护的是退款申请及其审核状态流转。
- 坏写法:这个系统是一个帮助运营提升效率的退款管理平台。
前一句能指导后面的设计,后一句更像产品介绍。
2. 再写分层与官方路径#
要写什么:写 3 到 5 层就够了,只写当前阶段真的存在的层,以及一条“正常情况下系统应该怎么走”的官方路径。
最容易写错成什么:把每个模块、每个目录、每个类都摊开,最后画成一张很复杂但没人敢用的盒子图。
这里最关键的不是层数,而是两件事:
- 谁是主线层
- 谁必须经过谁,不能直连
如果官方路径都写不出来,说明系统主线其实还没定。
3. 然后写三条关键边界#
要写什么:只写当前最容易被 AI 或开发者顺手越过的三条边界,也就是三条最贵的“禁止捷径”。
最容易写错成什么:写成抽象口号,比如“注意分层”“保持一致”“避免耦合”,这种话看起来像规则,实际上拦不住任何错误。
边界要写成能执行的句子,比如:
- 后台页面不能直接写主表,必须走审核服务
- 报表缓存不能反向覆盖主状态
- 风控命中结果只能作为输入,不能直接改最终审核结论
一眼就知道什么能做、什么不能做,才算边界。
4. 接着写已定决策#
要写什么:只写当前阶段已经可以让后续实现直接依附的判断。
最容易写错成什么:把“倾向”“猜测”“以后可能会这样”也混进来,结果文档里看上去全都像定论。
如果某条判断后面的开发已经可以直接照着走,那它才算已定。
如果它还需要再开会、再吵、再开 issue,它就不该写进这里。
5. 再把待定问题摊开#
要写什么:写那些现在还不能假装已经拍板,但如果不写出来,后面又一定会有人偷偷在实现里帮你拍板的问题。
最容易写错成什么:为了显得自己想得很全,把待定问题全删掉,最后让实现阶段默默替产品做决定。
这一格不是丢脸区,反而是整页里最值钱的一格之一。
因为它能阻止团队把“还没决定”误读成“已经默认决定了”。
6. 最后写下一批 issue 种子#
要写什么:写接下来最值得继续收敛的 2 到 4 个问题,它们应该是可以单独拿出来继续讨论、继续写 spec、继续落实现的种子。
最容易写错成什么:写成施工顺序清单,比如“先写后端,再写前端,再补测试”,这种写法看起来像计划,实际上没有告诉人“下一步到底该继续收哪一个判断”。
更好的写法是:
- 定义驳回原因的数据契约
- 拆审核服务和通知服务之间的接口
- 设计审核列表的投影与缓存刷新策略
这样写,下一步要开什么 issue 就已经很清楚了。
一个很实用的自检问题如果这一页写完之后,团队还是没法回答“下一步先继续收哪一个问题”,那通常不是执行不够快,而是这一页还不够像系统设计初稿。
用一个通用后台案例填一遍#
下面直接拿一个大众化很多的场景来填一次:退款审核系统。
# 退款审核系统设计初稿(v0)
## 1. 主资产
一句话:系统维护的是退款申请及其审核状态流转。
不是:不是运营报表,不是通知记录,也不是审计日志。
## 2. 分层与官方路径
- 入口层:运营后台页面、审核 API
- 应用层:退款审核服务,负责接收动作并编排后续流程
- 核心事实层:退款申请、审核记录、状态流转
- 投影层:审核列表缓存、退款报表、运营看板
- 证据层:风控命中、客服备注、审计日志
官方路径:
审核员 -> 运营后台 -> 退款审核服务 -> 退款申请与状态流转 -> 通知与报表投影
## 3. 三条关键边界 / 禁止捷径
- 运营后台不能直接写退款主表,必须通过退款审核服务提交动作
- 报表缓存只能读主状态,不能反向覆盖退款状态
- 风控命中结果只能作为审核输入,不能绕过人工审核直接拒绝退款
## 4. 已定决策
- 当前阶段只支持通过、驳回、补充材料三种审核动作
- 驳回动作必须填写原因
- 通知发送统一由退款审核服务触发,不允许页面层自己发消息
## 5. 待定问题
- 驳回原因采用枚举加备注,还是完全自由输入
- 高风险退款是否需要双人复核
- 审计日志保留到什么粒度
## 6. 下一批 issue 种子
- 定义驳回原因的数据契约和校验规则
- 设计退款审核服务与通知服务的接口
- 设计审核列表投影和缓存刷新策略这个例子最值得看的,不是业务本身,而是它已经把后面开发最容易漂的几件事先收住了:
- 主资产是退款申请和状态流转,不是缓存和报表
- 官方路径是“后台 -> 审核服务 -> 主状态”,不是“页面直接改表”
- 三条禁止捷径已经写成能执行的话
- 哪些能直接开工,哪些还得继续开 issue,也分开了
到这里,读者其实已经不需要再听更多方法论了。
拿这张模板,换成自己的后台、用户系统、支付系统、审批流,直接照着填就行。
再看 GraphSpec,为什么它也能套这张表#
GraphSpec 看起来比退款审核系统特别很多,但它其实也只是换了一个领域,同样能套进这张表。
可以压缩成这样看:
| 模板项 | GraphSpec 里的写法 |
|---|---|
| 主资产 | 架构图与 graph draft,而不是扫描结果 |
| 分层与官方路径 | CLI 入口 -> graph 应用层 -> 主资产层 -> scanner 证据层 -> 视图层 |
| 三条关键边界 | scanner 不能定义主图;视图不能反向绑死主资产;外层不能直接改内部主模型 |
| 已定决策 | 当前 phase 先做只读 graph、结构视图和下钻关系 |
| 待定问题 | graph edit 协议、OpenSpec bridge 粒度、snapshot schema 细化 |
| 下一批 issue 种子 | 数据契约细化、视图扩展、bridge 设计 |
所以 GraphSpec 真正能说明的,不是“这是一种特别新奇的系统设计写法”,而是:
只要这一页模板写得够清楚,再特别的领域,也照样能先收成一张能继续往下做的初稿。
如果想对照 GraphSpec 的原始材料可以直接看这两份文档:
到这里,下一章才接着讲 Spec、Rules 和 Skills#
这一页初稿写完之后,后面几件事的落点才会开始清楚:
Spec负责描述某一次具体变更Rules负责保护长期边界Skills负责复用稳定能力
它们都重要,但它们都不替代这一页。
因为这一页回答的是更前面的那个问题:
这个系统本体到底是什么,边界先立在哪里。