2026 2026年10月30日 28 min · 8.8k chars by yxc023
当代码可以随便生成,抽象还值不值钱?
AI 让写第二套实现的成本趋近于零,抽象曾经赖以成立的经济学动摇了。本文从真实接手经历出发,给出判断标准:会不会因同类理由变更、参数化污染信号、协议成本,并盘点 Sandi Metz、GitClear、arXiv 实证与 Fowler × Joshi 等业界讨论。
一份写给工程师的判断指南:在 AI 大量生成代码的今天,我们该在哪些地方继续抽象,在哪些地方应该放心地重复。
引子:我接过的几段代码
回看这几年接手的项目,还有团队自己这几年写的代码,看到一个现象:当初那些”统一维护一份”的抽象,现在正在集体变沉。
先说清楚一件事:当时的决定并不算错。人工写代码时代,减少逻辑量、减少代码量、把一批相似功能统一维护起来以降低成本——这是标准的、也是正确的工程选择。今天回头看,变的不是当时的判断力,而是成本结构本身。
第一件:已经变沉的既有抽象。 接手时项目里已经有一些抽象,不算错,但比较重——一段面向多种应用的公共执行逻辑,抽出来的时候挺顺,代码也漂亮,但它面向的从来就不止一个场景。后来现实里冒出新挑战,数据维度要扩展,才发现这套抽象的功能在哪儿都得挂一个参数化开关:走 A 分支的时候要传这个,走 B 分支的时候要关那个。开关越加越多,抽象本身越来越沉。
而它真正让人难受的地方在于改动半径:每次要动这段流程,都得先想一遍”其他几个用它的应用会不会受影响”。改一个地方,要看五个地方。这不是技术问题——是抽象给自己加了一层耦合。当初省下的那点代码,现在要用”每次改动都要多看几个地方”来还。
第二件是存储:项目里把几个类型略有不同的相似实体,统一存在了一张表里。刚开始确实省事——一张表、一个模型、一套查询。但随着业务不断扩展,新的类型想要进来,就会发现它得往这个共用模型里适配:字段塞不进去就加一个含义模糊的列,枚举对不上就加一个特殊值。削足适履,越到后面越难受。后来改成各存各的模型,反而清爽了。
第三件是渲染:之前为了”只维护一份东西”,定了一套渲染协议——先约定每个字段该用什么组件(表格?标签?卡片?),再写一套统一的渲染逻辑去生成页面。协议本身是个不小的成本,而且它限制了表达力:内容本身有差异的时候,套在那套组件协议里,怎么调都不好看。后来干脆拆开,每个文件针对自己的数据模型,单独生成一套渲染页面代码,效果反而好得多。维护的代码看着变多了,但每一份都简单、都能看懂。
所以我现在的判断是这样的:
- 抽象曾经很有价值,因为它能把复杂的逻辑想清楚,把一批类似的实体统一下来,用一套代码降低维护成本;
- 但现在这个性价比反转了。类似但略有不同的业务规则,即使概念上可以泛化,完全可以写成完整两套,各用各自熟悉的词汇——代码重复就重复,反而更简单直接,更容易理解。存储也一样:与其共一张表互相适配,不如各存各的模型。
这不是说当时的抽象做错了,而是当时的约束条件已经不成立了。
2014 年 RailsConf 上 Sandi Metz 说了一句话,后来被写成博客,成了她最被引用的一段:
duplication is far cheaper than the wrong abstraction 重复远比错误的抽象便宜。
十年前这句话是一句少数派异议。2026 年 6 月,那篇 2016 年的旧文重新登上 Hacker News 榜首,400 多分、270 多条评论。评论区里出现最多的句子是:
在一个 AI 可以一次性替你生成五百行”看起来正确”的代码的时代,这条原则比任何时候都更需要被重新讨论。
这条原则不只是”过时”。它其实刚刚好对上了 AI 编程的真相。
一、一个正在发生的成本反转
抽象之所以在过去的五十年里显得如此正当,是因为写代码很贵。
一段重复的代码要写两遍,一个泛型基类要设计参数、要写文档、要在每次调用时考虑绑定值是否正确。当”写”是瓶颈时,抽象的经济学是压倒性的:省下的行数是实打实的成本节约。
但现在这个前提反过来了。
| 人工时代 | AI 时代 | |
|---|---|---|
| 写第二套相似实现的成本 | 高(人天) | ≈ 0(分钟级) |
| 定一套协议 + 维护协议的成本 | 高 | 高(没变) |
| 审查一段通用实现的难度 | 中 | 高(要同时持有通用语义 + 本次绑定) |
| 表达力受限(被协议框住)的代价 | 高 | 高(没变) |
| 等待”第三个实例出现”的成本 | 高 | ≈ 0 |
| 分叉(实现各走各的路)的成本 | 高 | ≈ 0 |
于是稀缺资源发生了转移:
优化目标从”代码量最小化”变成了”审查成本最小化”。
而抽象恰恰是提高审查成本的。一份通用实现 + 一个 type 参数,读者需要在脑子里同时维护两个模型;两份各写各的完整实现,每份只需要维护一个模型,而且每一份都直接读得懂业务规则。
而且抽象省下的从来只是”写”的成本,它自己还有一笔从未变便宜的成本:先定协议、把内容塞进协议、以及被协议框住的表达力。这三笔才是抽象真正在交易的东西。
这就是”重复就重复”这个直觉背后真正的道理:它不是懒,它是把成本从”写”挪到了”读”,而”读”现在恰好是我们更稀缺的那一侧。
所以回头看,当年的那些抽象不是”做错了”,而是它们在一个已经变了的世界里继续服役。接手时让人痛苦的,不是抽象本身,而是”抽象曾经的理由已经不成立了,但代码还在”。
二、把”抽象的收益”拆成四份,看 AI 到底打掉了哪一份
“抽象”其实是个打包概念,里面混着四种完全不同的收益。把它们拆开,才能看清哪些该扔、哪些该留。
收益 A:消除重复书写 ✅ 已被彻底打掉
省人力、省代码行。这部分收益在 AI 面前归零。你再也不会因为”写第二遍要花两小时”而被迫设计一个参数化的通用方案。
这是唯一被真正消灭的部分。
收益 B:强制不变量与一致性 ❌ 没被消灭,而且风险被放大
金额计算、权限判定、审计留痕、对外承诺口径——这些东西的正确性依赖”只有一份实现”。两个实现就意味着两个真相,漂移了就出事。
而且 AI 让这件事更危险,不是更安全:
- 人工时代,复制粘贴第二套实现时,人会本能地觉得”不对劲”,多数人会回头抽公共基类;
- AI 时代,生成第二套实现零摩擦,而且每份实现局部看起来都非常合理。
AI 让”分叉”变便宜,也让”分叉”变得更危险——因为分叉得太顺手,而且看起来都对。
收益 C:收敛概念与词汇 ❌ 与 AI 完全无关
把纷杂的自然语言现实梳理成有限、标准的数据模型和行为——这件事的价值来自”业务本身有客观结构”,不是来自”代码要省行数”。
如果今天允许每一份实现各用一套字段名、各用一套状态定义,那么三个月后没有人能确定”这两个东西的待审核是不是一回事”。概念分裂的代价与 AI 无关,而且通常远大于代码重复。
放到我这两年接过的代码上:那些”为了抽象而抽象”的重,最终累赘的地方往往不是逻辑复杂,而是同一个东西在不同地方被叫成不同的名字、赋予了不同的含义。这种分裂不会报错,只会在需求变化时让人花半天确认”这两个到底是不是一回事”。
收益 D:降低读者认知负担 ⚠️ 方向反转
历史上有句谚语:“代码行数 ≈ 人的心智负担”。这其实从来不完全对——真正的负担不是行数,而是要同时在脑子里维护多少个心智模型。
- 通用实现 + 参数绑定:负担 = 通用语义 + 绑定值,两层;
- 两份具体实现:负担 = 每份各自一层。
现在稀缺的是审查时间,抽象增加审查负担。所以这一项今天的结论是反的。
小结
抽象的价值来源,从”消除重复书写”迁移到了”消除概念分歧”和”保证不变量”。 代码层面的统一程度可以下降;领域模型层与词汇层的统一不能省。
三、核心判据:它们会因同类的理由而变更吗?
这是整篇文章最实用的一条。判断”要不要统一”,不要问”像不像”,要问”会不会一起改”。
未来某一次业务变更,会不会同时改到 A 和 B?
| 会一起改 | 不会一起改 | |
|---|---|---|
| 判定 | 同一概念的两种表现 | 两个恰好相似的概念 |
| 模型层 | 共享实体、字段、状态机、词汇 | 完全独立建模 |
| 代码层 | 各写各的(各用各自熟悉的业务词汇) | 各写各的(本来也没得统一) |
例 1:同一概念 —— 一段面向多种应用的公共流程
一段逻辑同时服务多种应用,抽象出来的时候确实”消除了一堆重复”。但如果这些应用的变化节奏不一样——比如一类要支持数据维度扩展,另一类两年不动——那把它们焊在一起,改动成本就从”改一处”变成”改一处 + 想清楚会不会影响另外几处”。
这时候正确的做法是:共享模型与词汇(这些应用到底是什么、字段怎么定义、状态怎么流转),但执行流程各写各的。每份实现只服务自己那个场景,改动半径为零。
例 2:两个概念 —— 渲染逻辑
之前为了”只维护一份东西”,我们定了一套渲染协议——先约定每个字段用什么组件,再写一套统一的渲染逻辑去生成页面。协议限制了表达力:内容本身有差异的时候,套在那套组件协议里,怎么调都不好看。后来拆开,每个文件针对自己的数据模型单独生成一套渲染代码和页面,效果反而好得多。
这不是”抽象没做好”,这是两个概念恰好长得像。它们的差异不在数据,在最终呈现的效果。共用一套渲染逻辑,等于强行让两个不同的东西用同一种表达方式——省下的那点维护时间,全赔在效果上了。
例 3:两个概念 —— 共用一张表存相似实体
几个类型略有不同的相似实体,统一存在一张表里。短期省事,长期被业务扩展逼着做适配:新类型进来,字段塞不进去就加一个含义模糊的列,枚举对不上就加一个特殊值。这是典型的削足适履——共用模型反过来绑架了本来不同的业务。
代价还不止于字段:查询会越来越绕(每多一个类型就多一个 where 分支),约束会互相干扰(一个类型的必填规则卡住另一个类型),数据模型与业务的概念开始漂移。
处理方式就是本文的主张:各存各的模型。数据库层面多几张表、几份 DTO,换来的是每个业务都能用自己的字段、自己的约束、自己的语言。
例 4:两个概念 —— 被参数化开关撑起来的抽象
功能本身不复杂,却被一堆参数化开关撑起来,走哪条分支都要先读一遍参数怎么传。这通常说明当初被统一的那几个场景,根本不是同一个东西,只是写代码的时候看起来像。
这跟第一章说的”参数化污染”是同一个信号的两面:开关是抽象开始腐化的最早可见的痕迹。
这条判据在业界有出处
2026 年 6 月 HN 那场讨论里,被反复引用的核心问题几乎一字不差:
文章讨论的正是”你还不知道真相来源有几个”的情况。这两个位置用的是同一套算法,还是略有不同的版本?更重要的是,它们会因同类的理由而变更吗?——jonahx
同一位评论者还有一句更锋利的:
最关键的是,错误的抽象破坏了局部性——而那其实是你修改代码时唯一真正在乎的属性。我只想做这一个改动,不用担心对系统不相关部分的副作用。
“局部性”是比”复用”更重要的目标。 在 AI 时代尤其如此:你要改的是一段局部代码,而不是一个被 5 个调用者共享的参数化引擎。
四、参数化污染:识别”假相似”的现场信号
上一条判据在实践中需要一些抓手。有一个非常可靠的现场信号:
为了把 A 和 B 塞进同一份实现,你必须给它加
if/flag/ 参数维度。
// 统一审核流程
applyRule(order, type)
if (type == STANDARD) { ... }
if (type == VIRTUAL) { ... }
if (type == COOPERATION) { ... } // ← 第三个类型冒出来了
参数一多,状态空间成倍膨胀。每个调用者都要理解”通用语义 + 本次绑定”两层。通用实现开始长出第三个布尔或枚举参数时——这就是拆分信号。
这条机制在业界被描述得更加具体。Dejan Menges(Vinted Staff Engineer)写到:
AI agent 会写出能跑但架构上错的改动:实现了一个已经存在的东西、为已解决的问题引入第二套抽象、把新行为放在没人会想到去找的地方。改动能跑,PR 是绿的,任务完成了。直到下一次改动——这时另一个开发者或 agent 必须判断:两个实现里哪一个才是真的?
而 Reveneau 说得更准:
让模型处理三个相似案例,它通常会产出一个恰好能处理这三个的巧妙东西。这不是模型的 bug——它读过大量”合并相似案例是对的”的代码,它只是缺了路线图:它不知道第二个案例下周就要换方向。
所以参数化污染的那一刻,就是抽象出错的那一刻。
五、抽象的隐藏成本:先定协议,才能写代码
前面说的都是抽象”跑起来之后”的成本。还有一笔成本发生在动手之前:任何像样的抽象,都要求你先定下一套协议。
渲染是最清楚的例子:
抽象方案(我们走过的路) 直接方案(现在能走的路)
───────────────────────────── ─────────────────────────────
① 定一套渲染协议: 针对每个数据模型,
字段类型 → 组件的映射规则 单独生成一套页面代码
② 写一套通用渲染逻辑
③ 每份内容都往协议里塞 表达力不受协议限制
④ 内容有差异时:效果不好 想要什么效果就写什么
第 ① 步和第 ② 步是实实在在的维护成本,而且会一直付下去:协议本身要演进,映射规则要覆盖越来越多的字段类型,而协议一旦定下,所有业务都被框在它能表达的范围里。
而这套流程存在的唯一理由是”要维护一份”。在代码可以随便生成的今天,这个理由不成立了——针对一个数据模型,单独生成一套精美的渲染页面代码,完全可行。生成出来的效果不好吗?比通用模板套出来的更好看,因为它本来就是照着这个模型写的。
所以抽象的完整账单是这样的:
| 抽象的代价项 | 过去 | 现在 |
|---|---|---|
| 写第二套实现的成本 | 高 | ≈ 0 |
| 定协议 + 维护协议的成本 | 高 | 高(没变) |
| 通用实现的审查成本 | 中 | 高 |
| 表达力受限的代价 | 高 | 不变(现在甚至可以做得更好) |
中间两行没有因为 AI 而变便宜,第一行变便宜了,第三、四行变贵了。这就是性价比反转的全部机制。
这也解释了为什么”直接生成一套专属的渲染代码”不是偷懒,而是正确:它省掉的是协议成本,避开的是表达力限制,代价只是多了一份代码——而这份代码现在几乎不要钱。
回头看引子里那三件事,会发现它们其实是同一件事的三个切面:
| 接手时看到的 | 它其实是哪种成本 |
|---|---|
| 公共流程越改越要看多个调用方 | 耦合成本(抽象给自己加的) |
| 参数化开关越挂越多 | 协议成本(抽象要维护的那套约定) |
| 共用一张表、类型来了要适配 | 表达力成本(被共用模型框住) |
三笔都是抽象的固有成本,而且没有一笔因为 AI 而变便宜。真正变便宜的只有”写第二份实现”这一项——而那恰恰是抽象本来要解决的主要痛点。当唯一的优势消失,抽象的性价比就反转了。
六、重复不是免费的:它的账单要单独记
“代码重复就重复”是对的,但重复有它自己的成本结构,而且这份账单不随 AI 下降。
| 重复的隐藏成本 | 具体内容 | 对策 |
|---|---|---|
| 漂移检测负担 | N 份实现要定期确认”这 N 套规则现在还一致吗” | 一致性测试 / 共享测试数据 / 单一规则源 |
| 词汇漂移 | 两套实现各自演化术语,最后没人知道两边的”待审核”是不是一件事 | 术语映射表(glossary) |
| 导航成本 | 想知道”这条规则到底在哪”要看 N 处 | 索引/目录标注 |
| 承诺不一致 | 对内系统和对客系统给出不同答案 | ⚠️ 跨边界口径必须单一真源 |
反过来,抽象也有隐藏成本:leaky generality(通用实现被特例撑破)、参数维度膨胀、审查负担。
所以正确的做法不是在”抽象 vs 重复”里二选一,而是逐项比账。 最优解通常长这样:
┌──────────────────────────────────────────────────┐
│ 领域模型层(共享) │ ← 统一实体 / 状态机 / 词汇
│ 概念、字段、不变量 │ 这层必须统一
└──────────────────────────────────────────────────┘
▲
┌──────────────────────────────────────────────────┐
│ 规则 / 规格源(单一真源,可读可测) │ ← 抽象的真正落点
│ 决策表 / DSL / spec 文档 + 示例 │
└──────────────────────────────────────────────────┘
▲ ▲ ▲
┌───────────┐ ┌───────────┐ ┌───────────┐
│ 实现 A │ │ 实现 B │ │ 实现 C │ ← 各用各自词汇
│ 完整、独立 │ │ 完整、独立 │ │ 完整、独立 │ 从同一规格生成
└───────────┘ └───────────┘ └───────────┘
▲
┌──────────────────────────────────────────────────┐
│ 安全带:一致性测试 + 术语映射表 │
└──────────────────────────────────────────────────┘
要点:
- 规则写一次,实现写多次——业务真相单点可查、可测、可直接贴给 AI 当上下文;
- 一致性测试作为守门人——同一组输入喂给多套实现,断言输出一致(或断言差异符合预期)。这是”允许重复”的安全带;
- 模型层是共享词汇层——它保证两边说的是同一件事,但不强求两边用同一套代码。
这正是”抽象上移”:抽象没有消失,它从代码搬到了规格和词汇。
七、什么必须保留单一真源(不可重复的清单)
有些地方,“两份实现”不是省钱,是制造风险:
- 金额 / 账务 / 费率计算(精度、单位、四舍五入)
- 权限鉴权判定(两份授权逻辑 = 一个漏洞)
- 审计留痕 / 操作日志
- 对外承诺口径(合同、SLA、对客规则)
- 数据模型与存储约束(表结构、唯一键、外键——数据库层面本来就在统一)
- 核心状态机的合法迁移集合
判断口诀:
错误代价高 + 必须处处一致 → 单一真源 错误代价低 + 各场景独立演进 → 允许重复
八、业界说了什么:证据盘点
这个话题在 2025–2026 年已经从”少数派口味”变成了”有实证支撑的争论”。下面按证据强度分组。
8.1 强支持
Sandi Metz《The Wrong Abstraction》(2016) — “duplication is far cheaper than the wrong abstraction”。她给出了错误抽象的 8 步退化路径:
程序员 A 发现重复 → 抽出公共方法并命名 → 代码完美,A 满意离开 → 时间过去 → 新需求来了,现有抽象”几乎”够用 → 程序员 B 出于对既有代码的尊重,加一个参数、加一个分支 → 第三个需求、第四个参数、第五个 if → 到第八步时,你出现了,对着一堆纠缠的条件逻辑,试图理解哪些分支属于哪个调用者。
解法同样简洁:把抽象内联回去(“the fastest way forward is back”)——让每个调用者只保留自己真正需要的代码,再从头观察哪些相似性是真实的。
2026 年 6 月,这篇 2016 年的旧文重登 HN 榜首(400+ 分 / 270+ 评论)。
Justin Holt《The Case Against DRY in the Agentic Age》 — 提出 RYAN(Repeat Yourself As Needed):
重复是一种工具,不是罪过。抽象要挣得自己的位置,而不是因为”两件事恰好在某个星期二看起来像”。
- 放心重复代码。两个渲染相似 markup 的模板,可以就是两个模板。
- 不要重复知识。业务规则、税额计算、权限检查,应该活在一处。
这两句话几乎就是我全文的结论:知识/模型单点,代码可重复。
arXiv 2603.27130《真实仓库 AI 代码大规模实证研究》 — AI 生成代码 content ratio 更高、lexical density 更低,作者总结为 “Explicitness over Compactness”:
AI 生成的代码倾向于用重复的、显式的构造来表达逻辑,而不是紧凑的抽象。
这是最直接的实证背书:AI 自己就在往”显式、展开、好读”的方向产出代码。
arXiv 2610.24093《Does AI-Assisted Development Homogenize Software?》 — 50 个长期存活的 Java/Python 项目、三个时代(pre-LLM / LLM-assisted / agentic)对比:语义与语法相似度没有上升(Java 甚至显著下降),Python 无显著差异;质量指标基本稳定,agentic 时代的 code smell 与 SQALE 密度反而更低。
这反驳了”AI 必然把代码库搞成一片重复”的悲观论。
arXiv 2607.13077《The Hitchhiker’s Guide to Monoculture》 — Kaggle 2019→2026 提交物研究:AI 让语法趋同(连 seed = 42 都收敛),但 “approach / intent” 没有证据表明同质化。
推论很关键:“写法统一、思路保持多样”是可行的——这正好对应”各写各的但遵守统一约定”这种团队形态。
grapeot《超越DRY:AI原生软件工程的思考》 — 一年高强度 AI 开发后的第一手实践:
我并没有有意识地避免重复工作,甚至有意违背了软件工程最核心的原则——DRY。每次我想画流程图、做简单的可视化,就直接让 AI 帮我写,而没有把它们抽象成一个可复用的库。可是奇怪的是,我的开发效率并没有降低。
他进一步提出 UGS(User Generated Software)与 Generative Kernel 交付观:AI 原生设计应该是”激进透明”——暴露细粒度控制、提供原始错误信息、交付给 AI 看的知识。结论:
我们依然要不遗余力地避免在核心能力上重复自己,但我们允许、甚至鼓励 AI 在生成最终应用时,为满足个性化需求而进行有意义的重复。
8.2 保留意见
GitClear 2025(2.11 亿行改动数据):2024 年”≥5 行的重复代码块”出现频率同比 8 倍;copy/paste 首次超过 moved。
GitClear《The Maintainability Gap》(2026-06):2023–2026 共 6.23 亿次改动——refactoring 下降 70%、legacy 维护下降 74%、代码块重复上升 81%、error-masking 上升 47%。
这两组数据揭示了”允许重复”的真实代价,而且这个代价不在”重复”本身,在没有人再回头合并。
Dejan Menges《When code gets cheaper, architecture gets more expensive》(2026-10-11):
AI agent 能产出正确的改动,却不理解它属于哪里。保持系统内聚,正在变得更重要,而不是更不重要。
Martin Fowler × Unmesh Joshi《Conversation: LLMs and Building Abstractions》(2025-08-26) — 这条不是反对,而是给”抽象该放哪”定位。他们借 Brooks《No Silver Bullet》区分:
本质复杂度:软件实体本质的困难——数据集、关系、算法、函数调用。偶然复杂度:今天伴随生产而来的、并非本质的困难。
LLM 擅长削减偶然复杂度(语法、框架集成、样板代码)。但”写软件”本身是:切分问题、把相关数据与行为绑定、选择暴露意图的名字——
编程有两个深度交织的活动:发现并稳定抽象(创造性工作,人主导),和应用稳定抽象(有了稳定的词汇,LLM 就能机械执行)。
于是抽象的落点被重新定位了:从”代码复用”移到”领域词汇与稳定命名”——正好落在你我共识的那一层。
他们还提到 USI(Upfront Specification Impossibility):第一版规格最多是一个假设。这提醒我们:规格源本身也需要迭代,不能一次写死。
Grady Booch(UML 之父):AI 是新的一层抽象,软件工程的本质难题从未消失。
彭鑫(复旦)《智能化时代的软件工程:拥抱大模型的正确姿势》:瓶颈不在”AI 能否写好代码”(执行复杂度),而在”人如何准确高效地传达复杂任务目标”(目标传达复杂度);专家知识需要体系化、结构化沉淀。
大淘宝技术《AI Coding 思考》:企业级场景真正的瓶颈是专家知识未体系化、信息熵过高、上下文工程靠”人肉手艺”、知识重复建设。
这两条与”共享的是知识与词汇,而不是代码行数”完全同向。
8.3 业界共识
几乎没有人主张”抽象不重要”。真正的共识是三条:
- 错误抽象的代价在 AI 时代上升了——AI 的错抽象看起来更专业、更光滑,审查者更容易放行;
- 写第二套的代价下降得更多——所以”再等等看会不会出现第三个实例”的等待成本大幅下降;
- 因此抽象的门槛应该抬高、落点应该上移——从代码复用,移到领域词汇、领域模型、不变量与规格。
九、一个副产品:Convention over Abstraction 真的成立了
Ward Cunningham 当年说 “Convention over Configuration”,本意是”约定优于配置”。
今天更贴切的说法是:约定优于抽象(Convention over Abstraction)。
理由很实在:AI 生成与修改代码,靠的是模式匹配与结构可预测性。一份”整齐划一、意图直白、允许重复”的代码库,对 AI 的读写可靠性,远高于一个”精巧的通用引擎 + 一堆配置”。
通用引擎的分支组合空间,正是 AI 最容易出错的区域——生成的代码”看起来对”,实际漏了某个参数组合。反过来,两份各写各的完整实现,每份都是自洽的直白逻辑,AI 改动的爆炸半径也小得多。
所以在 AI 时代,代码库形态的最优解正在从复用最大化转向结构可预测性最大化:
- 命名统一、目录形态统一;
- 每份实现自洽、术语用业务语言;
- 通用机制用配置表达,而不是用隐式分支表达。
十、什么时候”重复”会翻车
原观点有明确的边界。以下情形需要收回:
- 跨团队 / 多实例:5 个以上团队各写一套”类似”规则,口径必然分裂;
- 规则被外部承诺:对客或对监管承诺过的口径,不允许两份实现;
- 强演进的领域:某天需要把 A、B 一起重构,重复版本会让改动成本翻倍;
- 错误代价不对称且不易发现:静默的算错、漏掉的分支,测试覆盖不到就永远潜伏;
- AI 加剧重复:模型每次生成都可能”再发明一遍”相似逻辑,两份实现会像”不同作者写的”——风格、命名、边界处理都不同,持续制造阅读噪声。
判断重复是否翻车,看一件事:这两份实现分歧了,谁会发现、多快会发现、后果多严重。 没人发现 = 灾难;测试一跑就炸 = 自由。
结语:稀缺的不再是”怎么抽象”,而是”何时抽象”
在一个 AI 可以替你写出合规代码的时代,真正的稀缺能力不再是”怎样抽象”,而是”何时抽象”。
后者需要的不是技巧,是耐心——是对业务领域持续观察后形成的判断,以及在沉没成本面前敢于把抽象拆回去的冷静。
在代码可以被无限生成的时代,最快的路有时候不是抽出来,而是——就让它重复。
评论