给一个已成型的项目画结构图:不读一行代码,画出「有哪几块、谁用谁、谁在改同一份数据」
你感觉到的「修 A 出 B、越改越多」,绝大多数不是你不会改,而是同一份东西被好几处同时改。这篇不教你读懂代码——读代码是 AI 的活。它教你把这三张表画出来,再用「改一下、看会怎样」验它准不准。
📅 更新于 2026-09-16
0030 秒速览:三句话、起手动作、以及你手上必须有什么
如果只记三句话
① 结构图回答的不是「代码怎么写的」,是三个关于关系的问题:有哪几块、谁用谁、谁在改同一份数据。你要判断的是关系对不对,不是代码对不对——这是两个完全不同的活。
② 一个东西被多少处「用」不重要,被多少处「改」才重要。全站样式被三十几个页面用,但它只有一份、只有一个地方能改,所以它从来不给你惹麻烦。反过来,同一份东西存了三十几份、你还得手动让它们保持一致——那才是你「越改越多」的来源。
③ 你不用读懂代码,就能验这张图准不准:改一个小东西,看实际有几处跟着变。变了的地方比图上多,就是图画漏了;比图上少,就是图多画了。你不需要知道为什么变,只需要知道会不会变。
起手动作:读完 60 秒内,你要做的第一件事
打开你手上最小的那个半途项目(烂尾的、你看不懂的,都行),让 AI 编程助手(能读你电脑里文件的那种 AI 工具)读一遍它,然后问一句话(你打给 AI 的那段话,行业里叫「提示词」):
# 这是一段提示词,整段复制,粘给 AI 编程助手
先不要解释任何代码。把这个项目分成 5 到 15 块,每块给我:
1) 一个中文名字,不要用行业词
2) 一句话:它负责什么
3) 它包含哪些文件或目录,列路径
不确定的地方标注「不确定」,不要猜。
但在按下回车之前,先做一个小动作:拿张纸,写下你猜它会列出几块。然后发送,对一下差多少。
为什么要先猜?因为这一猜,就把这件事从「听 AI 汇报」变成了一次实验。你的猜测和它的答案之间的差距,就是这个项目里你还没看见的那部分。第 6 节会把「先猜、再改、后对账」这套动作拆开讲——它是全文最值钱的一段,而你现在做的正是它的第一步。
做这个动作之前,你手上必须有什么
1. 一个已经存在的项目目录——哪怕烂尾、哪怕你一行代码都看不懂。这篇文章不会教你从零建项目。它的全部前提是「已经有一堆东西在那儿了」。
2. 一个能读你本地文件的 AI 编程助手——注意是「能读文件」的那种(Claude Code、Codex、Cursor 这类装在电脑上、能看见你项目目录的工具),不是网页聊天窗口。只开一个网页对话框没用:它看不见你的文件,只能听你转述,而你转述不出来的恰恰就是你不懂的那部分。
手上没有项目?那这篇文章你照样现在就能练——全篇的例子用的是 ai-teach 这个站本身,也就是你正在读的这个网站。它就在你手上、你天天看、而且它小到你几分钟就能走完一圈(第 5 节)。等拿它练完手,再回去开你那十几个烂尾项目里最小的那一个。
数字先给量级
这篇里会反复出现几个数字,它们都来自这个站自己,而且你随时可以自己数一遍(命令在最后一节):
| 这个站里有什么 | 数量 | 为什么这个数字值得记住 |
|---|---|---|
| 全站样式(决定所有页面长什么样的一份文件) | 1 份 | 被三十几个页面同时用,但从不出事——因为只有一处能改它 |
| 行为脚本(让按钮能点、目录能开的那份程序) | 1 份 | 同上。这两个是「一对多」关系里健康的样子 |
| 页面顶部那段「先决定用深色还是浅色」的小脚本 | 三十几份 | 同一段文字被逐字抄进了每个页面。改它必须一次改三十几处 |
| 校验脚本(一个替你做检查的程序) | 1 个 | 它不认识你的意图,只核对「几处数字对不对得上」 |
注意第一行和第二行,跟第三行的差别:都是「一个东西被很多地方用」,但第一二行只有一处能改,第三行有三十几处能改。这个差别就是这篇文章的全部要害。
01先破一个错想:这件事不是「读懂代码」
你可能已经这样想过了
「画结构图,那得先看懂代码吧。我看不懂代码,所以这件事我做不了。」
这个想法非常合理,而且它合理得值得说清楚为什么——因为如果它是个明显的蠢念头,你不会被它挡住这么久。
它有三个看起来很硬的理由:
所以你自然推出:画它需要懂代码。但这只说明那些人懂代码,不说明这件事要求懂代码——就像你见过的每份体检报告都是医生写的,不代表你不能自己量个血压。
「服务层」「中间件」「解耦」——这些词确实像门槛。但它们不是门槛,是行话。行话可以被替换成人话,门槛不能。这篇文章会证明:换成人话之后,图还是那张图,而且更有用。
那些工具(画图的软件、各种图例规范)都在解决「形状怎么摆」,前提是你已经知道要摆什么。而你的问题在更前面一步:我怎么知道要摆什么?没人回答这个问题,于是你只能猜「大概需要先读懂代码吧」。
真相是:你要画的关系,AI 读代码就能给你
把这件事拆开,其实是两个人的活:
「文件 A 里出现了文件 B 的名字,说明 A 用了 B。」
「这份数据在 C、D、E 三个文件里各存了一份。」
这事它比你快一万倍,而且它不嫌烦。你完全不必自己干。
「它说 A 用了 B——那我把 B 改一下,A 真的会跟着变吗?」
这件事 AI 做不了,因为它只能读,不能改。而你能改。
这里有个关键区别,值得单独说一句:AI 是从「写下来的文字」推关系,你是从「改一下之后真的发生了什么」看关系。文字会说谎——某个文件里写着「用到了订单模块」,但那段代码可能从来没被执行过。行为不会说谎。
所以你的位置不是「不如 AI」,而是补上了 AI 唯一缺的那一环:AI 给你一张申请的图,你负责验它。验完,这张图才从「AI 说的」变成「你知道的」。
一个类比:这张图像大楼的消防图
消防图不告诉你墙用什么材料、钢筋多粗、线路怎么走——那是施工队的事。它只告诉你三件事:
1. 有几个房间(对应表一:有哪几块)
2. 哪扇门通向哪个房间(对应表二:谁用谁)
3. 哪条走廊是唯一的出口——堵了就全都出不去(对应表三:谁在改同一份数据)
这三件事,一个不懂建筑的人也能看懂、也能验:指着门问「这扇门真的通那边吗」,走一遍就知道了。
这个类比的边界在哪:消防图不会告诉你「这面墙能不能拆」。同样,本文这张图不回答「这段代码写得好不好」——它只回答一个问题:我要动的这个东西,会牵动什么。你要是拿它去问「我这项目的整体设计优不优雅」,那是我误导了你。
为什么「关系」比「代码」更要紧
回到你真实的那个感受:「修 A 出 B,越改越多」。
这件事几乎不会发生在「代码写错了」的时候。代码写错了,你改那一行,它就对了。它发生在你以为你在改一个地方,其实你同时改动了另一个地方的命根子的时候。
而「另一个地方」在代码里通常长得跟你改的东西毫无关系——它可能是另一个文件、另一个页面,甚至另一份配置(存设置的那份文件)。你从字面上看不出它们连着。这就是为什么你需要一张图:图上画的就是那根看不见的线。
02表一 · 有哪几块:把项目分成 5 到 15 块
这张表长什么样
| 块的名字(用人话) | 它负责什么(一句话) | 它包含哪些文件 |
|---|---|---|
| 读文章的界面 | 把一篇文章显示出来,能滚动、能开目录、能切深浅色 | 所有页面文件本身 |
| 全站外观 | 决定每个页面长什么样:字体、颜色、间距 | 样式那份文件 |
| 交互行为 | 让按钮能点、目录能开、搜索能用 | 脚本那份文件 |
| 首页列表 | 把所有文章排成卡片,让人点进去 | 首页文件 |
| 生成器 | 按规矩生成新文章、生成卡片、检查有没有出错 | 生成器那一整个目录 |
就长这样。没有一行代码,没有一个你听不懂的词,长度不超过一屏。
最容易搞错的一处:文件列表不等于「块」
src/ 下面有 components/、utils/ 这些文件夹……照抄一遍目录树,一行一层,画了四十行。
问题:目录结构回答的是「文件放在哪」。可文件会搬家——今天放 utils/ 的下个月挪到 lib/,而「它负责什么」没变。你抄下来的是会过期的信息。
把「改一个功能时要一起动的那些文件」圈成一块。块的名字来自它负责什么,不是来自它放在哪个文件夹。
判断法:改这个功能的时候,你会同时打开哪几个文件?那几个就是一块。
怎么判断一块划得好不好
这一块能不能只用一句话说清「它负责什么」,而且这句话里不需要提到别的块的名字?
能 → 这块划得干净。
不能,比如你非得说「它负责给订单那块准备数据」——那它跟「订单那块」要么该合并,要么它们的边界划错了,得重划。
这条检验你完全可以自己做,不需要懂代码。你需要的只是「这句话读起来别扭吗」的语感。
块的数量:5 到 15 块
- 少于 5 块:说明一块里塞了太多东西,等于没分。这时候你仍然不知道「改这个会牵动什么」——因为那一块里的东西彼此毫无关系,却被你并成了一块。
- 多于 15 块:说明你在按文件分,不是在按职责分。或者这个项目真的很大——那也别一次画完,只画你现在要动的那一块,和它周围两三层。
这里有个来自画图规范的建议,可以直接拿来用:C4 模型(一套公开的软件结构画法)明确说「你不需要画满所有层」——它建议多数团队画到「系统上下文 + 容器」这两层就够了,再往下是给要改代码的人看的。来源见文末。
翻译成你的判据:画到「再往下画就需要懂代码了」那一层,就停。那一层之上的所有内容,都是你该管、也管得动的。
03表二 · 谁用谁:每块被别人从哪几个口子用
这张表长什么样
| 谁 | 用了谁 | 从哪个口子用(具体到文件或功能名) |
|---|---|---|
| 首页列表 | 文章页面 | 卡片上的链接,点一下跳过去 |
| 文章页面 | 全站外观 | 页面顶部引一下那份样式文件 |
| 文章页面 | 交互行为 | 页面底部引一下那份脚本 |
| 生成器 | 文章页面 | 直接生成出这些文件 |
| 校验脚本 | 首页列表 | 读出每张卡片的日期,跟文章里的日期比 |
为什么要画这张表:它就是「改动的影响半径」——改了它,波及到哪一圈
这张表回答一个问题:我把 B 改了,谁会跟着疼?
行业里管「A 用了 B」叫 A 依赖 B,管两组东西「一处变了、另一处必须跟着变」这种关系叫耦合。这两个词你以后会一直撞见,现在你知道了:它们说的就是这张表上的箭头。箭头指向你的时候,你就在影响半径里。
这张表最大的用处是看方向:
A 用 B,B 用 C。你要改 C 的时候,知道自己得去看看 A 和 B——数得清,跑得完。
更健康的是「一个东西被很多处用,但只有一处能改它」:这个站的样式文件就是这样。三十几个页面都引它,可它只有一份,改它就等于改全站,不会有「漏改一个」这种事。
A 用 B,B 也回头用 A。这时候你改 A 会影响 B,改 B 又会影响 A——你没法只改一边。
这是「越改越多」最典型的产地:你以为在给 A 打补丁,其实同时在给 B 制造新问题,然后你去修 B,又回头碰 A。
最容易搞错的一处:把「名字出现了」当成「真的用了」
AI 是从文字找关系的,所以它容易把这两种情况混起来:
「文件 A 里出现了 B 的名字」——这只是文字上的引用。
「A 真的会走到 B 那条路上去」——这才是真的用了。
差别在哪?一个项目里经常有一段代码写着「如果出错,就调用紧急处理流程」——但那个错误从来没发生过,所以那段紧急处理流程一次都没跑过。它在图上画着一条线,实际上那条线是死的。
这正好说明:图上有一条线,不等于那条线活着。这就是为什么你后面必须用「改一下看会怎样」去验(第 6 节)。
所以在要提示词的时候,得逼 AI 把「确定的」和「疑似但没确认的」分开列——第 7 节的第二段提示词就是干这个的。
这张表要画多细
判据:画到「你改之前能一眼看出该去哪几个地方看一眼」就够了。
不要试图画全。你不需要知道 A 里的第 37 行调用了 B 里的第 12 行——你需要知道的是「我要动 B,所以我得先打开 A 看一眼」。
05最小例子:拿 ai-teach 这个站走一遍三张表
为什么用这个站:你正在读它。它小到几分钟能走完一圈,而且每一处结论你都能自己核对——文末给了核对命令。
先看表一:这个站有哪几块
| 块的名字 | 它负责什么 | 它包含哪些文件 |
|---|---|---|
| 文章页面 | 把一篇文章显示出来,能滚动、能开目录、能切深浅色 | 三十几个页面文件 |
| 全站外观 | 决定所有页面长什么样 | style.css 一份 |
| 交互行为 | 主题按钮、手机上能把目录拉出来的那个开关、搜索、排序、复制代码按钮 | theme.js 一份 |
| 首页列表 | 把文章排成卡片、支持搜索和筛选 | index.html |
| 生成器 | 生成文章、生成卡片、检查有没有出错 | 生成器目录里的说明书、题材表、风格规范、校验脚本 |
| 站点配置 | 存站名、副标题、以及「这个站写给谁看」 | learn.config.json |
六块。注意「全站外观」和「交互行为」各只有一份文件——这是好事,先记住,下面会用上。
再看表二:谁用谁
| 谁 | 用了谁 | 从哪个口子用 |
|---|---|---|
| 首页列表 | 文章页面 | 每张卡片是一个链接,点一下跳过去 |
| 文章页面 | 首页列表 | 页面右下那个「返回目录」按钮 |
| 文章页面 | 全站外观 | 页面顶部引一下 style.css |
| 文章页面 | 交互行为 | 页面底部引一下 theme.js |
| 首页列表 | 全站外观、交互行为 | 同上,首页也引这两份 |
| 交互行为 | 首页列表 | 脚本会读出每张卡片上的标题、简介、日期、难度标签——用来做搜索和排序 |
| 生成器 | 文章页面、首页列表、站点配置 | 生成它们,并读配置里的站名和读者画像 |
| 校验脚本 | 文章页面、首页列表、站点配置 | 读出几处数字,互相核对 |
箭头不少。但看方向:它们基本是从上往下的——「生成器」和「校验脚本」站在最上面,读下面所有东西;下面的东西之间只有几条水平线。没有「互相回头指」的死结。
最后看表三:这个站里,谁在改同一份数据
这是全篇的核心。我把这个站里真实存在的三处列出来,按「改一处会牵动几处」从多到少排:
| 这份东西是什么 | 存了几份 | 谁在写 | 我改一处、忘了别处,会出什么事 |
|---|---|---|---|
| 页面顶部那段「先决定深浅色」的小脚本 | 三十几份 (每个页面各存一份逐字相同的副本) | 人手改 | 什么都不报错。只有你漏改的那几篇,打开时会闪一下白。校验脚本能抓到——但它抓的方式是「拿每篇的那段跟首页那份比」,所以真正的规则是:改它必须一次改三十几处 |
| 首页卡片上的更新日期 | 2 份 (文章里一份、卡片上一份) | 生成器写 | 校验脚本直接失败,并明确告诉你「卡片上的日期和文章里写的对不上」。这是会喊疼的那种 |
| 网站名字 | 2 份 (配置里一份、首页上显示一份) | 人改配置 | 校验脚本失败,说首页上找不到配置里的那个站名 |
然后,把第四行补上——这个站里不属于这张表的东西:
| 这份东西是什么 | 存了几份 | 谁在写 | 改一处会怎样 |
|---|---|---|---|
全站外观(style.css) | 1 份 | 人手改 | 改一处,所有页面同时跟着变。不会漏,不会不一致。这是你想要的样子 |
交互行为(theme.js) | 1 份 | 人手改 | 同上 |
现在把这两张表并排看——这就是这篇文章想让你亲眼看到的东西:
样式文件:被三十几个页面用,只有 1 处能改 → 从来不给你惹麻烦。
主题引导脚本:也被每个页面用,但有三十几处能改 → 改一次要改三十几遍,漏了就静默出错。
它们被「用」的规模几乎一样。差别只在能被「改」的地方有几个。
这个站真的栽过一次
2026-09-16,这个站为了在首页加一张卡片,改完发现要回滚(回滚就是把改动退回去、恢复成改之前的样子)。
表面上看,那只是「加一个卡片」。但按上面这两张表拆开看,加一张卡片要动的是:
这是你想得到的那一处。
校验脚本会核对这个数字和实际文章数是否一致。忘了改 → 直接失败。这是你没想到的第一处。
卡片是按日期从新到旧排的,插错位置 → 校验脚本报「主页非按日期倒序」。这是你没想到的第二处。
两处数字必须相同,校验脚本逐个比。这是第三处。
超了会把整行卡片撑高,网格散掉。校验脚本按字符数拦。这是第四处。
「加一个卡片」——本来以为是一处,实际是五处。
这正好是那个信号:一个看起来很小的改动,要动的地方超过三处。出现这个信号的时候,你遇到的不是「一个 bug」(bug 就是程序出错的地方),是「结构问题」——继续埋头改只会越改越多,正确动作是停下来回头看结构。
它之所以好,是因为有一道自动检查盯着它。没有那道检查的话,它就变成第一行那种「静默出错」了。
这一点可以直接搬到你的项目里:对于那些不得不在两处各存一份的东西,至少要留一个能自动对账的检查。没有检查的复制,等于埋雷。
06不懂代码,怎么知道图画对了:预测 → 扰动 → 对账
这是全文最值钱的一段。前面三张表都是「AI 给你的」——这一段才把它变成「你知道的」。
先说清为什么需要这一步
AI 给你的表,是从文字里推出来的。而文字有两个毛病:
- 它可能写着一段从来不跑的代码(上一节的「那条线是死的」);
- 它可能漏掉一段绕来绕去的线——两个文件通过第三种方式连在一起,字面上看不出来。
所以「AI 给了三张表」不等于「图上是对的」。而好消息是:验证它,恰恰不需要你懂代码。
方法只有三步:预测 → 扰动 → 对账
一个字、一个日期、一个颜色、一张卡片——越小越好。所谓「能退回来」,是指这个项目能撤销你的改动、回到上一版(如果你用 git 管着——git 是一种记录每次改动、随时能退回上一版的工具,退回去的命令就是 git checkout;不确定的话,先复制一份整个文件夹,改那份副本)。
这个改动不必你亲自动手。你完全可以告诉 AI:「把首页第三张卡片上那个日期改成 2026-01-01」——它去改,你负责看结果。这个方法里你是观察者,不是操作者;动手那部分可以外包给 AI,只有「预测」和「对账」必须是你。
具体到「哪个页面、哪个数字、哪一块」会跟着变。这一步是整个方法的核心,也是唯一需要你动脑的地方——不要跳过它。没有预测,后面就无从对账,你只会得到一句「哦,好像变了」。
打开项目、刷新页面、跑一遍那个自动检查——用一切你能用的方式观察。不需要看懂任何代码,只需要看「什么跟着动了」。
对账:三种差,各自说明什么
| 你的预测 | 实际结果 | 这说明图上哪里错了 |
|---|---|---|
| 预测它会变 | 真的变了 | 图上这条线是对的。你可以信它了 |
| 预测它会变 | 没变 | 图上多画了一条线。你以为这两处有关,其实无关——多半是那段代码从来没被执行过 |
| 没预测到 | 却变了 | 图上少了一条线。——这就是你要找的东西,也正是你「修 A 出 B」的根源 |
| 没预测到 | 变了,而且什么都没报错 | 最危险的一类。它不是图上少了一条线的问题,是「这条线还带着一个静音开关」——它在悄悄让两处说的不一样 |
这个方法为什么不需要你懂代码
你不需要知道「为什么」会变,只需要知道「会不会」变。
「为什么」是因果关系,那需要读懂代码——那是 AI 的活。
「会不会一起变」是共变关系,你改一下、看一眼,就知道了。这是你的活。
这件事在行业里有正式名字,叫影响分析(change impact analysis)。它的标准定义是:「找出一次改动可能带来的后果,或者估计为了完成这次改动还需要改什么。」专业人士用工具做这件事(能自动把所有连线画出来的那种),你用一次真实的改动做。名字一样,问的是同一个问题:改了它,还有什么要跟着改?来源见文末。
把它变成数字:改一处,牵动几处
对账完之后,数一下:为了这一个改动,我一共动了几个地方?
「改一个小东西要动三处以上」——这是你能拿到的最有用的一个信号。它不要求你懂代码,只要求你数数。
现在就能做的一次实验(拿这个站)
这个站里有两处「会喊疼」的耦合,都配了自动检查。你可以直接做一次:
# 第 1 步:先数一下,现在有几处存着同一段脚本
# ("ln-theme" 是那段脚本里独有的一个词,用它来把存了副本的文件全找出来)
grep -l "ln-theme" learn/*.html | wc -l
# 你会看到一个三十几的数字 —— 每一份都是一个页面里存的那段副本
# 第 2 步:只改一处(把某一篇文章的那份改坏一个词)
# (cloudflare-overview.html 是这个站里随便一篇文章,换成你看到的任意一篇都行)
sed -i '' 's/prefers-color-scheme: light/prefers-color-scheme: dark/' learn/cloudflare-overview.html
# 第 3 步:让那个自动检查跑一遍,看它会不会告诉你
bash .agents/skills/learn/check.sh learn/cloudflare-overview.html
# 第 4 步:撤回,把项目恢复到改之前
git checkout learn/cloudflare-overview.html
它们是要在终端里跑的(终端就是电脑上那个只能打字的黑色窗口,macOS 上按 Command + 空格 搜「终端」就能打开)。打开后先让终端进到项目目录里,再一条一条粘进去、按回车。
不想碰终端?完全可以。把这些命令直接粘给你的 AI 编程助手,说「帮我在这个项目里跑一下这几条,把结果告诉我」——它替你跑,效果一样。你要的是「改一下、看会怎样」这个动作,不是「学会打命令」。
第 3 步会失败,并且明确告诉你:那段脚本跟首页那份对不上了。
你刚才做的,就是一次完整的「预测 → 扰动 → 对账」:你预测「改这一处会出事」,扰动了一处,检查替你确认了。而你全程没有读一行代码。
这个实验之所以安全,全靠第 4 步——改完能退回去。
所以这条方法有一条铁律:只扰动你能撤销的东西。《怎么把「批准方案」换成「验收结果」》那篇里有一条判据也是这个意思——判断不了哪个对的时候,选「错了更容易改回来」的那个。用在这里就是:拿能复制、能撤销的部分去试,不要去碰你没法恢复的东西(比如线上的真实数据、别人正在用的东西)。
验到什么程度可以停
不要想验完整张图——那是不可能的,也没有必要。判据是:
对于你「这次要动的那个地方」,图上那条线你验过了,就够了。
你不需要验证整个项目。你需要的是——在你要动手之前,那个特定位置的连线是真的。图是为这一次改动服务的,不是为了一次性把项目看透。
07可复制的提示词:三张表各一段,外加一段追问
下面四段话可以整段复制、粘给 AI 编程助手。注意它们的设计意图——这些句子不是客套,每一句都在堵一个具体的漏洞。
第 1 段:要表一(有哪几块)
先不要解释任何代码,也不要贴代码。把这个项目分成 5 到 15 块。
每块给我四样东西:
1) 一个名字,用中文、用日常说法,不许用「服务层」「中间件」这类行业词
2) 一句话说清它负责什么。这句话里如果必须提到别的块才能说清,请直接标注「和 X 块分不开」
3) 它包含哪些文件或目录,列具体路径
4) 改这一块的时候,通常还要同时动哪几个文件
不确定的地方标「不确定」,不要猜。最后用一句话告诉我:哪一块是最大的。
这几句分别在堵什么:「不要贴代码」堵它甩一堆你没用的东西;「不许用行业词」堵它用行话糊弄;「必须提到别的块就标注」就是你第 2 节那条「一句话检验」的自动化;「改这块还要动哪几个文件」是在逼它按「一起变」来分块,而不是按目录分。
第 2 段:要表二(谁用谁)
列出这个项目里「块与块之间的使用关系」,一行一条,格式是:
A 用了 B —— 从 B 的哪个口子用的(具体到文件名或功能名)
只列你确认存在的关系。如果你只是「在 A 里看到了 B 的名字」
但找不到真的会执行到的地方,不要混进来,
单独列一张「疑似、未确认」的清单给我。
最后额外回答一个问题:这些关系里,有没有互相指的(A 用 B,B 也用 A)?
如果有,单独列出来 —— 这是我最关心的一组。
关键在中间那句:把「确定的」和「疑似没确认的」分开。这正是第 3 节说的那个坑——「名字出现了」不等于「真的用了」。最后那句是让它主动把「互相指」的挑出来,因为那是麻烦最集中的地方。
第 3 段:要表三(谁在改同一份数据)——最重要的一段
停。现在只回答一个问题,不要讲别的:
这个项目里,有哪些「同一份东西存在不止一处」或者「同一份东西被不止一处改写」的地方?
不要只找数据库和配置文件。任何一份"被复制过"或"被好几个地方碰过"的东西都算,
包括:同一段代码被抄进好几个文件、同一个数字写在好几个地方、
同一条规则在前后两端各写了一遍、同一个说明文档里的内容和代码对不上。
每一处给我五行:
1) 这份东西是什么 —— 用人能懂的说法,比如「首页上显示的更新日期」
2) 它总共在几个地方各存了一份 —— 给我一个数字
3) 谁负责写它 —— 是自动生成的,还是人手改的
4) 谁读它 —— 哪些文件或功能依赖它
5) 如果我只改了其中一处、忘了别处,会出什么事 ——
请明确告诉我是「会报错」还是「不报错、但结果已经不对了」
最后按「改一处会牵动几处」从多到少排序,第一行应该是最危险的那个。
如果一处都没有,直接说没有,不要凑。
这段里有三个地方是故意的:
- 「不要只找数据库和配置文件」——否则 AI 会给你一张标准的数据库表清单,而你真正的麻烦在别处(比如那段被抄了三十几份的脚本)。后面那串举例就是在给它划范围。
- 第 5 行必须回答「报错还是不报错」——这是整段最值钱的一问。会报错的耦合只是烦人;不报错的耦合才是你真正需要知道的那个(第 4 节解释过为什么)。
- 「如果一处都没有,直接说没有」——这句是防它硬编。你问它「有哪些问题」,它天然倾向于给你找出几个来,哪怕没有。
第 4 段:它开始甩代码 / 说行话的时候,用这段
停。不要贴代码,也不要用「解耦」「抽象」「服务层」这类词。
用一句话回答我:这段代码是「谁改了什么」?
如果不能用一句话说清,就告诉我「说不清,因为……」。
这一段你会在整个过程中反复用到。它不是防 AI 犯错,是在防你自己糊弄自己——「我看不懂但好像很专业」这种状态下点下去的那个「好的」,是你后面所有麻烦的起点。允许 AI 说「说不清」,比逼它给一个你听不懂的答案有用得多。
用这些提示词的时候,怎么读它的回答
08画完之后怎么用:改之前看图,改完更新图
改之前:三个问题,答完再动手
这就是这张图存在的全部意义。在你要改任何东西之前,先问三个问题——三张表各出一个:
| 问什么 | 用哪张表 | 答不上来的时候,说明什么 |
|---|---|---|
| 我要改的这东西,属于哪一块? | 表一 | 你还没找到地方——先别改,先找 |
| 有谁在用这一块? | 表二 | 你不知道改完要检查什么——这正是「修 A 出 B」的入口 |
| 这份东西还在别处存着吗? | 表三 | 最危险的一种。你极可能改了一半、漏了另一半,而且它多半不报错 |
三个都答得上来,你再动手。答不上来的时候去问 AI——问法就是上一节那四段话。
改完:更新图,而且只改那几行
因为没有图的时候你会小心,有图的时候你会信它。你照着一条早就失效的线去做判断,还不如没有。
所以图要跟着改。但更新图不等于重画——那太重了,重到你第二次就不会做。最小动作是:
- 这次改动牵动了哪几条线?只改那几行。
- 如果发现了一条以前图上没有的线(「原来改这里还会影响那里」),把它补上——你刚刚花代价学到的东西,不记下来就白付了。
- 把图上的日期改成今天。
把它放成一份文件,放在项目里
不要留在聊天记录里,也不要只存在脑子里。写成一份文件放进项目目录,名字随便(结构图.md、项目地图.md 都行),内容就是那三张表加一个日期。
两个好处,都很实际:
- 下次你忘了,能查。你手上有十几个项目,隔两个月回来,你不会记得任何一个的细节。
- AI 也能读它。下次你让 AI 改这个项目的时候,它自己会看到这份文件——于是它做的判断会带着这些关系,而不是从零重新猜一遍。
「更新于 2026-09-16」——它告诉你这张图是什么时候为真的。看到一份没有日期的图,你的正确反应是:不知道它现在还准不准,得当它不准。
09什么时候别做这件事
这一节和前面同等重要。前面教你怎么做,这一节防你做过头——而做过头这件事,会让一张好方法变成新的负担,然后你就再也不会用它了。
四种别做的情况
| 什么时候 | 为什么别做 | 改做什么 |
|---|---|---|
| 你能一口气讲完这个项目 | 如果你不看任何东西、用五句话就能说清这个项目有哪几块,那这张图对你是零信息——你脑子里已经有了 | 直接改。图是给「说不清」的项目用的 |
| 只是修一个已经知道改哪的 bug | 这是个真 bug,不是结构问题。先画图再修 = 用大炮打蚊子,还容易把自己绕晕 | 直接修。修完如果发现「改了三个地方才修好」,那时候再回头看结构 |
| 项目大到你一次画不完 | 贪全的结果是画了三小时、画出一张没人看得懂的图,然后放弃 | 只画你现在要动的那一块,加它周围两三层。图可以一点点长出来 |
| 你只是想「了解一下这个项目」 | 没有具体要改的东西时,画出来的图没有验证对象——你没法用「改一下看会怎样」去验它,于是它只是一份好看的文档 | 等你要动手的时候再画。这张图的用途只有一个:回答「我改这个会牵动什么」 |
别做过头:长得像的文字,不等于同一份知识
这是「谁在改同一份数据」这张表最大的误用,值得单独讲。
你学会表三之后,会很想把「所有重复的东西」都合并掉。但其中有一部分不该合。
项目里有两个地方都写着「满 200 包邮」。你把它们合并成一处共用。
三个月后,运营要求「只在老客户活动里包邮,日常下单不包邮」——你发现自己把两件本来会朝不同方向变的事情焊死在了一起了。拆开比当初复制一遍还麻烦。
这种「长得一样、其实是两件事」的重复,行业里叫巧合的重复。
如果这两处将来会因为不同的理由而变 → 让它们各自独立。
如果它们必须永远一样、不一样就是出错 → 合并成一处。
一句话判据:「如果这两处变得不一样了,那是个 bug 吗?」是 → 合并。不是 → 分开。
这个区分不是我编的:前面说的那条「每条知识只留一份」的老规矩,配套就有一条明确的提醒——「巧合的重复」不应该被当成重复来处理,硬合并反而会造出错误的抽象。来源见文末。
表三的第一价值是让你知道它在那儿——改的时候记得两边都改。合不合并是第二步的决定,而且要看上面那条判据。
先知道,再决定。别一上来就动手合并——那正是「越改越多」的另一种走法。
还有一个反向的边界
这个方法也有它看不见的地方。它只看「关系」,不看「好坏」。
一张画得完全正确的结构图,可能对应着一个写得很烂的项目,也可能对应着一个写得很好的项目——图上看不出来。所以:
- 它不能回答「我该不该把整体结构翻新一遍(行业里叫重构)」「这个项目的设计好不好」;
- 它不能代替测试——它能告诉你「改这里可能牵动那里」,但不能告诉你「那里现在到底对不对」;
- 它只能回答一个问题:我要动的这个东西,会牵动什么。
知道一个方法管什么、不管什么,你才不会在它失灵的时候以为是自己做错了。
10五个一定会撞上的误解
这五条是你真做的时候会遇到的,不是假想的。
11一页纸速查
三张表,各一句话
| 表 | 它回答什么 | 搞错的典型样子 |
|---|---|---|
| 一 · 有哪几块 | 这个项目分成哪几块,每块负责什么 | 照抄目录结构——文件会搬家,职责不会 |
| 二 · 谁用谁 | 每块被谁用、从哪个口子用 | 把「名字出现了」当成「真的用了」 |
| 三 · 谁在改同一份数据 | 哪些东西存了不止一份、或被不止一处改 | 只看「被多少处用」,不看「被多少处改」 |
验证三步
| 对账结果 | 说明 | 该做什么 |
|---|---|---|
| 预测到了、真的变了 | 图上这条线是对的 | 这条可以信了 |
| 预测变了、没变 | 图上多了一条线 | 划掉它 |
| 没预测到、却变了 | 图上少了一条线 | 补上——这就是你「修 A 出 B」的根源 |
| 变了、还没报错 | 最危险:静默出错 | 给它加一道自动检查 |
看到这些信号就停下来
改一个小东西,要动三个以上的地方。这不是 bug,这是结构问题。继续埋头改只会越改越多,正确动作是回头看这三张表。
你手上必须有什么(再强调一次)
- 一个已经存在的项目目录(本文不教从零建项目)
- 一个能读你本地文件的 AI 编程助手——不是网页聊天窗口
- 一个能撤销改动的方式(用 git 管着,或者先复制一份整个文件夹)
三样都没有也没关系:拿这个站练。它就在你手上,例子全篇都是它。
12来源与证据边界
外部来源
| 用在哪 | 出处 | 我说了什么、它实际说了什么 |
|---|---|---|
| 表一的「画到哪一层为止」 | C4 模型官网https://c4model.com/diagrams | 原文:「不同层级的缩放,让你能对不同的人讲不同的故事」,并且「你不需要用满全部 4 层」,多数团队画到「系统上下文 + 容器」两层就够。我据此说:画到「再往下就需要懂代码」那一层为止。 |
| 第 6 节的方法依据 | 影响分析(change impact analysis)的标准定义,出自 Arnold & Bohner 的研究,见 ICSM 2003https://www.computer.org/csdl/proceedings-article/icsm/2003/19050256/12OmNqGRGeX | 定义是「找出一次改动可能带来的后果,或估计为完成这次改动还需要改什么」。专业人士用依赖图、调用图、执行轨迹等工具做;本文教的是手工版。「手工版」是我加的,不是原文说的。 |
| 表三的规矩 | 《程序员修炼之道》(The Pragmatic Programmer, Hunt & Thomas, 1999)提出的 DRY 原则 | 原文:「每一条知识在系统里都必须有一份单一的、明确的、有权威的表述」。注意它说的是「知识」,不是「长得像的文字」——这一点在第 9 节展开。 |
| 第 9 节的「巧合的重复」 | Industrial Logic:SPOT and Coincidental Duplicationhttps://www.industriallogic.com/blog/spot-and-coincidental-duplication/ | 它指出:看起来一样、但代表不同知识的重复是「巧合的重复」,不该被合并。我把它变成了一个可操作的问句:「如果这两处变得不一样了,那是个 bug 吗?」——这个问句是我加的。 |
一手材料:这个站自己
第 5 节里那些数字(三十几份副本、1 份样式、2 处日期)是我在 2026-09-16 当天在这个仓库里实际数出来的。你可以自己复核:
# 有多少个页面,就存着多少份那段「深浅色」脚本的副本
grep -l "ln-theme" learn/*.html | wc -l
# 全站样式有几份?(数出来是 1 —— 这就是"干净的那种")
ls learn/style.css | wc -l
# 首页卡片上写着的日期,和文章里写的日期,是两处;校验脚本会逐个比
bash .agents/skills/learn/check.sh --index
「三十几」这个说法是故意含糊的,因为它本来就是个会变的数字:它等于「这个站里有多少个页面」。我写这篇的那天数出来是 34 份,而你读到的时候多半已经更多了——每加一篇文章,就多一份副本;你正在读的这一篇,自己也是其中一份。
这正好又是这篇文章在讲的那件事:一个数字存在多处,而且还会各自变化,那么写在文档里的那个版本迟早对不上。所以要准的,别信任何文档里写的数字,用上面的命令现数。
证据边界
- 关于这个站的数字:全部是 2026-09-16 的实测值,命令已给出。项目一改,数字就变。
- 关于那次回滚:第 5 节提到「2026-09-16 为了加一张卡片,改完要回滚」。这件事我是按你知道的情况写的;它具体卡在哪一步我没有逐条核对。但上表列出的「加一张卡片要动五处」是我照着校验脚本的实际检查项数出来的。
- 关于外部来源:C4 官网那一页只说了「不同层级服务不同的人」,没有逐一指定「哪一层给谁看」——所以我没有编造这种对应关系,只取了「画到哪一层为止」这一条。
- 方法本身的边界:这套手工验证法没有经过实证研究检验,它是我从「影响分析」的标准做法推导出来的手工版本。它在小项目上很好用;项目越大,能靠「改一下看会怎样」覆盖到的范围越小,那时需要专业工具。
99一句话总结
一个东西被多少处「用」不重要,被多少处「改」才重要——把那几处找出来,你就不是在盲改。
而找它的方法,从头到尾不需要你读一行代码:让 AI 给你三张表,然后用「预测 → 扰动 → 对账」验它。你验的不是代码对不对,是关系对不对——那正好是只有你能做的事,因为 AI 只能读,而你能改。
留给你自己验的那一条
这篇文章里所有结论我都能替你验,除了这一条——它只能你来。
拿出你手边那个最小的半途项目,试着回答:这个项目里,有哪一份东西是「存了不止一份」的?(提示:先别想代码。想想有没有同一个邮箱、同一个数字、同一句说明文字,你记得自己改过两次。)
然后想一想——它有没有一个自动检查盯着?如果没有,你就知道那个「越改越多」是从哪来的了。