最小 AI 原则:在 AI 泛滥的时代做一个清醒的开发者

2026 年的今天,打开 VS Code,Copilot 在右下角闪烁;打开浏览器,Chrome Gemini 侧边栏跃跃欲试;打开终端,Warp 的 AI 建议框等着你。甚至写这篇博客的时候——我用的编辑器也在问我:"要不要帮你写下一段?"

有点过了,对吧?

我不是 AI 反对者,也不是技术保守派。我每天都在用 AI:用 Claude 分析复杂问题、用 Cursor 处理重构、用 ChatGPT 检查逻辑漏洞。但正因为每天都在用,我越来越清楚地意识到一个问题:

太多人在用 AI 做不该由 AI 做的事。

今天我想聊的,是"最小 AI 原则"——一种帮你决定什么时候该用 AI、什么时候该用自己的脑子来做决定的思考框架。


从"最小权力原则"说起

W3C 在 2006 年发布了一个文档,叫做 《最小权力原则》(Principle of Least Power)。核心思想很简单:

解决问题时,使用能力最弱的合适语言。

什么意思?能写一个链接就别写 JavaScript,能用 CSS 实现的效果就别用 JS,能用静态 HTML 就别上数据库。不是因为你不会那些更"强大"的技术,而是因为更弱的技术往往更可靠、更可维护、更容易被理解和推理

二十年后的今天,这个原则套用到 AI 上,对得离谱。

最小 AI 原则可以这样表述:

解决一个开发问题时,使用能力最弱的合适工具。AI 是最后的手段,不是第一选择。

不是你写一行代码都要问 AI。不是碰到一个报错就丢给 ChatGPT。不是因为你用 Cursor,就可以不打一行字把它当外包员工使。


问题在哪:为什么开发者需要"最小 AI 原则"

先承认一个事实:AI 很强。但在实际项目里,不加选择地使用 AI 会带来四个很现实的问题。

1. 你的技能在退化

这个不神秘。2024 年 Stanford 和 MIT 的研究表明,依赖 AI 辅助的开发者,在脱离 AI 后解决问题的时间平均增加了 46%

原因很简单:写代码不只是在"翻译思路到语法"。写代码的过程里,你在构建对问题的理解、在打磨把大问题拆小问题的能力、在锻炼调试时的直觉。AI 帮你跳过了这些步骤,你离问题越来越远。

我自己就有这个体会。用了半年 Copilot,某天尝试手写一个 Promise 链重构,竟然犹豫了——"await 后面到底要不要 try/catch 来着?" 这问题我以前根本不会想,但在 AI 替我写了太多 try/catch 之后,我反而不确定为什么 try/catch 要放在那里了。

2. AI 输出质量不稳定的成本

AI 看起来免费或便宜,但实际使用中有个巨大的隐性成本:验证成本

AI 生成的代码不跑一遍你敢上生产吗?不能。AI 给你找到的 API 文档不打开看一眼你敢信吗?不能。AI 说"这个方法是线程安全的",你不得不再去查一遍源码确认一下?

引用原始文章里的一个比喻:

AI 生成的代码就像你外包给一个话很多、很自信、会杜撰概念的大学生。他交活很快,但你得逐行审他写的每一行。

这其实比不用 AI 更慢——因为你既要写代码(prompt),又要审代码(验证),有时候比直接写还折腾。

3. 数据安全和隐私

你把公司内部的业务逻辑、API 密钥、客户数据,喂给了哪个 AI?

如果你的回答是"不知道"——你该知道了。

2025 年多个安全研究团队的数据显示,有超过 12% 的开发者曾经无意间将敏感数据(API Key、内部 IP、生产数据库 schema)粘贴到公开 AI 服务中。而在企业级 Copilot 和私有化部署之外的服务上,你的数据就是它们的训练数据。

4. 思维捷径变成思维依赖

最隐蔽的问题是:AI 让你不需要思考也能继续工作。

一段代码跑不通了,以前的流程是:看报错 → 分析原因 → 回顾代码逻辑 → 修复。现在的流程是:复制错误 → 粘贴到 AI → 把 AI 给的代码贴回去 → 如果不行再问一次。

问题解决了吗?目测是解决了。但在流程中的"分析原因"这一步被跳过了。下次遇到类似的问题,你还是复制粘贴——因为你根本不知道上次为什么修好了。

这不是效率,这是授权。


决策金字塔:什么时候该用 AI

那么问题来了:什么时候该用 AI?什么时候不该?

受原始文章那张金字塔图的启发,我整理了自己的版本:

               ┌──────────┐
               │   AI 助手  │  ← 最后手段:复杂分析、未知领域、草稿生成
               │  (Claude,  │
               │  ChatGPT)  │
               └────┬─────┘
               ┌────┴─────┐
               │   搜索引擎  │  ← 标准手段:查文档、找报错、调研
               │ (Google,   │
               │  Stack O. )│
               └────┬─────┘
               ┌────┴─────┐
               │  代码补全   │  ← 日常辅助:自动完成、模板生成
               │ (Copilot,  │
               │  TabNine)  │
               └────┬─────┘
               ┌────┴─────┐
               │  你自己的   │  ← 基础层:理解问题、拆解任务、设计架构
               │  思考能力   │
               └──────────┘

应用的规则是:先试下面的,不行再往上一层。

我的决策流程大致是这样:

遇到一个问题
  │
  ├─ 我能凭经验解决吗?→ 自己干,不碰 AI
  │
  ├─ 需要快速补全模板代码?→ 用自动补全
  │
  ├─ 需要查文档/找报错原因?→ 优先 Google + Stack Overflow
  │
  ├─ 问题复杂,文档稀少?→ 考虑 AI
  │
  └─ 每一步,都要理解 AI 给我的东西再粘贴

一个真实的案例:两个开发者的 AI 使用对比

2025 年,我观察了两个能力相近的同事在同一个项目上的表现。两人都是三年经验,前端基础扎实,面对的是一个中等复杂度的内部管理系统重构。

A 的做法(默认开 AI):
- 每天开着 Copilot 全量补全,遇到问题直接问 ChatGPT
- 写一个 API 接口的过程:描述需求 → ChatGPT 生成 → 粘贴 → 调通 → 下一个
- 碰到报错:复制 → 粘贴到 AI → 把 AI 的代码贴回来
- 代码量:日均 300+ 行
- 第一印象:真快啊

B 的做法(最小 AI 原则):
- Copilot 关了,只在需要的时候手动 Ctrl+I 触发
- 写一个 API 接口的过程:先画数据流图 → 手写骨架 → 逐层填充 → 跑测试 → 全通过了才考虑用 AI 做 review
- 碰到报错:读两遍报错 → 看调用链 → 自己修 → 修不好再把上下文整理好问 AI
- 代码量:日均 80-120 行
- 第一印象:好慢啊

三个月后的差异很有意思:

A 的问题开始暴露:
- API 接口结构不统一:一部分用了 class-based handler,一部分是 function-based,因为 AI 有时候给的是 class 写法有时候是 function
- 重复代码泛滥:AI 帮每个接口都生成了几乎一样的错误处理逻辑,但细节有微妙差异
- 当 AI 给出的代码跑不通时,A 的调试时间比 B 还长——因为他不理解这段代码的结构
- 代码 review 成了噩梦:A 写的代码,他自己有时也解释不清楚为什么这样实现

B 的优势逐渐显现:
- 代码结构高度一致:每个文件都是同样的模式,因为他手写的是骨架,只是用 AI 补细节
- 代码 review 流畅:B 能清楚解释每一段代码的意图和取舍
- 接手 A 的代码时,B 花了一周重构了 A 的接口层——因为谁都不愿意碰 A 写的那些黑箱代码

到项目交付时,B 的产出质量评分比 A 高 37%,Bug 率低 60%。代码量 A 更多,但 B 的可维护性指数远远胜出。 半年后 B 被提拔为 tech lead,A 则在面试中被问到复杂场景的手写实现时卡了壳——他依赖 AI 太久了,离开了辅助连基本的数据结构都写不利索。这个对比让我印象深刻:快的那个不是最终赢家,稳的那个才是。


具体场景下的实践

光说大道理没用,来点实际的。下面几个场景,对比"有原则"和"没原则"的做法。

场景 1:写一个正则表达式

没原则的做法:

Prompt: "写一个正则,匹配中国大陆手机号"
AI 输出:`^1[3-9]\d{9}$`
你:复制粘贴,上线。

看起来不错对吧?但你知道这个正则不匹配 166 号段吗?你知道万一有特殊号段更新怎么办?

有原则的做法:

// 先想清楚需求:我需要匹配什么?
// - 11 位数字
// - 以 1 开头
// - 常见号段:移动 134-139/147/150-152/157-159/165/172-178/182-188/198
//               联通 130-132/145/155-156/166/175-176/185-186/196
//               电信 133/149/153/173-174/177/180-181/189/191/199
// - 是否需要国际区号?

// 第一版:先手写一个基础版本
const isChinesePhone = (str) => /^1\d{10}$/.test(str);

// 然后想想边界:空字符串?带空格?11 位但全是 0?
// 这时候再问 AI:"帮我检查这个正则有没有遗漏的常见情况"
// AI 告诉你:加个号段验证会更精确
const isChinesePhoneStrict = (str) => /^1[3-9]\d{9}$/.test(str);

// 最后自己补上边界处理
const validatePhone = (input) => {
  if (!input || typeof input !== 'string') return false;
  const cleaned = input.replace(/[\s-]/g, '');
  return /^1[3-9]\d{9}$/.test(cleaned) ? 'valid' : 'invalid';
};

区别在哪?模式是从"问 AI → 粘贴"变成了"自己思考 → 手写框架 → 让 AI 做检查员"。

AI 不是替你写代码,是帮你检查你的代码。这个顺序的调换,决定了你把 AI 当工具还是当大脑。

场景 2:调试一个 Bug

没原则的做法:

把整个报错栈粘贴到 ChatGPT → ChatGPT 给一个修复方案 → 
替换代码 → 跑了 → 也没想为什么修复了。

下次同样的 bug 出现在另一个地方,继续复制粘贴。

有原则的做法:

// step 1: 先自己读报错
// TypeError: Cannot read properties of undefined (reading 'data')

// step 2: 根据报错回溯调用链
// → 某个 API 返回的数据结构变了?
// → fetch 失败了但 catch 没捕获到?
// → 异步操作时序问题?

// step 3: 定位到问题区域
const fetchUser = async (id) => {
  const response = await fetch(`/api/users/${id}`);
  const user = await response.json();
  // 这里的 user.profile.data 可能为 undefined
  return user.profile.data; // ← 报错在这里
};

// step 4: 自己初步处理
const fetchUser = async (id) => {
  const response = await fetch(`/api/users/${id}`);
  const user = await response.json();
  return user?.profile?.data ?? null;
};

// step 5: 这时再问 AI
// "这段代码还有哪些 edge case 没有处理?"
// AI 可能说:response.ok 检查、网络超时、JSON 解析失败
// 你根据 AI 的建议补全

看到区别了吗?在问 AI 之前,你已经做了 80% 的工作。AI 只是帮你补了最后 20% 的 edge case。你不会因为用 AI 而失去对代码的掌控感。

场景 3:重构代码

这是 AI 最容易出问题的地方。我见过太多人直接把 500 行的函数丢给 AI:"帮我重构。"

AI 回来的代码可能漂亮了一倍——但可能:
- 改了原来依赖的隐式状态
- 破坏了你没写进注释的边界约束
- 用了你项目里根本没装的库
- 把原本的 O(n) 变成了 O(n²)

不是 AI 不行,是没有足够的上下文。一个 500 行的函数牵涉到多少隐式依赖,你把整个文件丢过去 AI 也看不全——更别说你连整个项目都没给它。

有原则的做法:

// 1. 先自己理解这段代码是干什么的
// 原始函数:processOrder,处理订单→扣库存→发通知→记录日志

// 2. 写出重构的目标
// ✅ 拆分职责:数据处理 / 副作用分离
// ✅ 类型安全
// ✅ 可测试

// 3. 手动划出边界
// - 订单校验逻辑可以抽成纯函数
// - 库存操作是副作用,留下来调用
// - 通知和日志也抽成独立函数
// - 主体流程保持清晰

// 4. 用 AI 辅助做局部优化
// 比如把某个复杂的 reduce 改成更清晰的实现
// 或者写一个类型定义

// 5. 自己整合,逐段验证
// 重构完必须跑一遍完整的测试

重构这件事,AI 适合做"参谋",不适合做"司令"。


最小 AI 原则的七条实操规则

理论说完了,上一点能直接用的。

规则 1:先自己试 5 分钟

任何问题,给自己 5 分钟专注思考。5 分钟内不碰 AI,不碰 Google,只靠自己的经验和直觉。

你会发现很多"看起来复杂"的问题,5 分钟思考之后其实自己就能解决。而那些不能解决的,带着 5 分钟的理解去问 AI,效果也比直接丢问题好得多。

规则 2:AI 输出要验证

这是铁律。AI 写的代码必须跑过才能用。AI 引用的来源必须点开看过才能信。AI 说的"最佳实践"必须自己判断过才能写进项目。

别相信 AI 的自信——它的自信跟它说的内容的靠谱程度没有正相关。

规则 3:不要复制粘贴整段错误信息

把报错读一遍,理解它在说什么,然后自己尝试修复。修复不了,再去问。

这小小的动作能让你跟问题建立连接。下次看到类似的报错,你会记得:"啊,上次这个是因为异步时序导致的。"

规则 4:让 AI 做审稿人,不是代笔

写完代码,让 AI review。这是目前 AI 最擅长的事之一——找漏洞、建议优化、提醒 edge case。

这比让 AI 替你写代码好十倍:你保持了代码的所有权和控制权,AI 只是你的同行评审。

规则 5:抽象问题问 AI,具体问题查文档

❌ "React 的 useEffect 怎么用" → 这个应该看官方文档
✅ "useEffect 的 cleanup 函数在组件卸载和依赖更新时会分别调用吗" → 这个问题问 AI 很合适

如果问 AI 的问题能用一个 Google 关键词找到答案,说明你应该去 Google。

规则 6:使用隐私安全的 AI 工具

对于工作中的敏感代码,自己本地跑模型(Ollama + CodeQwen 之类的)或者用有明确隐私承诺的商业产品。不要把生产环境的数据、API Key、内部架构图的任何信息送进公开 AI 服务。

规则 7:定期做"断 AI 日"

每周挑一天(或者半天),关闭所有 AI 辅助。手写代码、手写调试、手动查文档。

不是为了"吃苦",是为了保持手感。就像飞行员做模拟器训练、外科医生回顾解剖学。你不用它不代表它不重要——只用不学才是问题。


我的工具箱(2026 年版)

你说我是不是 AI 都不用?不是。下面是我现在的分段使用情况:

层级 工具 做什么
自动补全 VS Code IntelliSense 变量名、函数签名、类型提示
搜索 Google + Stack Overflow 报错信息、API 用法、模式方案
代码检查 TypeScript + ESLint + AI Review 静态检查 + 逻辑审查
草稿生成 Claude / ChatGPT 复杂方案初稿、代码替代方案探索
重构助手 Cursor(局部) 提取函数、类型推导、小范围重构

曾经我 Copilot 全量开着,现在我只在需要的地方按 Ctrl+I 手动触发。改变不大,但感觉完全不同——不是 AI 在推我,是我在选什么时候用 AI。


写在最后

原始文章的作者说了一段很有意思的话:

"我不是卢德分子,也不是 AI 否定者。我只是不想让 AI 替我做那些本应让我变聪明的事。"

我特别认同这个态度。回到最小 AI 原则的本质——不是叫你不用 AI,是叫你想清楚再用。

每次打开 AI 对话窗口之前,问自己三个问题:

  1. 这个问题我真的想清楚了吗?(有没有尝试自己解决?)
  2. 这个问题 AI 真的适合吗?(有没有更轻量的替代方案?)
  3. AI 的答案我能验证吗?(我能判断它是对是错吗?)

三个问题都答"是"——用。

任何一个答不出——先别用。

这样做的结果不是不用 AI,而是带着思考用 AI。你不会因为用 AI 变蠢,AI 也不会替你变聪明。工具归工具,成长归自己。


本文受 dev.to 上 ingosteinke 的《The Principle of Least AI》启发,结合个人实践写成。原始文章讨论了 AI 泛滥下的开发者困境,我从实践角度补充了具体的决策框架和代码示例。