AI、熵与现代软件中的收敛幻觉
Source: Dev.to
请提供您希望翻译的完整文本内容,我将按照要求保留源链接并将正文翻译成简体中文。
系统的变化速度快于团队对必须保持真实的共识
代码不断演进,功能不断累积,测试套件也在增长——然而信心却在悄然流失。测试不再充当护栏,反而开始制造噪音。
不久前,我读到 Khalil Stemmler 的一个洞见,它彻底改变了我对软件系统的看法。他将创造描述为两种力量的平衡:divergence(发散)和 convergence(收敛)。
“要在世界上创造任何事物,都依赖这两种创造性力量:发散和收敛。”
— Khalil Stemmler, Why You Have Spaghetti Code
Divergence
- Expansion
扩展 - Emergence
出现
发散是我们进行探索的阶段。我们尝试不同的方法,生成变体,勾勒方案,并通过实践学习。
- 大多数发散工作成本低且可逆:想法可以被抛弃,代码可以重写,测试可以删除。
- 这里的目标不是 正确性,而是 理解——在决定最终方案之前,先扩展可能可行的空间。
Convergence
- Contraction
收敛 - Contracts
收敛是我们做决定的阶段。我们将众多可能性压缩为少数承诺,使系统能够抵御未来的变化。
- 收敛工作是有意为之且成本更高,因为它会创建未来工作必须遵守的约束。
- 这正是 contracts 形成的地方:关于结构、行为和不变量的决策,系统将随时间主动维护这些约束。
平衡的必要性
健康的系统需要两种力量。当它们失去平衡时,熵会悄然渗入。在另一篇关于遗留代码的文章中,Khalil 将熵用作一种隐喻,描述当分歧没有随之而来的收敛时会发生的情况:
“就像熵是宇宙的自然状态,代码也倾向于随时间变得混乱。测试充当一种‘熵逆转’机制。”
— Khalil Stemmler, How to Improve Legacy Code w/ Characterization Tests
探索仍在继续,但决策从未彻底锁定。系统在扩展,却从未真正安定下来。
AI 辅助开发
这种框架深深触动了我,尤其是在我深入 AI 辅助开发时。
- 起初,我对看到我的测试套件蓬勃发展感到兴奋,但这种兴奋并没有持续太久。
- 模式更改和重构变得越来越困难。小的改动会在整个系统中传播。
- 我对测试套件的信心慢慢下降。我很快意识到 这些新测试中很少有真正代表我记得自己做出的决策。
由 LLM 驱动的发散
大型语言模型在发散性工作方面表现异常出色。它们快速探索、生成备选方案,并以人类难以匹配的速度迭代。这使它们成为学习、实验和早期探索的强大工具。
变化的不是发散的功能,而是其成本: 现代 AI 工具显著降低了探索解空间所需的努力。
当发散几乎无摩擦时,系统的扩展速度超过人类收敛的速度——评审变得更浅,测试因惯性被合并,合同累积而无人记得曾同意。这就是为什么 AI 起初常让人感到赋能——但随时间会导致不稳定。
收敛必须保持人为所有
如果使用得当,AI 支持发散并为判断提供信息。但让 AI 接管 收敛决策——在没有人为所有权的情况下锁定需求、边界、合同——不仅没有帮助,反而通过削弱本应抵抗混乱的机制,主动加速熵的增长。
这些决策数量虽少,却影响不成比例。我也是吃了苦头才明白的。
测试作为收敛机制
接口和模式收敛结构;测试收敛行为。
测试常被描述为验证工具:一种检查系统是否按预期运行的方式。虽然这并没有错,但把它们视为收敛机制会让它们更加强大。
- 它们不应仅仅描述系统当前是如何工作的——这正是源代码的职责。
- 它们应当定义系统在演进过程中必须继续保持的行为。
编写测试,就像编写代码一样,可能涉及探索。我们尝试场景,探查边界情况,了解系统的行为。当我们决定哪些信号足够稳定以进行编码,哪些行为应当成为契约时,测试工程的收敛行为就开始了。
当测试很好地承担了此角色时,它们会让变更更安全。重构不再令人畏惧,因为系统已经就必须保持真实的内容达成一致。
当它们没有发挥作用——当测试镜像实现细节或硬编码偶然行为时——它们就无法收敛系统。它们不是在逆转熵增,反而通过把系统绑定到本不该稳定的东西来放大熵增。
合约寿命
合约的价值取决于其预期的有效时长。有些合约寿命短暂;而另一些则旨在经受多年变迁。对合约的投入努力应与其寿命成比例。
单元测试
- 将合约 编码靠近实现。
- 有价值,但往往不稳定。
- 随着代码重构、抽象层次变化或职责转移而改变。
- 在精确度与寿命之间进行权衡。
面向用户(端到端)测试
- 将合约 编码在系统与用户的边界。
- 描述 产品的功能,而不是其内部构建方式。
- 通常能够超越内部变更的寿命:重构、API 变更,甚至完整的架构改造。
指标陷阱
当团队在需要稳定合约的场景中使用短期合约时,会出现问题。度量指标通过奖励 测试的存在 而不是 它们所编码的承诺的强度,进一步强化了这一错误。
- 覆盖率上升,但信心 没有提升 —— 因为系统正朝错误的方向收敛。
使用 AI 生成大量测试代码或记录满足覆盖率指标的用户流程是很诱人的。但这些产物很少能够编码长期意图。它们看似收敛,却使底层的承诺仍然浅薄。
要点
合同预期要经受更长时间的变更,其收敛努力就必须越加审慎。平衡 AI 驱动的发散与人为引导的收敛能够抑制熵的增加,并保持对系统演化的信心。
Generate we must be in defining it, and no contract is longer-lived than the promises we make to users.
The forces here aren’t new. Software has always required exploration followed by consolidation. What has changed is how cheap exploration has become.
AI accelerates divergence. Convergence — deciding what must remain true — is the bottleneck.
That decision shows up as contracts.
Some contracts are short‑lived and can change freely. Others are meant to survive refactors, rewrites, and architectural shifts. The longer a contract is expected to hold, the more deliberate we need to be about defining it.
Testing is where this tension becomes visible.
Seen through this lens, ask yourself:
- Which of your tests are actually reducing entropy — and which are quietly increasing it?
测试是这种张力变得可见的地方。
从这个视角审视,问问自己:
- 哪些测试真正降低了熵——而哪些却在悄悄增加熵?