Hacker News 中文摘要

RSS订阅

海勒姆定律 -- Hyrum's Law

文章摘要

Hyrum定律指出,当API的用户数量足够多时,无论接口合同中承诺了什么,系统的所有可观察行为都会被某些用户依赖。在实践中,随着系统使用量的增加,用户往往会依赖接口中无意暴露的实现细节,导致接口与实现之间的理论分离失效。

文章总结

标题:海勒姆定律

内容概述:

海勒姆定律是软件工程领域的一个观察结果,其核心观点是:当一个API拥有足够多的用户时,无论你在接口中承诺了什么,系统的所有可观察行为都会被某些用户所依赖。这一现象在复杂的软件系统中尤为明显,尤其是在进行底层基础设施迁移时。

在软件系统中,接口通常被视为与系统交互的抽象(如汽车的方向盘和踏板),而实现则是系统完成工作的方式(如车轮和发动机)。这种抽象有助于管理系统的复杂性,因为大多数有用的系统很快变得过于复杂,单个个体或团队无法完全理解。然而,随着系统使用量的增加,用户开始依赖通过接口有意或无意暴露的实现细节,这种现象被称为“泄漏抽象定律”。

当这种现象发展到极致时,就形成了“隐式接口定律”:只要有足够多的用户,就不存在私有的实现。也就是说,如果接口有足够多的用户,他们将会集体依赖实现的每一个方面,无论是有意还是无意。这种效应限制了实现的变更,因为实现现在必须同时符合明确记录的接口和通过使用捕获的隐式接口。这种现象通常被称为“bug-for-bug兼容性”。

隐式接口的形成通常是渐进的,用户往往在不知不觉中依赖这些接口。例如,接口可能没有对性能做出任何保证,但用户往往会对实现的性能产生某种期望。这些期望成为系统隐式接口的一部分,系统的变更必须保持这些性能特征,以继续为用户提供功能。

并非所有用户都依赖相同的隐式接口,但只要有足够多的用户,隐式接口最终将与实现完全匹配。此时,接口已经消失:实现成为了接口,任何对实现的更改都会违反用户的期望。尽管广泛的、全面的自动化测试可以检测到这些新的期望,但无法消除它们。

隐式接口是大型系统有机增长的结果,尽管我们可能希望这个问题不存在,但设计师和工程师在构建和维护复杂系统时应明智地考虑这一点。因此,要意识到隐式接口如何约束你的系统设计和演进,并知道对于任何相当流行的系统,接口的影响远比你想的要深远。

关于作者:

海勒姆是Adobe的首席科学家,之前在谷歌担任软件工程师。他专注于大规模代码变更工具和基础设施,并花费数年时间改进谷歌的核心C++库。海勒姆定律的提出源于他在工作中发现,即使是最简单的库变更也会导致某些遥远系统的失败。虽然这一观察由海勒姆提出,但将其命名为“海勒姆定律”并广泛推广的功劳归于泰特斯·温特斯。

历史背景:

相关的XKCD漫画:https://xkcd.com/1172/

评论总结

评论主要围绕Hyrum's Law(海勒姆定律)展开,讨论了API设计、用户依赖以及实现细节对软件变更的约束。以下是主要观点和论据的总结:

  1. API设计者与用户的视角差异

    • 从API设计者的角度看,Hyrum's Law是需要考虑的重要因素,但从用户的角度看,依赖未明确承诺的实现细节是不合理的工程实践。
    • 引用:“从API设计者的角度看,Hyrum's Law是必须考虑的,但从用户的角度看,这是工程上的失职。”(From an API designer's standpoint, Hyrum's Law is something that has to be taken into account. But from a user's standpoint, it is engineering malpractice, plain and simple.)
  2. 随机化实现以阻止依赖

    • 通过随机化实现细节(如Go语言中map的遍历顺序),可以防止用户依赖未承诺的行为,减少潜在的错误。
    • 引用:“Go语言中map的遍历顺序总是随机的,以防止依赖顺序导致的微妙错误。”(For instance, traversal order of maps in Go is always randomized, to prevent subtle bugs caused by depending on the order.)
  3. 用户对未承诺行为的依赖

    • 即使API未明确承诺某些行为,如果这些行为在实践中一致,用户往往会依赖它们,导致变更时出现问题。
    • 引用:“即使你在合同中明确否认对某些行为的保证,如果你通常提供这种行为,大多数客户都会依赖它。”(Even if you explicitly deny a guarantee of a certain behavior in your contract, if you usually deliver that behavior, most of your customers will depend on it.)
  4. API设计中的断言机制

    • API应提供断言选项,以确保调用时的行为符合预期,避免依赖未承诺的实现细节。
    • 引用:“API应始终有一个‘assertions: true’选项。为什么普通函数调用可以有断言/不变性检查,而API调用不能?”(This is why an API should always have an 'assertions: true' option. Why should normal function calls have assertion/invariant checks, and not API calls?)
  5. LLM(大语言模型)中的类似问题

    • 在LLM领域,由于输出行为没有明确的合同保证,且可能随更新而变化,下游系统需要评估机制来应对这种不确定性。
    • 引用:“在LLM的输出中,合同中没有明确的承诺,只有可观察的行为,且这些行为可能随每次更新而变化。”(In terms of output of an LLM, there is no clear promise in the contract, only observable behaviour. Also the observable behaviour is subject to change with every update in LLM.)
  6. 软件作者的自主权

    • 软件作者有权定义API的规则,用户依赖未承诺的行为是用户的责任,而非作者的义务。
    • 引用:“我的API是我所说的那样,如果你依赖我没有保证的东西,那是你的问题,不是我的。”(my API is what I say it is and if you rely on something that I don't guarantee that's on you and not me.)
  7. 历史案例与Hyrum's Law的普遍性

    • 历史上,用户依赖未定义但一致的行为(如Commodore 64的非法操作码)是普遍现象,软件变更因此受到约束。
    • 引用:“这让我想起了Commodore 64中的‘非法操作码’。我相信它们之所以保留,是因为客户依赖它们。”(This reminds me of the 'illegal opcodes' in Commodore 64. I suspect, it was deliberate since 'customers relied on them'.)

总结:评论中既有对Hyrum's Law的理解和认同,也有对其约束力的质疑,强调了API设计者与用户之间的责任划分,以及通过技术手段(如随机化实现、断言机制)减少依赖的必要性。