AI时代的工程协作:人做决策,AI写代码

用AI写代码不难,难的是不让系统崩。
用AI写代码这事,越来越多人在做了。但很多人的体验是:写得挺快,崩得也快。
写在前面
很多人用AI写代码的体验是这样的:
- AI生成了一堆代码,能跑,但你不知道逻辑对不对
- 改了一个地方,另一个地方莫名其妙崩了
- 项目越来越大,越来越不敢动
- 最后变成”能跑就不要碰”
问题出在哪?
不是AI不行,是你把”决策权”也交给了AI。AI很会”生成”,但它不会替你背锅:这个设计合不合理、这个边界该怎么处理、出错了系统停在哪。
这篇文章想做一件事:给你一套从需求到上线的完整流程。每一步都知道自己该干嘛、AI该干嘛。
核心原则只有一条:你永远在决策位,AI永远在执行位。
一、项目启动前:5个必问问题
在让AI动手之前,先问自己这 5 个问题。想清楚了,后面一半的复杂设计会自动消失。
问题1:给谁用?
判断三点:
- 几个人用?(1人 / 几个 / 几百 / 不确定)
- 用得频不频繁?(偶尔 / 每天 / 一直在用)
- 坏了会不会出事?(无所谓 / 影响工作 / 出事故)
结论用一句话写出来:“这是一个给 ___ 用、___ 频率、坏了 ___ 的系统。”
5个人用的内部工具和5万人用的付费产品,设计完全不一样。
问题2:最重要的是什么?
只能选1-2个:快、稳、便宜、安全、好改。
规则很硬:
- 人少 → 优先”好改 + 便宜”
- 用户少 → 不追求极致快
- 内部工具 → 稳 > 快
架构本质就是:为了这1-2个最重要的东西,放弃其他的。
问题3:哪些绝对不能错?
常见答案只有四类:钱、状态、数据、权限。
凡是”不能错”的地方,设计要保守。架构不是哪都复杂,是只在关键点变重。
问题4:先做多简单?
铁律:没有被明确证明”不够用”的,一律不加。
- 没慢过 → 不加缓存
- 没堵过 → 不上队列
- 没多人一起改 → 不拆服务
“感觉以后可能要” = 不加。
问题5:以后最怕改哪?
找出那个”牵一发动全身”的地方,把它单独放清楚。其他地方先写死、写傻、写直。
二、人×AI协作流程
这是时间顺序,按步骤走就行。每一步都写清楚:你做什么、AI做什么、产出什么。没有产出物不进入下一步。
整体分三个阶段:架构设计 → 编码实现 → 验收上线。
阶段一:架构设计
这个阶段全是”想清楚”,不写代码。把系统的骨架、边界、错误处理、日志策略全部定死,后面编码才能顺。
Step 1:锁定需求
你做什么:给AI一句话需求。
比如:“给5个同事用的内部数据查询工具”。
不讨论技术、不讨论实现、不让AI写代码。目的是锁住问题本身。
AI做什么:把需求翻译成四个维度。
给AI的指令:
把这个需求翻译成:
1. 谁用
2. 用来干嘛
3. 用得多不多
4. 坏了会怎样
不要提任何技术。
产出:一页纸需求澄清。
你检查:AI 输出后,你确认、修改、删除。不满意就不往下走。
Step 2:定”不做清单”
你做什么:亲自写不做清单。
- 现在明确不做的事(比如:不做权限系统、不做高可用、不做缓存)
- 不考虑的未来(比如:不考虑1年后的规模)
AI做什么:复述校验。
给AI的指令:
根据我的不做清单,确认哪些复杂度禁止出现。
如果我写的不做清单有遗漏或矛盾,指出来。
产出:确认后的不做清单。
这一刻:系统的复杂度上限被你锁死了。
Step 3:定不变量
你做什么:写3-5条”绝对不能被打破的事实”。
这是最高级、最容易被忽略的东西。
你要在项目一开始写下永远成立的话,例如:
- 钱只会在一个地方被扣
- 核心状态只能单向流转
- 外部系统的返回永远不可信
- 用户权限默认拒绝
- 所有副作用必须可重试
规则:不变量 > 架构 > 代码。AI 生成的任何东西,只要违反不变量,直接推翻。
AI做什么:复述校验。
给AI的指令:
根据我定义的不变量,检查它们之间有没有矛盾。
如果有遗漏重要不变量,建议补充(我来决定)。
产出:不变量清单(INVARIANTS.md,10行就够)。
Step 4:画系统骨架
你做什么:让AI画最粗的系统线形。
给AI的指令:
只用5-6个盒子,画一个从【外部 → 内部 → 数据 → 外部】的线形流程图(用 Markdown 线框图)。
每个盒子一句话说明。
不许出现具体技术名。
不许出现我"不做清单"里的东西。
AI做什么:输出盒子图。
产出示例:
请求进来 → 核心流程处理 → 查/存数据 → 调外部服务 → 记录日志 → 返回结果
你检查:有没有”不做清单”里的东西偷偷混进来,流程是否正确无误。
Step 5:冻结责任边界
你做什么:让AI明确每个盒子的责任。
给AI的指令:
对每一个盒子,写清楚三件事:
1. 负责什么
2. 明确不负责什么
3. 出错时只允许做什么
产出:责任边界表。
职责单一的人话版:一个模块不是”只能做一件事”,而是”只为一个原因变化”。
如果一个模块:
- 既关心业务
- 又关心存储
- 又关心格式
那它一定会烂。
高内聚、低耦合的人话版:
- 该在一起的,放一起
- 不该知道的,别知道
架构直觉:知道得越少,活得越久。
这一刻:
- 系统的责任边界被锁死
- 后面AI不能随便跨盒子写逻辑
- 架构70%已经稳定
Step 6:定数据模型
你做什么:让AI列出系统里有哪些”东西”。
你问的不是用什么数据库,而是:系统里有哪些”东西”是真正存在的?
例如:用户、订单、任务、配置。
给AI的指令:
列出系统里需要存储的核心实体。
对每个实体说明:
1. 它代表什么
2. 哪些字段是必须的
3. 哪些约束是不能违反的(唯一、不能空、有顺序)
4. 它的状态怎么变化(状态机)
数据建模的架构直觉:
数据一旦存在,就会被依赖很久。
所以:
- 建数据要谨慎
- 删数据要更谨慎
关系与约束:约束不是限制你,是保护系统。
越是”不能错”的东西,越要写死在数据层:
- 唯一的,不能重复
- 必须存在的,不能空
- 有顺序的,不能跳
状态机:几乎所有复杂系统,本质都是状态变化。
例如:创建 → 处理中 → 成功/失败,草稿 → 提交 → 审核 → 发布。
架构直觉:
你不写状态机,状态机也存在,只是藏在 if 里。
所以你要做的:
- 明确哪些变化合法
- 非法的直接拒绝
强一致 vs 可以拖一拖:
你不用背CAP,只记一句话:
- 钱、权限、核心状态 → 不能拖
- 统计、报表、日志 → 可以晚点
架构直觉:该慢的时候慢,该稳的时候稳。
产出:数据模型表 + 状态机图。
Step 7:技术选型
你做什么:让AI列选项,你来选。
给AI的指令:
针对每个盒子,列出2-3个可选技术方案。
每个方案只写:优点、缺点、什么时候会不合适。
不要推荐,不要给结论。
你选择:哪一个最符合你前面定的”最重要的点”?
顺便检查:是否需要考虑这些条件?
| 条件 | 要加什么 |
|---|---|
| 多个写操作要一起成功 | 事务 |
| 用队列/定时任务 | 异步边界 |
| 多人同时改同一资源 | 并发控制 |
| 跨服务调用 | 网络边界 |
产出:技术选型表。
Step 8:定目录结构
你做什么:让AI设计目录结构,要考虑内聚解耦、业务需求、技术选型和未来扩展。
给AI的指令:
设计目录结构,要求:
1. 映射到前面的盒子图
2. 高内聚低耦合:相关的放一起,不相关的分开
3. 每个目录一句话说明"只干什么、不干什么"
4. 考虑未来扩展:新功能加进来时,应该很清楚放哪
你检查:
- 是否和盒子图对应?
- 每个目录职责是否清晰?
- 加新功能的时候,知道往哪放吗?
你定模块所有权:
哪怕只有你一个人,也要假装有边界。明确:
- 哪个模块是”核心,慎改”
- 哪个模块是”可替换”
- 哪个模块是”脏活累活隔离区”(第三方、临时逻辑)
规则:
- 核心模块:宁慢、宁笨、宁啰嗦
- 边缘模块:可以快、可以脏、可以扔
你冻结命名规则:
- 目录名 = 角色
- 文件名 = 名词(order_repo, payment_client)
- 函数名 = 动词(create_order(), refund())
让AI复述规则,确认它理解了。
产出:目录职责表 + 命名规则 + 模块所有权表。
Step 9:设计边界契约(核心中的核心)
你做什么:让AI列出关键调用线,强制分层,并为每条线生成边界卡。
这是最关键的一步,直接决定系统是否健壮。
给AI的指令(第一步):
从入口到返回,列出5-12条关键调用线。
每条调用线必须标注属于哪种边界(下面12类之一):
1. 入口边界(用户/调用方 → 系统)
2. 权限边界(谁可以做什么)
3. 核心流程边界(流程步骤之间)
4. 数据读边界(系统 → 数据库查询)
5. 数据写边界(系统 → 数据库写入)
6. 事务边界(哪些操作必须一起成功)
7. 第三方边界(系统 → 外部API)
8. 网络边界(跨服务/跨进程)
9. 异步边界(任务队列/定时任务)
10. 并发边界(多线程/多请求同时来)
11. 配置边界(环境差异)
12. 可观测边界(日志/指标/告警)
只列关键线(一般5-12条)。
判断是否关键的标准(任意满足一条就算关键):
- 涉及钱/权限/核心数据
- 涉及第三方调用
- 涉及写数据库
- 涉及异步/并发
- 涉及跨进程/跨机器
给AI的指令(第二步):
对每条关键线生成一张"边界卡":
1. 这是哪条边界:A → B
2. 属于12类边界中的哪一类
3. A 给 B 什么(输入):字段 + 允许为空吗 + 格式
4. B 回 A 什么(输出):字段 + 含义
5. 前置条件:什么时候不允许调用?
6. 失败分类(只准5类以内):
- 用户问题(输入不对/权限不够)
- 资源不存在(找不到)
- 冲突(重复/版本不一致)
- 外部失败(第三方/网络)
- 内部失败(bug/数据库/未知)
7. 失败策略:
- 这条边界重试吗?(条件/次数/间隔)
- 兜底吗?(返回默认值/延迟执行/降级)
- 要不要补偿?(撤销/回滚/标记待处理)
8. 幂等性:重复调用会怎样
9. 记录:
- 成功时打什么日志(关键点)
- 失败时打什么日志(必须带什么上下文)
10. 可测试性:
- 如何模拟这个边界失败?
- 最少要写哪3个测试?
12类边界的关键问题(AI生成边界卡时必须回答):
1)入口边界
- 输入缺字段怎么办?
- 参数合法但业务不允许怎么办?
- 如何限流、防刷、防误调用?
2)权限边界
- “身份”怎么确认?
- “权限”怎么判断?(按角色/按资源)
- 没权限要不要暴露资源是否存在?
3)核心流程边界
- 这一步失败,前面做过的要不要撤销?
- 允许重复执行吗?
4)数据读边界
- 查不到算错吗?还是正常空?
- 数据量大怎么分页?
5)数据写边界
- 重复提交会不会写两次?
- 并发修改怎么处理?(最后写赢/版本号/锁)
6)事务边界
- 哪些必须”一起成功”?哪些可以”最终一致”?
- 失败后如何恢复?
7)第三方边界
- 超时多长?重试几次?
- 第三方返回奇怪数据怎么办?
- 第三方挂了要不要降级?
8)网络边界
- 请求丢了/重复了怎么办?
- 是否需要请求ID贯穿?
9)异步边界
- 任务失败重跑会不会重复副作用?
- 任务积压怎么办?
10)并发边界
- 同一资源同时更新会怎样?
- 需要锁吗?锁的粒度在哪里?
11)配置边界
- 测试/生产有哪些配置不同?
- 密钥怎么管理?怎么轮换?
12)可观测边界
- 出问题你要在5分钟内定位,最少需要哪几条日志?
- 哪些字段绝对不能打?
系统一定会失败,区别只是:你有没有提前准备好。
接口与契约:接口不是函数签名,而是承诺。
你要说清楚:
- 你给我什么
- 我保证什么
- 出错我怎么说
模块化的本质:
模块不是为了好看,是为了出事时只炸一块。
产出:边界卡集合(5-12张)。
Step 10:定错误分层规则
你做什么:定义错误在哪一层被处理。
给AI的指令:
把每条调用线的错误,标注在哪一层被处理。
规则:
- 底层:把原始错误转成"失败分类"
- 中层:决定策略(重试/补偿/兜底)
- 上层:对外表达(状态码/错误码/提示/不泄露细节)
输出错误分层表:
失败分类 → 内部错误码 → 对外错误码/提示 → 日志等级 → 处理策略
错误三层法则:
| 层级 | 职责 | 例子 |
|---|---|---|
| 底层 | 把原始错误转成分类 | ”数据库连不上” → DatabaseError |
| 中层 | 决定怎么办 | 重试3次,还失败就标记待处理 |
| 上层 | 给用户看什么 | 返回500 + “服务繁忙” |
铁律:错误永远不要一口气从最里面冲到用户脸上。
产出:错误分层表。
Step 11:定日志策略
你做什么:定义关键日志点。
给AI的指令:
每一条请求/任务必须有:
1. 请求ID(贯穿全链路)
2. 关键输入摘要(不记敏感信息)
3. 关键步骤点(到哪一步了)
4. 错误栈 + 上下文(失败时)
规则:
- 成功少打(只打关键节点)
- 失败必打(信息完整)
- 同一错误只打一次(避免刷屏)
- 敏感信息不落盘
你不是为了"全面监控",你是为了:出事5分钟内定位。
所以只问一句:"出问题时,我第一眼看什么?"
产出:日志事件表(事件名 → 必带字段 → 级别)。
Step 12:写架构文档
你做什么:让AI把前面所有设计整理成一份架构文档,包括决策记录。
系统不是被bug杀死的,是被没人知道当初为什么这么做杀死的。所以架构文档必须包含决策记录。
给AI的指令:
把前面的设计整理成架构文档,包含:
1. 需求概述:一句话需求 + 谁用/频率/后果
2. 不做清单
3. 不变量(INVARIANTS)
4. 系统骨架图
5. 责任边界表
6. 数据模型 + 状态机
7. 技术选型及理由
8. 目录结构及职责 + 模块所有权
9. 边界卡集合(按12类分组)
10. 错误分层表
11. 日志策略
12. 决策记录(DECISIONS)
格式:决策是什么 | 当时的约束 | 放弃了什么 | 未来什么时候可能推翻
这份文档的用途:
- AI 后续编码时可以参考
- 新人接手时可以快速理解
- 自己回头看时不会懵
- 6个月后你还能接手
- AI不会反复"建议你换方案"
产出:架构文档(一份 Markdown 文件,包含决策记录)。
架构设计阶段完成:到这里,系统的骨架、边界、错误处理、日志策略全部定死,并且有文档记录。可以开始写代码了。
阶段二:编码实现
Step 13:定AI使用边界
你做什么:明确AI可以做什么、不可以做什么。
你现在最大的新风险不是技术,是AI过度参与。
你要明确:
AI可以做什么:
- 生成代码
- 列方案
- 补测试
- 重构实现细节
AI不可以做什么:
- 决定边界
- 引入新概念
- 改不变量
- 跨边界调用
- 新增目录或技术(除非先问你)
铁律:
AI 不拥有任何”最终决定权”
产出:AI使用规则(写给自己,也写给AI)。
Step 14:开始编码
你做什么:告诉AI可以写代码了,但必须遵守前面的规则。
给AI的指令:
现在开始编码,但必须遵守:
- 不允许新增目录(除非先问我)
- 不允许新增技术(除非先问我)
- 不允许跨边界调用
- 不允许自创错误处理方式
- 不允许违反不变量
- 必须按边界卡和错误分层表实现
如果需要变更上面任何一条,先停下来问我。
AI做什么:按图施工。
你检查(边写边看):
- 有没有偷加复杂度?
- 有没有跨目录引用?
- 错误是不是在对的层处理?
- 有没有违反不变量?
架构退化预警:
你要提前知道:什么时候该停下来重构。
常见退化信号:
- 同一个判断出现3次以上
- 目录边界开始被”临时穿透”
- 错误开始随意往上抛
- 日志开始”什么都打”
- 新功能必须改5个地方
规则:
不是”感觉该重构”,而是命中信号才动
技术债为什么一定会出现:
因为:
- 需求变
- 时间有限
- 人会换
成熟不是消灭技术债,而是:
知道哪是债,什么时候该还。
阶段三:验收上线
Step 15:代码验收
你做什么:检查。
验收清单:
1. 有没有偷加复杂度?
2. 有没有跨目录?
3. 错误是不是在对的层处理?
4. 日志够定位问题吗?
5. 不做清单有没有被破坏?
6. 不变量有没有被违反?
AI做什么:自查并输出报告。
给AI的指令:
对照前面的规则自查:
1. 目录结构是否和架构文档中的目录职责表一致?
2. 边界处理是否和边界卡一致?
3. 错误处理是否和错误分层表一致?
4. 日志是否和日志策略一致?
5. 有没有违反不变量?
输出检查报告,列出不一致的地方。
Step 16:上线检查
上线前必须确认:
发布与回滚:
- 能上线
- 能撤回
- 能不改数据就撤回
架构直觉:
不能回滚的设计,等于不准出错。
配置:
- 不同环境不一样
- 密钥不能写死
- 行为可调
测试:关键边界至少3个测试
- 正常场景
- 典型失败
- 重复执行(幂等性)
Step 17:定停止线
上线后要有的护栏:
停止线清单(什么时候必须停下来):
这是防止系统崩盘的最后一道闸。
必须停下来的情况:
- 发现违反不变量
- 发现边界说不清
- 发现错误无法分类
- 发现日志无法定位问题
- 发现”先写了再说”
规则:
一旦触发停止线,禁止继续写代码
产出:停止线清单(贴在项目 README)。
三、几点心得
架构不是图,是决策
架构不是画一张漂亮的图,而是一组选择:做什么不做什么、复杂度放在哪、边界在哪里。图只是把这些决策可视化。
人和AI的分工很清楚
- 人:定边界、定规则、做选择、喊停
- AI:列选项、生成代码、按图施工
AI不拥有任何”最终决定权”。
简单是最难的
早期失败的常见原因不是做少了,而是做太多。好的设计是:宁可啰嗦、宁可重复、宁可慢一点、宁可写死。
边界=契约+失败策略
任何边界都必须写两件事:
- 契约:进来什么、出去什么
- 失败:错了怎么办、谁来处理
你不需要一次想完所有细节,你只需要把每条边界都变成一张”边界卡”。你只要把边界卡做全,系统就很难崩。
你不需要想全,需要知道什么时候该停
架构不是一次想全所有细节,而是每一步冻结一个决定,然后在关键节点不被AI带跑。
遇到新问题你不需要慌,因为你只要做两步:
- 这属于12类边界里的哪一类?
- 用边界卡模板把契约和失败策略填出来
你不靠记忆,你靠”分类 + 模板”。
掌握了这套方法,你会发现:架构不是玄学,是流程控制。你不需要想全所有细节,只需要在关键节点做好决策,然后让 AI 去执行。