<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>law on Kohsruhe</title>
    <link>https://www.kohsruhe.com/zh/tag/law/</link>
    <description>Recent content in law on Kohsruhe</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh</language>
    <managingEditor>kohsruhe@outlook.com (Leehyon HNG)</managingEditor>
    <webMaster>kohsruhe@outlook.com (Leehyon HNG)</webMaster>
    <lastBuildDate>Tue, 19 May 2026 09:44:02 +0800</lastBuildDate>
    
    <atom:link href="https://www.kohsruhe.com/zh/tag/law/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>[译] 软件工程 20 条定律</title>
      <link>https://www.kohsruhe.com/zh/2026/05/the-20-software-engineering-laws/</link>
      <pubDate>Tue, 19 May 2026 09:44:02 +0800</pubDate>
      <author>kohsruhe@outlook.com (Leehyon HNG)</author>
      <guid>https://www.kohsruhe.com/zh/2026/05/the-20-software-engineering-laws/</guid>
      <description>&lt;p&gt;软件工程中的核心规律本质上反映的是人在复杂系统、时间压力和协作环境中不可避免的行为模式，这些规律决定了系统如何构建、团队如何运作以及为什么项目常常偏离预期。原文由 Dr Milan Milanović 发布。&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>软件工程中的核心规律本质上反映的是人在复杂系统、时间压力和协作环境中不可避免的行为模式，这些规律决定了系统如何构建、团队如何运作以及为什么项目常常偏离预期。原文由 Dr Milan Milanović 发布。</p>
<blockquote>
<p>Original: <a href="https://newsletter.techworld-with-milan.com/p/the-20-software-engineering-laws">https://newsletter.techworld-with-milan.com/p/the-20-software-engineering-laws</a></p>
</blockquote>
<h2 id="引言为什么软件项目会失败系统会腐化团队会慢下来">引言：为什么软件项目会失败，系统会腐化，团队会慢下来</h2>
<p>大多数工程师都是用惨痛教训学会这些定律的。当你试图重写某个东西却没有交付预期结果时，或者当一个项目已经延期，再往团队里加工程师只会让它失败得更快。有时，当你开始用某个指标来衡量进度，整个团队就会开始想办法操纵这个指标。然后，六个月后，有人提到一条 1975 年的定律，恰好解释了发生的一切。</p>
<p>我也为此付出过代价：我花了半个职业生涯，用艰难的方式学会这些经验，很多人可能也一样。</p>
<p>下面列出的二十条定律，是我最常引用的那些，当然还有更多（后面会讲到）。软件开发定律解释了正在发生什么、即将发生什么，以及无论你多努力都行不通的是什么。其中一些定律已经有六十年历史。它们在 2026 年的软件开发中依然适用，在 2036 年也仍会适用，因为它们本质上并不是关于软件的，而是关于人们如何在时间压力下协作构建事物（基本上，其中很多只是人性的定律）。</p>
<p>这些定律不是告诉你该怎么做的规则。它们告诉你已经在发生什么，但最终仍然需要你来做决定。这些定律只是帮助你理解现状。</p>
<p>这些定律之所以能进入这个列表，是因为我亲眼见过它们发生在自己身上。我的书涵盖了全部五十六条定律。如果你只来得及记住二十条软件开发定律，我认为这些就是最重要的。</p>
<p>具体来说，我们会讨论以下定律：</p>
<ul>
<li><strong>Gall 定律</strong>：一个能够正常工作的复杂系统，总是从一个先前能够正常工作的简单系统演化而来。</li>
<li><strong>KISS</strong>：保持简单。除此之外的一切都是额外负担。</li>
<li><strong>Conway 定律</strong>：组织设计出的系统，会映射其沟通结构。</li>
<li><strong>Hyrum 定律</strong>：只要用户足够多，你 API 的每一个可观察行为都会变成某个人的依赖，无论契约怎么写。</li>
<li><strong>CAP 定理</strong>：分布式系统只能在一致性、可用性和分区容错性三者中保证其中两个。</li>
<li><strong>Zawinski 定律</strong>：每个程序都会不断膨胀，直到它能阅读邮件。不能做到这一点的程序，会被能做到的程序取代。</li>
<li><strong>Brooks 定律</strong>：向一个已经延期的软件项目增加人手，只会让它更晚完成。</li>
<li><strong>Ringelmann 效应</strong>：团队规模越大，个人产出越低。</li>
<li><strong>Price 定律</strong>：一半的工作由人数平方根那么多的人完成。</li>
<li><strong>Dunning-Kruger 效应</strong>：你对某件事知道得越少，往往越自信。</li>
<li><strong>Hofstadter 定律</strong>：事情总是比你预期的更久，即使你已经考虑了 Hofstadter 定律。</li>
<li><strong>Parkinson 定律</strong>：工作会膨胀，直到填满可用的时间。</li>
<li><strong>Goodhart 定律</strong>：当一个衡量指标变成目标时，它就不再是一个好的衡量指标。</li>
<li><strong>Gilb 定律</strong>：任何你需要量化的东西，都可以用某种比完全不测量更好的方式来测量。</li>
<li><strong>Knuth 优化原则</strong>：过早优化是万恶之源。</li>
<li><strong>Amdahl 定律</strong>：并行带来的加速受限于顺序执行的部分。</li>
<li><strong>Murphy 定律</strong>：凡是可能出错的，都会出错。</li>
<li><strong>Postel 定律</strong>：发送时要保守，接收时要宽容。</li>
<li><strong>Sturgeon 定律</strong>：任何事物中 90% 都是糟粕。</li>
<li><strong>Cunningham 定律</strong>：在网上获得正确答案最快的方法，是发布一个错误答案。</li>
</ul>
<p>那么，让我们开始吧。</p>
<p>想了解更多？<a href="https://techworldwithmilan.gumroad.com/l/lawsofsoftwareengineering"><strong>《软件工程定律》一书</strong></a> 📔 已经出版。</p>
<h2 id="系统是如何构建出来的">系统是如何构建出来的</h2>
<h3 id="1-gall-定律">1. Gall 定律</h3>
<p><strong>一个能够正常工作的复杂系统，总是从一个先前能够正常工作的简单系统演化而来。</strong></p>
<p>系统在现实生活中的运行效果，通常不会像纸面设计那样好，因为许多问题只有在进入真实世界后才会暴露。这些问题只有当真实用户开始使用系统时才会出现，而到了那时，系统要么能工作，要么不能。每一个能够正常工作的复杂系统，都是一步一步演化成这样的。那些一开始就试图做到完美的系统，通常都会失败。</p>
<p>这就是为什么大多数从零重写的新版本系统都不会成功：团队保留了之前拥有的所有功能，却丢掉了让旧系统好用的那些简单特质。</p>
<p><strong>示例：</strong> 以 Instagram 为例。最初，它其实是别的东西，并不是一个图片分享平台。这个应用叫 Burbn，里面把签到、游戏、照片分享全都塞在一起。后来，创始人砍掉了除照片分享之外的一切，这个精简后的核心就成了真正的产品。</p>
<p>Google Wave 则走向了相反方向。它一推出就同时包含聊天、电子邮件、论坛和文档编辑器。没人能说清楚它到底是做什么的，于是 15 个月后它就死掉了。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!xivn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c081e9e-92f0-429d-a297-1b10cac73543_1536x550.png" alt="Gall 定律插图"></p>
<h3 id="2-kiss-keep-it-simple-stupid">2. KISS (Keep It Simple, Stupid)</h3>
<p><strong>保持简单。除此之外的一切都是额外负担。</strong></p>
<p>KISS 原则提醒我们，简单性应该是我们的核心目标。如果你可以用一个 50 行脚本解决问题，而不是使用一个复杂的 500 行方案，那么 KISS 会偏向更简单的方案，因为每一行代码都有可能引入错误。</p>
<p>为什么简单性如此重要？软件总体上构建起来很复杂，而且必须由人来理解。简单的设计更容易维护：新团队成员能更快上手，Bug 更容易定位，修改造成的连锁影响也更少。</p>
<p>KISS 原则鼓励开发者抵制那种一次做太多事的“聪明”代码，也避免为了应对未来问题而设计出让当前复杂度上升的架构方案。</p>
<p><strong>示例：</strong> 假设有一家创业公司需要一个功能开关系统，并决定构建一个自定义方案。他们把它做成了一个独立的微服务，拥有自己的数据库、缓存、管理界面、WebSocket 通知和 A/B 测试支持。这引入了大量复杂性，也花了很多时间构建；一旦出问题，就会造成很多麻烦。</p>
<p>他们真正需要的只是一个 JSON 配置文件。这本来一个下午就能完成。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!xX-a!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F23a88e82-2f5c-4382-99e0-b8625c6d7d2a_1359x758.png" alt="KISS 插图"></p>
<h3 id="3-conway-定律">3. Conway 定律</h3>
<p><strong>组织设计出的系统，会映射其沟通结构。</strong></p>
<p>你的应用架构其实已经被定义好了，而且本质上与你的组织结构图相同。比如，如果有四个团队一起做一个项目，你最终很可能会得到一个由四个部分组成的应用。如果负责前端、后端和数据的团队彼此不沟通，你的应用就会有三个无法良好协作的部分。</p>
<p>如果你在不改变公司组织方式的情况下重写系统，你得到的仍然是同一个系统，只不过换了一种语言来写。</p>
<p>反过来也成立。你可以先选择想要的架构，然后创建自然会产出这种系统的团队。Amazon 在 2000 年代就这么做过。他们把系统拆成由小团队管理的小型服务，这改变了系统与公司的协作方式。这被称为“逆 Conway 操作”。</p>
<p><strong>示例：</strong> 许多现代 AI 组织经常把研究团队与应用工程团队分开。于是，研究团队优化基准测试，而产品团队面向真实用户发布应用。最终产出的是一个分数很好看的模型，以及一个并不好用的产品，因为双方都在围绕自己的沟通边界进行优化。</p>
<p>这种模式在小规模团队中也会出现。一个三人团队几乎总是会交付一个单体应用，因为把它拆开的成本高于让它保持在一起的成本。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!kdgR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e52fa1c-1ef8-489b-a18b-10c856835d40_883x529.png" alt="Conway 定律插图"></p>
<h3 id="4-hyrum-定律">4. Hyrum 定律</h3>
<p><strong>只要用户足够多，你 API 的每一个可观察行为都会变成某个人的依赖，无论契约怎么写。</strong></p>
<p>你写下的接口契约并不是真正的契约。真正的契约是你的系统实际做了什么，包括那些你从未预料到会重要的部分。例如，它可能是时序、错误消息文本、JSON 响应中的键顺序，以及哈希的精确字节。总有人在某个地方依赖着这一切。</p>
<p>这就是为什么成熟系统中的向后兼容成本如此之高。这意味着你实际维护的并不是你设计的 API，而是那个偶然形成的 API。</p>
<p><strong>示例：</strong> 一个很好的例子是 SimCity 游戏。我清楚地记得它有一个 use-after-free Bug，在 Windows 3.x 上运行没问题，因为内存实际上从未被回收。后来 Windows 95 开始回收这块内存，SimCity 就崩溃了。Microsoft 在 Windows 95 中加入了一个特殊的内存分配器模式，只在 SimCity 运行时启用，这样这个 Bug 就能继续“正常工作”。</p>
<p>浏览器在互联网规模上也会这样做。Web 开发者构建进平台的每一个怪癖，实际上都会成为平台的一部分。浏览器无法改变这些怪癖，否则会破坏半个 Web。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!sHLN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ad50394-1511-45c7-9795-a0609d1537fc_1440x762.png" alt="Hyrum 定律插图"></p>
<h3 id="5-cap-定理">5. CAP 定理</h3>
<p><strong>分布式系统只能在以下三者中保证其中两个：一致性、可用性和分区容错性。</strong></p>
<p>网络会失败。在分布式系统中，这不是你能绕开设计的问题，而是你必须接受的事实。一旦发生网络分区，你就必须选择：阻塞写入以保持数据一致，或者继续提供流量服务并允许副本产生偏差。每个分布式数据库都会做这个选择。大多数只是不会告诉你它选择了哪一个。它们藏在“最终一致性”或“高可用”这样的标签背后，直到事故发生时才让你发现真相。</p>
<p><strong>示例：</strong> MongoDB 偏向一致性，这意味着当发生分区问题时，一些 MongoDB 副本不会接受任何数据，直到整个系统重新正常工作。另一方面，Cassandra 即使在副本之间不一致时也会继续响应查询，并在之后修复不一致。MongoDB 和 Cassandra 都没有错。它们只是针对你的系统能承受失去什么，做出了不同选择。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!wvGB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72afbefa-1500-4d46-a351-a40d018c3745_720x647.png" alt="CAP 定理插图"></p>
<h3 id="6-zawinski-定律">6. Zawinski 定律</h3>
<p><strong>每个程序都会不断膨胀，直到它能阅读邮件。不能做到这一点的程序，会被能做到的程序取代。</strong></p>
<p>功能蔓延并不是过程中偶然发生的事情。它其实就是这个过程本身。当一个工具擅长它所做的事情，并且人们喜欢它时，人们就会一直使用它。负责产品的人希望让用户保持参与并留在平台上。于是这个工具开始承担与它相关的任务。久而久之，这个工具会变得非常缓慢，并拥有很多不必要的额外功能。</p>
<p>然后一个新的竞争者会带着更简单、能完成同样事情的版本出现。随着这个应用越来越受欢迎，越来越多不必要的功能又会被加进去。</p>
<p><strong>示例：</strong> 一个著名例子是 Netscape，它一开始是浏览器，最后变成了包含电子邮件、新闻和网页编辑器的套件。Firefox 作为修正方案出现，把它精简下来，变得流行，但后来又加入了插件和开发者工具链。</p>
<p>我们也记得 Slack，它最初是为了消灭电子邮件而推出的，如今却有语音、视频、机器人和应用目录。如果产品没有正确的北极星指标，这一切都会发生。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!a7Bu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e3847df-6da3-4ada-a98a-9773ce74d3a3_1316x652.png" alt="Zawinski 定律插图"></p>
<h2 id="团队是如何失去速度的">团队是如何失去速度的</h2>
<h3 id="7-brooks-定律">7. Brooks 定律</h3>
<p><strong>向一个已经延期的软件项目增加人手，只会让它更晚完成。</strong></p>
<p>软件工作并不容易在团队成员之间拆分。当你把一个新人带进项目时，他需要一段时间才能上手，这意味着有经验的人必须停下手头的工作来帮助新人学习。如果你的项目已经落后于计划，增加更多人并不会让它变快，只会让情况更糟。</p>
<p><a href="https://en.wikipedia.org/wiki/Fred_Brooks">Frederick P. Brooks</a> 说得很好：不能因为有九个女人怀孕，就能在一个月内生出一个孩子。软件工作也是如此。软件工作不会仅仅因为有人在做，就变得更快完成。</p>
<p><strong>示例：</strong> 有一次，我是一个八人团队的负责人，我们总是落后于计划。我的第一反应是再招两名工程师来帮助我们赶上进度。但与此同时，在我们寻找新人时，有两个人离开了团队。结果看起来一切反而更好了，沟通更容易，我们完成的事情也比以前更多。所以很明显，解决办法是让团队变小，而不是变大。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!KaO2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317eb53f-7e8b-48c2-8950-131604b27b3b_738x633.png" alt="Brooks 定律插图"></p>
<h3 id="8-ringelmann-效应">8. Ringelmann 效应</h3>
<p><strong>随着团队变大，人均产出会下降。</strong></p>
<p>当很多人一起拉绳子时，每个人都不会拉得那么用力。一部分原因是很难顺畅协作，另一部分原因是人们会认为别人会完成那部分工作。不管怎样，这种模式是真实存在的，而且比大多数人想象得更明显。</p>
<p><strong>示例：</strong> 一项大型 <a href="https://doi.org/10.1007/s10664-015-9406-4">GitHub 研究</a> 直接测量了这一点。2 到 5 人团队中的开发者，平均每月编写约 1,850 行代码；而 10 人团队下降到 1,200 行。到 50 人或更多时，则是 450 行。人均产出下降了 75%。</p>
<p>这就是为什么小团队比大团队交付更快，也解释了为什么 Amazon 的“两块披萨规则”仍然成立。它是在防御 Ringelmann 效应。尤其是在今天这个 AI 驱动的世界里，这一点更加明显，因为 AI 正在提高个人和团队生产力，高产团队的人数比以前更少。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!52T0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb63851e9-2bf1-445f-9146-81b698d4fa56_2169x1221.png" alt="Ringelmann 效应插图"></p>
<h3 id="9-price-定律">9. Price 定律</h3>
<p><strong>一半的工作由人数平方根那么多的人完成。</strong></p>
<p>在一个 100 人的群体中，大约 10 个人真正完成了一半重要的工作。如果你有一个 16 人的群体，很可能是 4 个人完成了大部分工作。这适用于每一个创造性领域。</p>
<p>群体中完成大部分工作的人非常重要，但其他人也很重要，因为他们会做那些支持所有人所必需的工作。他们确保一切正常运转（有时称为胶水工作）。所以我们需要这两类人，但问题在于，如果你团队中的顶尖人员离开，团队完成事情的能力会大幅下降。</p>
<p><strong>示例：</strong> 我们都知道，当 Musk 接管 Twitter 时，公司裁掉了大约 50% 的员工，而网站仍然继续运行。Price 定律预测到了这一点。但这条定律没有预测到的是，裁员带走了什么：信任与安全方面的深度、SRE 覆盖，以及事故响应能力。顶尖员工让系统继续运转。组织却失去了处理下一个难题的能力，后来 Twitter 悄悄请一些被裁员工回来。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!xmEo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4764fa03-dca2-4731-bbe8-7c29bcb5fe50_1731x884.png" alt="Price 定律插图"></p>
<h2 id="计划为什么会漂移">计划为什么会漂移</h2>
<h3 id="10-hofstadter-定律">10. Hofstadter 定律</h3>
<p><strong>事情总是比你预期的更久，即使你已经考虑了 Hofstadter 定律。</strong></p>
<p>假设你需要估算某件事要花多久。你认为四周是一个估算值，但随后你想起自己的估计通常过于乐观，所以为了保险起见，把它翻倍到八周。但最终，它花了十六周。</p>
<p>现在你想，下一次你会做得更好，对吧？你认为它会花十六周，因为上次就是这样。不，它这次会花三十二周，因为你不知道的事情会让你意外。这些事情包括计划外的集成问题或需求变更。</p>
<p>在实践中，Hofstadter 定律解释了为什么估算加缓冲、意识到 Parkinson 定律，以及使用历史数据等技术都很必要，但意外仍然会发生。</p>
<p><strong>示例：</strong> Hofstadter 定律的一个好例子是 Berlin Brandenburg Airport 项目。软件集成过程比预期花费了长得多的时间，因为它涉及 75,000 个传感器和 50,000 个照明装置。原计划用 18 个月完成，但后来他们意识到这不可能，于是把时间线延长到 30 个月。最终，它花了 7 年才完成，最终成本达到 70 亿欧元，比计划高出 2.5 倍，机场晚开通了 9 年。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!atRn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3999c866-cdd9-49cf-9b82-cff3c07b9073_1467x951.png" alt="Hofstadter 定律插图"></p>
<h3 id="11-dunning-kruger-效应">11. Dunning-Kruger 效应</h3>
<p><strong>你对某件事知道得越少，往往越自信。</strong></p>
<p>令人不舒服的部分在这里。你完成某件事所需要的技能，和你判断自己完成得好不好所需要的技能，是同一种技能，而这正是问题所在。不太擅长某件事的人看不到自己哪里做错了，所以会以为自己比实际更擅长。而真正擅长的人能看到自己仍然做错的所有地方，所以会以为自己没有实际那么擅长。</p>
<p><strong>示例：</strong> 当被问到某件事什么时候能完成时，新开发者经常给出自信而精确的估计，而有经验的开发者会给出范围（也就是著名的“看情况”回答）。初级开发者并不是故意错得自信。他们只是还不知道自己不知道什么（未知的未知）。</p>
<p>人们通常会在一开始对新技术非常兴奋。这是因为他们还没有大量使用它。我们现在正在看到这种情况发生在 Artificial Intelligence 上。那些说 AI 什么都能做的人，通常是那些并不每天使用它的人，比如管理者。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!yN7_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a861def-2e08-485e-848e-082fe252d333_2392x1464.png" alt="Dunning-Kruger 效应插图"></p>
<h3 id="12-parkinson-定律">12. Parkinson 定律</h3>
<p><strong>工作会膨胀，直到填满可用的时间。</strong></p>
<p>如果你给开发者两周时间去做一个两天就能完成的任务，它就会花两周完成。这并不意味着开发者懒惰或拖延。人们倾向于把手头拥有的时间填满。在这两周里，开发者很可能会花时间制定计划、尝试方案，并添加一些并不需要完成的额外任务（镀金）。但如果截止日期是一天内完成，它很可能当天就会完成。</p>
<p>Parkinson 定律的要点是，如果你给人们一定的时间去做某件事，他们很可能会用满全部时间。所以，团队应该设定清晰且现实的时间限制（也就是 deadline-driven development）。不过，管理者必须审慎使用它，把 Parkinson 的洞察与现实的排期结合起来。如果你把时间线压缩得太厉害，就可能撞上 Hofstadter 定律，它提醒我们，即使有缓冲，工作通常仍然会比预期更久。</p>
<p><strong>示例：</strong> 一个开发者如果被给了两个月来完成一个一周的任务，可能会花一个月做不同方案的原型，另一周争论架构，最后三周打磨没人要求的细节。如果同一个任务被给出明确的一周截止日期，它就会在一周内交付。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!8gNo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c3e0fca-438b-4138-9111-87fa05cb74bb_2007x1329.png" alt="Parkinson 定律插图"></p>
<h2 id="指标如何扭曲工作">指标如何扭曲工作</h2>
<h3 id="13-goodhart-定律">13. Goodhart 定律</h3>
<p><strong>当一个衡量指标变成目标时，它就不再是一个好的衡量指标。</strong></p>
<p>我们可以用很多不同方式来衡量工作，例如关闭的 Bug 数量、事故数量、测试覆盖率或团队速度。当我们开始根据这些东西来衡量人的绩效时，他们就会专注于让这些数字看起来更好，而不是真正把工作做好。</p>
<p>数字会上升，但工作不会变得更好。这是因为当我们给人们激励时，他们会做能获得奖励的事，而不是我们真正想要的事。当我们衡量错误的东西时，人们就会为了领先而做错误的事。</p>
<p><strong>示例：</strong> 我见过一个团队在 2000 年初因为编写代码行数而获得奖励，几年后又因为创建 PR 的数量而获得奖励。开发者开始复制粘贴，而不是抽取共享逻辑。有些人几乎为每一次提交都创建一个 PR。</p>
<p>现代版本是每位工程师消耗的 AI token 数量（称为 <a href="https://techcrunch.com/2026/04/17/tokenmaxxing-is-making-developers-less-productive-than-they-think/">tokenmaxxing</a>）。更多 token 正被当作生产力的标志。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!9ku2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc023fa5-e4ab-4a6c-b856-b4717730d68d_1422x815.png" alt="Goodhart 定律插图"></p>
<h3 id="14-gilb-定律">14. Gilb 定律</h3>
<p><strong>任何你需要量化的东西，都可以用某种比完全不测量更好的方式来测量。</strong></p>
<p>Gilb 定律就像 Goodhart 定律的另一面。看着 Goodhart 定律时，你可能会说，有指标是坏事，但这其实并不对。完全没有指标甚至更糟。如果某件事对你很重要，你就应该尝试找到一种方式来衡量它，因为我们无法改进那些不测量的东西（正如 Peter Drucker 的名言所说）。</p>
<p><strong>示例：</strong> 开发者生产力通常很难衡量，而且一直如此。我们曾有许多糟糕的指标，从代码行数到 token 消耗。但部署频率和变更前置时间可以作为代理指标给你提供信号（就像 DevOps 中的 DORA 指标）。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!uNbg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5c1ba61e-ce21-4f6e-af73-2e41cf28df57_683x374.png" alt="Gilb 定律插图"></p>
<h2 id="什么会在负载下崩坏">什么会在负载下崩坏</h2>
<h3 id="15-knuth-优化原则">15. Knuth 优化原则</h3>
<p><strong>过早优化是万恶之源。</strong></p>
<p>大多数性能工作发生得太早，而且发生在错误的地方。团队优化那些永远不会成为热点的代码路径，引入并不需要的复杂性，并把时间耗在解决一个他们也许永远不会达到的规模问题上。</p>
<p>所以最好的方式是先写出能工作的代码，然后检查它的性能。如果有问题，工具会告诉你问题在哪里。如果没有，就继续前进。</p>
<p><strong>示例：</strong> 我曾在一家创业公司工作，我们花了大量时间搭建 Kubernetes。问题在于，我们这么做是为了支撑数百万用户，而当时我们甚至还没有 10 个用户。我们在为不存在的负载准备基础设施。我们的产品功能甚至还没有完成。</p>
<p>我的一位同事说，在我们担心如何支撑数百万用户之前，应该先确认是否有 100 个人真正想要我们的产品。他是对的。我们最终还是延期发布了。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!Xws3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9209e92f-5b2b-481e-9681-51e1231d5a94_671x384.png" alt="过早优化（Knuth 优化原则）插图"></p>
<h3 id="16-amdahl-定律">16. Amdahl 定律</h3>
<p><strong>并行带来的加速受限于顺序执行的部分。</strong></p>
<p>如果你 10% 的工作必须顺序完成，那么无论你使用多少台计算机，整体工作最多只会快 10 倍。如果 50% 的工作必须一件一件做，那么整体最多只会快 2 倍。</p>
<p>同样的事情也会发生在人身上。如果有一组人必须对关于构建方式的每个决策都点头同意，那么无论你有多少工程师，这都会限制团队的工作速度。如果你增加工程师，但他们都必须等待同一组人批准，那么排队的人只会变得更长。你的工程师团队仍然会很慢，因为做决策的那组人就是瓶颈。工程师团队的工作速度，只能快到决策者那组人的速度。</p>
<p><strong>示例：</strong> 通过增加更多应用服务器来扩展 Web 流量是有帮助的，直到每个请求都打到同一个共享数据库或认证服务上。此时，继续增加横向扩展就没有用了。</p>
<p>关于 AI 生产力的讨论现在也触到了天花板。AI 让编码更快，但你仍然必须思考、检查、修复错误，并在那些无法同时完成的步骤上协作。这限制了你最终能获得的收益。这就是为什么有些工程师看到自己的工作速度提升 10 倍，而另一些人只看到 1.2 倍提升。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!2G1b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd4473529-5915-4626-bf5f-fb3b1bc5d656_2560x1873.png" alt="Amdahl 定律插图"></p>
<h3 id="17-murphy-定律">17. Murphy 定律</h3>
<p><strong>凡是可能出错的，都会出错。</strong></p>
<p>在软件中，Murphy 定律经常被用来解释 Bug 和生产事故：代码中任何可能出错的地方（空指针、竞态条件、网络中断）最终都会显现出来，尤其是在大规模用户场景下，或者在最糟糕的时间点（周五晚上）。</p>
<p>在实践中，这条定律鼓励开发者编写更具防御性的代码。这意味着检查空值、处理异常、验证输入，并在错误发生时优雅失败。它也提醒 DevOps 团队通过实现监控、启用回滚和维护应急计划来预判故障。</p>
<p><strong>示例：</strong> 2024 年 7 月 19 日，CrowdStrike 对 Falcon Sensor 设置进行了变更。这个变更在 Windows 机器上造成了内存问题，使 850 万台 Windows 机器停止工作并显示蓝屏。为了解决这个问题，必须有人登录到每台机器并应用修复，因为那些机器无法启动。这个过程无法远程完成。而这一切发生在一个周五早晨，当时没有 IT 员工在工作。它给航空公司、医院和银行都造成了问题。那天，所有可能出错的事情都出错了，正如 Murphy 定律所说。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!oa9O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfe372b6-9a31-43df-bf11-7ec4397ffbae_1183x677.png" alt="Murphy 定律插图"></p>
<h3 id="18-postel-定律">18. Postel 定律</h3>
<p><strong>发送时要保守，接收时要宽容。</strong></p>
<p>这条定律说，如果你的服务器发送 HTTP 响应，它应该严格按照规范格式化标头。但如果你的服务器收到一个 HTTP 请求，其中标头顺序不常见或格式不寻常，只要你能安全地解释它，就应该继续处理，而不是直接断开连接。</p>
<p>浏览器在规模上就是这么做的。Web 上的大多数 HTML 都写得不正确，但现代浏览器仍然会渲染它们。如果浏览器很严格，半个互联网都找不到了。</p>
<p>但有一件事需要考虑。过于宽容是有代价的：如果每个人都接受任何东西，问题就永远不会被纠正，只会变得更加混乱。</p>
<p>在安全敏感的代码中，容忍输入可能会让攻击者更容易找到漏洞。所以，基本思想仍然成立。你需要运用判断力，因为宽容并不等于放任。</p>
<p><strong>示例：</strong> 在 API 中，假设你的服务期望一个时间戳。如果它收到一个没有时区的时间戳，你可以不直接拒绝，而是假设它是 UTC，或者仍然尝试解析它，这就是在接收时保持宽容。但当你的服务返回数据时，你总是包含时区，以确保输出保守且精确。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!oOF5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff51e1938-a1a6-4ce8-a432-b95cf2707e8b_534x268.png" alt="Postel 定律插图"></p>
<h2 id="如何更好地判断">如何更好地判断</h2>
<h3 id="19-sturgeon-定律">19. Sturgeon 定律</h3>
<p><strong>任何事物中 90% 都是糟粕。</strong></p>
<p>我们创造的大多数东西都不会被使用，我们写的大多数代码也并不好。我们启动的大多数项目，并不会交付我们以为它们会带来的价值。这本身并不是坏事。这就是我们试图创造新事物时的现实。如果我们假装一切都很棒，就会以同样方式对待每个项目，这会让事情变得过于复杂。</p>
<p>真正重要的是那些项目中的少数，比如 10%。找到这些项目，并摆脱其余项目，才是真正需要技巧的地方。</p>
<p><strong>示例：</strong> WordPress 的目录中大约有 57,000 个插件。其中超过 34,000 个在过去 2 年没有更新，近 19% 的插件没有任何活跃安装。少数维护良好的插件支撑着超过 40% 的公开 Web。这种分布就是 Sturgeon 定律的一张截图。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!_hX1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F100c340d-b7a9-4eba-9fa2-3f331498f6d9_1291x897.png" alt="Sturgeon 定律插图"></p>
<h3 id="20-cunningham-定律">20. Cunningham 定律</h3>
<p><strong>在网上获得正确答案最快的方法，是发布一个错误答案。</strong></p>
<p>当你在某个在线论坛上提问时，通常得不到回应。如果你发布了明显错误的内容，人们就会跳出来纠正你。他们看到一个问题时可能只是路过，但当看到错误内容时，往往忍不住要纠正。你其实可以利用这一点。如果你在某件事上遇到困难，不要问你应该怎么做。相反，提出一个你知道并不太好的方案，或者分享一个草稿，然后看看会发生什么。正确答案可能会在你甚至没有主动提问的情况下出现。</p>
<p>请注意，这个技巧只有在你周围的人知道自己在说什么时才有效。如果你所在的群体里，每个人都和你一样困惑，那么一个错误答案实际上可能弊大于利。在这种情况下，错误答案可能会变成人们开始相信的信息。</p>
<p><strong>示例：</strong> Wiki 以及后来的 Wikipedia 的整个赌注，都是建立在这个洞察之上的。人们纠正错误的速度，比从零开始写文章更快。这个赌注在文明尺度上获得了回报。</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!vphl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdb910e25-0f2d-45ae-a4c2-3612be0c0562_1536x1024.png" alt="Cunningham 定律插图"></p>
<h2 id="结论">结论</h2>
<p>在这篇文章中，我分享了一些我在职业生涯中见过的最有影响力的定律。你不必把它们全部记住。前五六条定律就能帮助你解决大多数问题。其余定律，则是在新问题出现时派上用场。</p>
<p>更重要的是知道一条定律什么时候适用，什么时候不适用。这二十条定律经常相互冲突。Knuth 说不要过早优化。Amdahl 说要找到并修复项目中拖慢一切的部分。两者在某些时候都是正确的。关键在于知道现在该用哪一条。</p>
<p>另外，这个列表是我的列表。你的列表会不同。那些曾经给你造成问题的定律，对你而言会比那些没有造成过问题的定律更重要。随着时间推移，你会添加自己的定律。当你注意到它们时，把它们写下来。每个项目、事故或重写记录一行。哪条定律帮到了你？哪条定律给了你建议？发生了什么变化？你的个人列表会比我能给你的任何列表都更有帮助。</p>
<p>自从 Brooks 在 1975 年写下他的书以来，框架、平台和部署模型都已经改变了。但这些定律没有改变。它们描述的是唯一没有改变的东西：<strong>人类在尚未完全理解的约束下共同构建事物。</strong></p>
<p>这就是为什么它们值得在项目出问题之前学习，而不是之后才学习。</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>