对开发人员有用的定律、理论、原则和模式。(Laws, Theories, Principles and Patterns that developers will find useful.)
定律
- 90-9-1 法则 (90–9–1 Principle or 1% Rule)
- 阿姆达尔定律 (Amdahl's Law)
- 破窗效应 (The Broken Windows Theory)
- 布鲁克斯法则 (Brooks's Law)
- CAP 定理 (CAP Theorem or Brewer's Theorem)
- 康威定律 (Conway's Law)
- 坎宁汉姆定律 (Cunningham's Law)
- 邓巴数字 (Dunbar's Number)
- 邓宁-克鲁格效应 (The Dunning-Kruger Effect)
- 费茨法则 (Fitts's Law)
- 盖尔定律 (Gall's Law)
- 古德哈特定律 (Goodhart's Law)
- 汉隆的剃刀 (Hanlon's Razor)
- 席克定律 (Hick's Law or Hick-Hyman Law)
- 侯世达定律 (Hofstadter's Law)
- 哈伯特定律 (Hutber's Law)
- 技术成熟度曲线 (The Hype Cycle or Amara's Law)
- 隐式接口定律 (Hyrum's Law or The Law of Implicit Interfaces)
- 柯林汉定律 (Kernighan's Law)
- 林纳斯定律 (Linus's Law)
- 梅特卡夫定律 (Metcalfe's Law)
- 摩尔定律 (Moore's Law)
- 墨菲定律 (Murphy's Law / Sod's Law)
- 奥卡姆剃刀 (Occam's Razor)
- 帕金森定理 (Parkinson's Law)
- 过早优化效应 (Premature Optimization Effect)
- 普特定律 (Putt's Law)
- 里德定律 (Reed's Law)
- 复杂性守恒定律 (The Law of Conservation of Complexity or Tesler's Law)
- 得墨忒耳定律 (The Law of Demeter)
- 抽象泄漏定律 (The Law of Leaky Abstractions)
- 帕金森琐碎定理 (The Law of Triviality)
- Unix 哲学 (The Unix Philosophy)
- Spotify 模型 (The Spotify Model)
- 沃德勒定律 (Wadler's Law)
- 惠顿定律 (Wheaton's Law)
原则
- 乔治·伯克斯定律 (All Models Are Wrong or George Box's Law)
- 切斯特森围栏 (Chesterson's Fence)
- 死海效应 (The Dead Sea Effect)
- 呆伯特法则 (The Dilbert Principle)
- 帕累托法则 (The Pareto Principle or The 80/20 Rule)
- 舍基原理 (The Shirky Principle)
- 彼得原理 (The Peter Principle)
- 鲁棒性原则 (The Robustness Principle or Postel's Law)
- SOLID
- 单一功能原则 (The Single Responsibility Principle)
- 开闭原则 (The Open/Closed Principle)
- 里氏替换原则 (The Liskov Substitution Principle)
- 接口隔离原则 (The Interface Segregation Principle)
- 依赖反转原则 (The Dependency Inversion Principle)
- 不要重复你自己原则 (The DRY Principle)
- KISS 原则 (The KISS Principle)
- 你不需要它原则 (YAGNI)
- 分布式计算的谬论 (The Fallacies of Distributed Computing)
定律
90-9-1 法则 (90–9–1 Principle or 1% Rule)
90-9-1 法则表明,在诸如维基这样的互联网社区中,90% 的用户只看内容并不参与互动,9% 的用户会参与讨论,而只有 1% 的用户会创造内容。
现实世界的例子:
- 2014 年,对四个健康的数字社交网络进行的一项研究发现,排名前 1% 的人创造了 73% 的帖子,紧随其后的 9% 平均占 25%,其余的 90% 的人平均占 2%。 (参考)
参见:
阿姆达尔定律 (Amdahl's Law)
阿姆达尔定律显示了计算任务通过增加系统资源可以获得的加速潜力。该公式通常用于并行计算中。它可以预测增加处理器数量的实际收益,该收益受到程序可并行比例的限制。
举例说明:如果程序由 A、B 两个部分组成,A 部分必须由单个处理器执行,B 部分可以并行运行。那么向执行程序的系统添加多个处理器只能获得有限的好处。它可以极大地提升 B 部分的运行速度,但 A 部分的运行速度将保持不变。
下图展示了一些运行速度的提升潜能的例子:
可以看出,50% 并行化的程序在使用大于 10 个处理单元之后的速度提升收效甚微,而 95% 并行化的程序在使用超过一千个处理单元之后仍然可以显著提升速度。
随着摩尔定律减慢,单个处理器的速度增加缓慢,并行化是提高性能的关键。图形编程是一个极好的例子,现代着色器可以并行渲染单个像素或片段。这也是现代显卡通常具有数千个处理核心(GPU 或着色器单元)的原因。
参见:
破窗效应 (The Broken Windows Theory)
在破窗理论中认为,一些明显的犯罪迹象(或缺乏环保意识)会导致进一步的、更严重的犯罪(或环境的进一步恶化)。
破窗理论已应用于软件开发中,它表明劣质代码(或 Technical Debt)可能会影响后续优化的效率,从而进一步造成代码劣化;随着时间的推移,这种效应将会导致代码质量大幅下降。
参见:
例子:
- 《程序员修炼之道:软件熵》(The Pragmatic Programming: Software Entropy)
- 《Coding Horror:破窗效应》(Coding Horror: The Broken Window Theory)
- 《开源:编程之乐 - 破窗效应》(OpenSource: Joy of Programming - The Broken Window Theory)
布鲁克斯法则 (Brooks's Law)
软件开发后期,添加人力只会使项目开发得更慢。
这个定律表明,在许多情况下,试图通过增加人力来加速已延期项目的交付,将会使项目交付得更晚。布鲁克斯也明白,这是一种过度简化。但一般的论据是,新资源的时间增加和通信开销,会在短期内使开发速度减慢。而且,许多任务是密不可分的,换句话说,这样可以使更多的资源之间能轻易分配,这也意味着潜在的速度增长也更低。
谚语 九个女人不能在一个月内生一个孩子 与布鲁克斯法则同出一辙,特别是某些不可分割或者并行的工作。
这是《人月神话》的中心主题。
参见:
CAP 定理 (CAP Theorem or Brewer's Theorem)
CAP 定理由 Eric Brewer 所定义,它指出对于分布式数据存储来说,不可能同时满足以下三点:
- 一致性 (Consistency):在读取数据时,每个请求都会接收到 最新的 数据,或者返回错误。
- 可用性 (Availability): 在读取数据时,每个请求都会接收到一个 非错误的响应,但不能保证该数据是 最新的 数据。
- 分区容错性 (Partition Tolerance):当节点之间任意数量的网络请求失败时,系统能按预期继续运行。
核心论证如下:因为无法保证不会存在网络分区(参见分布式计算的谬论 (The Fallacies of Distributed Computing)),所以在分区的情况下,我们可以选择取消当前操作(增加一致性并降低可用性),或者选择继续进行该操作(增加可用性降低一致性)。
该定理的名字来源于一致性 (Consistency)、可用性 (Availability)、分区容错性 (Partition Tolerance) 的首字母。请注意,这与 ACID 没有任何关系,因为其对一致性有另一种定义。最近发展出来的 PACELC 定理与 CAP 定理相比,增加了对网络 未 分区时(即系统按预期操作时)的延迟和一致性的约束。
大多数的现代数据库平台会通过向数据库用户提供选项的方式,来选择是需要高度可用的操作(比如“脏读 (dirty read)”),还是高度一致的操作(比如“法定确认写写入 (quorum acknowledged write)”)——这间接地承认了这一定理。
现实世界的例子:
- Inside Google Cloud Spanner and the CAP Theorem - 该文详细介绍了 Cloud Spanner 是如何工作的,表面上该平台似乎能够保证 CAP 三者,但实际上依然是一个 CP 系统,即只有一致性和分区容错性。
参见:
康威定律 (Conway's Law)
这个定律说明了系统的技术边界可以反应一个组织的结构,它通常会在改进组织时被提及。康威定律表明,如果一个组织被分散成许多小而无联系的单元,那么它开发的软件也是小而分散的。如果组织是更多地围绕以功能或服务为导向的垂直结构,那么软件系统也会反映这一点。
参见:
坎宁汉姆定律 (Cunningham's Law)
在网络上想得到正确答案的最好方法不是提问题,而是发布一个错误的答案。
据史蒂芬·麦克基迪说,沃德·坎宁汉姆早在 20 世纪 80 年代早期的时候建议他,在互联网上获得正确答案的最好方法不是提问题,而是发布一个错误的答案。麦克基迪称这为坎宁汉姆定律,而坎宁汉姆不以为然,并觉得这是“错误的引用”。最初这条定律只是用于描述 Usenet 上的社交行为,但后来也渐渐用于其他的在线社区(如 Wikipedia、Reddit、Twitter、Facebook 等)。
参见:
邓巴数字 (Dunbar's Number)
邓巴数字是对一个人能够保持稳定社会关系的人数的认知极限——在这种关系中,一个人知道每个人是谁,也知道每个人与其他人的关系如何。而对这一数字的确切值则有着一些不同意见。邓巴指出,人仅能轻松地维持 150 个稳定的关系。这样的关系在一个更社会化的背景中,便是当你碰巧在酒吧里碰到这些人时候,你不会因为加入他们而感到尴尬。邓巴数字的估计值一般在 100 至 250 之间。
和人与人之间稳定的关系一样,开发人员与代码库的关系也需要努力维护。当面对大型、复杂的项目,或许多项目的归属权时,我们会依赖于约定、策略和建模过程来进行扩展。邓巴数字不仅在办公室规模的扩大的过程中举足轻重,而且在设置团队工作范围,或决定系统何时应该注重于辅助建模和组织管理开销自动化的工具时,也是非常重要的。将邓巴数字放入工程内容中进行类比,那就是您能加入并有信心随叫随到进行轮换的项目数(亦或是单个项目的规范化复杂性)。
参见:
邓宁-克鲁格效应 (The Dunning-Kruger Effect)
无能的人往往不会意识到自己的无能。而得出正确答案所需要的技能,正是你认识到何为正确答案所需要的技能。
邓宁-克鲁格效应是一种理论上的认知偏差,大卫·邓宁和贾斯汀·克鲁格在 1999 年的一项心理学研究和论文中对此进行了描述。研究表明,在一项任务中能力水平较低的人会更容易高估自己的能力。之所以会产生这种偏向,是因为一个人对问题或领域的复杂性有足够的认识时,才能够针对自己在该领域的工作能力提出明智的意见。
邓宁-克鲁格效应也有另一个类似的,更显式的描述,即“一个人对某个领域的了解越少,他就越容易轻视这个领域的难度,从而更倾向于相信自己可以轻易地解决该领域的问题”。该效应与技术高度相关,具体表现为不太熟悉某个领域的个人(如非技术团队成员或经验较少的团队成员)会更有可能低估解决该领域问题所需的工作量。
随着对某一领域的理解和经验的增长,人们很可能会遇到另一种效应-虚幻的优越性 (Illusory superiority),即特定领域内的丰富经验使得他们更容易高估他人的能力,或低估自己的能力。总而言之,这些影响都归咎于认知偏差。当意识到偏差存在时,我们可以尽量提出意见来消除这些偏差,这样往往可以避免异议。
真实案例:
- 苹果公司 vs 联邦调查局:为什么这个反恐鹰派改变了立场 (Apple vs. FBI: Why This Anti-Terror Hawk Switched Sides) - 2016 年,参议员林赛·格雷厄姆改变了他对苹果在设备加密中创建“后门”的立场。起初,格雷厄姆曾批评苹果公司反对创建“后门”,因为他认为这对调查潜在的恐怖计划是必要的。然而,随着他对这个领域的技术复杂性有了更多的了解,格雷厄姆意识到这比他原先想的要困难很多,并可能会产生严重的负面后果。这便是邓宁-克鲁格效应的真实案例--网络安全专家会更清楚如何利用这样的后门,因为他们对该领域有深刻的理解;而外行人士可能会简单地将设备安全类比于物理上的安全,执法时可以使用“万能钥匙”,但这显然与网络安全中的现代加密不可同日而语。
费茨法则 (Fitts's Law)
该法则指出,移动到目标区域所需的时间是到目标的距离除以目标宽度的函数。
费茨法则决定了在设计 UX 或 UI 时,交互元素应该尽可能大,而用户注意力区域和交互元素之间的距离应该尽可能小。这会对设计产生影响,例如将相近的任务进行归类分组等。
同时它还将“魔角 (Magic Corners)”这一概念正式化,即在角落放置关键的 UI 元素,从而使得用户可以通过移动鼠标轻松点击到。Windows 的开始按钮便位于魔角处便于选择,而有趣的是 MacOS 恰恰相反,它的“关闭窗口”按钮 不处于 魔角处,从而能有效减小被误点击的概率。
参见:
盖尔定律 (Gall's Law)
一个切实可行的复杂系统势必是从一个切实可行的简单系统发展而来的。从头开始设计的复杂系统根本不切实可行,无法修修补补让它切实可行。你必须由一个切实可行的简单系统重新开始。
约翰·盖尔 (John Gall)
盖尔定律说明了设计高度复杂的系统很可能会失败。它们很难一蹴而就,更多是从简单的系统逐渐演变而来。
最典型的例子便是互联网。如今的互联网是一个高度复杂的系统,而它最早只是被定义为一种在学术机构之间共享内容的方式。互联网成功实现了最初的目标,并且随着时间不断演化,最终成就了如今的复杂繁荣。
参见:
古德哈特定律 (Goodhart's Law)
当压力施于其上以进行控制时,任何观测到的统计恒性都倾向消散。
查尔斯·古德哈特 (Charles Goodhart)
另见:
当一个措施本身成为目标时,它就不再是一个好的措施。
玛丽莲·斯特拉腾 (Marilyn Strathern)
根据这一定律,由测量驱动的优化反而可能导致测量结果本身的说服力下降。盲目使用一些过度严格筛选的方法 (KPIs) 可能会产生一些不良的影响。人们会倾向于用“钻空子”的行为去做局部优化,从而满足一些特定的度量标准,而不会在意整体的结果。
现实中的例子:
- Assert-free 测试可以达到代码覆盖率的预期,但度量的目的应该是创造经过良好测试的软件。
- 由 commits 的行数来评价开发人员的表现,从而导致了不合理的代码库扩增。
参见
汉隆的剃刀 (Hanlon's Razor)
能解释为愚蠢的,就不要解释为恶意的。
罗伯特·汉隆 (Robert J. Hanlon)
这一原则表明,一个行为所产生的消极结果并不是恶意。相反,消极结果更有可能归咎于这些没有得到充分理解的行动或影响。
席克定律 (Hick's Law or Hick-Hyman Law)
决策时间和可供选择的选项数量呈对数增长关系。
William Edmund Hick and Ray Hyman
在下方的等式中,T
是做出决定所花费的时间,n
是选项的数量,b
是一个由数据分析所确定的常数。
[图片上传失败...(image-d71e26-1668487539921)]
(图片参考:Creative Commons Attribution-Share Alike 3.0 Unported, https://en.wikipedia.org/wiki/Hick%27s_law)
该定律仅适用于选项 按顺序排列 的情况,例如 ABCD。这隐含在一二为底的对数中,也就是说决策者本质上在进行 二分法查找。实验表明,如果选项不是按顺序排列的,那么所花费时间与选项个数将会呈线性增长关系。
这在 UI 设计中,该定律也可以有效地确保用户在搜索选项时更轻松愉快地做出决策。
在 Speed of Information Processing: Developmental Change and Links to Intelligence 一文中可见,智商和反应时间之间的相关性也满足席克定律。
参见:
侯世达定律 (Hofstadter's Law)
即使考虑到侯世达定律,它也总是比你预期的要长。
侯世达 (Douglas Hofstadter)
在估计需要多长时间开发时,你可能会听到此定律。软件开发似乎有这样一条定理,即我们往往不能准确地估计需要多长时间才能完成。
参见:
哈特伯定律 (Hutber's Law)
改善即恶化。
帕特里克·哈特伯 (Patrick Hutber)
这个定律说明了对一个系统的改进会导致其他部分的恶化;或者它会将其他的恶化隐藏起来,并导致系统整体状态的退化。
例如,某个端点的响应延迟减少,就可能导致请求流中的吞吐量和容量问题进一步增加,并影响到另一个完全不同的子系统。
技术成熟度曲线 (The Hype Cycle or Amara's Law)
我们倾向于过高估计技术在短期内的影响,并低估长期效应。
罗伊·阿马拉 (Roy Amara)
技术成熟度曲线是高德纳咨询公司对技术最初兴起和发展的视觉展现。一图顶千言:
简而言之,这个周期表明,新技术及其潜在影响通常会引发一阵浪潮。团队快速使用这些新技术,有时会对结果感到失望。这可能是因为该技术还不够成熟,或者现实应用还没有完全实现。经过一段时间后,技术的能力提高了,使用它的实际机会会增加,最终团队也可以提高工作效率。罗伊·阿马拉简洁地总结了这一点:我们倾向于高估技术短期内的影响,并低估长期效应。
隐式接口定律 (Hyrum's Law or The Law of Implicit Interfaces)
当 API 有足够多的用户时,你在合同中的承诺已不重要:你系统的所有可观察行为都将被某些人所依赖。
海勒姆·赖特 (Hyrum Wright)
隐式接口定律表明,当你的 API 有足够多的用户时,API 的所有行为(包括那些未囊括在公共说明中的一部分)最终都会被其他人所依赖。 一个简单的例子是 API 的响应时间这种非功能性因素;还有一个更微妙的例子是:用户使用正则表达式匹配错误提示来判断 API 的错误类型,即使 API 文档中没有任何关于错误提示的内容,而是指导用户应该使用相应的错误代码。一些用户依然会使用错误提示内容(而非错误代码),这种情况下变更 API 错误提示信息,实际上会破坏 API 的使用。
参见:
柯林汉定律 (Kernighan's Law)
调试在一开始就比编写程序困难一倍。因此,按照定义,如果你的代码写得非常巧妙,那么你就没有足够的能力来调试它。
布莱恩·柯林汉 (Brian Kernighan)
柯林汉定律是以布莱恩·柯林汉 (Brian Kernighan) 的名字命名的,引述自柯林汉和普劳格 (P.J. Plauger) 的《编程格调》 (The Elements of Programming Style) 一书中的一句话:
每个人都知道,调试在一开始就比编写程序困难一倍。那么,如果您在编写它时尽可能地巧妙,又如何来调试它?
尽管这有些夸张,但它提出的论点是,简单的代码会比复杂的代码更可取,因为调试复杂代码的过程中出现的任何问题都会十分棘手,甚至无法解决。
参见:
林纳斯定律 (Linus's Law)
足够多的眼睛,就可让所有问题浮现。
Eric S. Raymond
简单地说,能够看到问题的人越多,有人解决过相关的问题或事情的可能性就越高。
最初该定律是用来描述开源模型对于项目的价值的,并适用于任意的软件项目。同时它也可以扩展到开发流程之中——更多的代码审查、更多的静态分析和多重测试可以让问题更加明显和容易识别。
林纳斯定律的一个更正式的说法如下:
如果有足够大的测试员和联合开发人员基础,那么几乎每个问题都能很快被特征化,从而让以前遇到过类似问题的人解决。
这条定律最早出现在 Eric S. Raymond 所著书 "The Cathedral and the Bazaar" 中,并以 Linus Torvalds 的名字命名以作纪念。
梅特卡夫定律 (Metcalfe's Law)
在网络理论中,系统的价值约等于系统用户数的平方。
这个定律基于一个系统中可能的连接对数量,并且与里德定律 (Reed's Law) 十分相近。奥德利兹科 (Odlyzko) 和其他人认为,里德定律和梅特卡夫定律夸大了系统本身的价值,因为它们没有考虑到网络效应中人类认知的限制。
参见:
摩尔定律 (Moore's Law)
集成电路中的晶体管数量大约每两年翻一番。
这条定律通常用于说明半导体和芯片技术提高的绝对速度。从 20 世纪 70 年代到 21 世纪前十年,摩尔的预测被证明是高度准确的。 近年来,这种趋势略有变化,部分原因受到量子隧穿效应影响。然而,并行化计算的进步以及半导体技术和量子计算潜在的革命性变化,可能意味着摩尔定律在未来几十年内继续保持正确。
墨菲定律 (Murphy's Law / Sod's Law)
凡是可能出错的事就一定会出错。
出自 爱德华·A·墨菲 , 墨菲定律 说明了如果一件事有可能出错,那么就一定会出错。
这是一句开发人员间的俗语,在开发、测试甚至在生产中都有可能会发生一些令人意想不到的事情。而这一定律也可以参考在英式英语中更为常见的 索德定理 :
如果某件事可能出错,那么它一定会在最糟糕的时候发生。
这些定律常常用于幽默嘲弄。但是,类似于 Confirmation Bias 和 Selection Bias 的现象很容易导致人们过分强调这些定律(即在大部分情况下,一件事的成功会显得司空见惯;而失败才会引起更多的注意和讨论)。
参见:
奥卡姆剃刀 (Occam's Razor)
如无必要,勿增实体。
奥卡姆的威廉 (William of Ockham)
奥卡姆剃刀指出,在几种可能的解决方案之中,最有可能的解决方案便是概念和假设最少的那个。因为这个解决方案最为简单,只解决了问题,并且没有引入额外的复杂度和可能的负面后果。
参见:
- 你不需要它原则 (YAGNI)
- 没有银弹:软件工程的本质性与附属性工作
- No Silver Bullet: Accidental Complexity and Essential Complexity
例子:
帕金森定理 (Parkinson's Law)
在工作能够完成的时限内,工作量会一直增加,直到所有可用时间都被填满为止。
基于官僚机构的研究背景,该定律被应用于软件开发中。该理论认为,团队在截止日期之前效率低下,然后在截止日期前赶紧完成工作,从而使实际截止日期变得随意。
将这个定理与侯世达定律相结合,则会获得更加悲观的观点:为了在规定时间内完成工作,工作将增多,花费比预期更长的时间。
参见:
过早优化效应 (Premature Optimization Effect)
过早优化是万恶之源。
在高德纳的《goto 语句的结构化编程》论文中,他写到:“程序员们浪费了大量的时间去思考或者担心他们的程序中的非关键部分的速度。而在考虑调试和维护的时候,这些所谓提高效率的做法实际上十分不妥。我们应该放弃小的效率点,并且要在 97% 的时间提醒自己,过早优化是万恶之源。而且连那关键的 3% 也不能够放过。”
然而,过早优化 (简而言之)可以定义为在我们知道需要做什么之前进行优化。
普特定律 (Putt's Law)
技术由两类人主导,一类是纯粹的管理人员, 一类是纯粹的技术人员。
普特定律常常遵循普特推论:
每一个技术层次,假以时日,能力将逆转。
这些结论表明,由于各种选择标准和群体组织的趋势,技术组织的工作层面将有一些技术人员,以及一些不了解复杂性和挑战的管理人员。这种现象可能是由于 彼得原理 (The Peter Principle) 或 呆伯特法则 (The Dilbert Principle) 造成的。
但是,应该强调的是,诸如此类的定律是一种广泛的概括,可能适用于某些类型的组织,而不适用于其他组织。
参见:
里德定律 (Reed's Law)
大型网络,尤其是社交网络的效用会随着网络的大小呈指数级扩增。
这一定律基于图论,图论中的效用与可能的子组数量呈正比,并且该增长速度会比参与者的数量和可能的连接对数量要快。奥德利兹科 (Odlyzko) 和其他人认为,里德定律夸大了系统本身的价值,因为它们没有考虑到网络效应中人类认知的限制。
参见:
复杂性守恒定律 (The Law of Conservation of Complexity or Tesler's Law)
该定律表明系统中存在着一定程度的复杂性,并且不能减少。
系统中的某些复杂性是无意的。这是由于结构不良,错误或者糟糕的建模造成的。这种无意的复杂性可以减少或者消除。然而,由于待解决问题固有的复杂性,某些复杂性是内在的。这种复杂性可以转移,但不能消除。
该定律有趣的一点是,即使简化整个系统,内在的复杂性也不会降低。它会转移到用户,并且用户必须以更复杂的方式行事。
得墨忒耳定律 (The Law of Demeter)
别和陌生人讲话。
得墨忒耳定律又称最少知识原则,是一条与面向对象语言有关的软件设计原则。
该定律表明,软件的一个单元应该只与其直接合作者交谈。比如对象 A
引用了对象 B
,对象 B
引用了对象 C
,则 A
可以直接调用 B
的方法,但不应直接调用 C
的方法。所以如果 C
有一个 dothing()
的方法,A
不应该直接调用,而是使用 B.getC().doThis()
。
遵循这一定律可以限制代码更改的范围,使其以后更容易维护、更安全。
抽象泄漏定律 (The Law of Leaky Abstractions)
在某种程度上,所有非平凡的抽象都是有泄漏的。
乔尔斯·波尔斯基 (Joel Spolsky)
该定律指出,通常用于简化复杂系统的抽象,在某些情况下将底层系统泄漏出来,使得抽象表现出意外的行为。
例如加载文件并读取其内容。文件系统 API 是较低级别内核系统的抽象,它们本身是与磁盘(或 SSD 的闪存)上的数据更改相关的物理过程的抽象。在大多数情况下,处理文件(如二进制数据流)的抽象将起作用。但是,对于磁盘驱动器,顺序读取数据将比随机访问快得多(由于页面错误的开销增加)。但对于 SSD 驱动器,此开销不会出现。需要理解基础细节来处理这种情况(例如,数据库索引文件的良好结构可以减少随机访问的开销),开发人员需要合理的抽象,来处理不同的细节。
当引入更多的抽象时,上面的例子会变得更复杂。Linux 操作系统允许通过网络访问文件,但在本地表示为普通文件。如果存在网络故障,这种抽象将会泄漏。如果开发人员将这些文件视为普通文件,而不考虑它们可能会受到网络延迟和故障的影响,那么解决方案就会出错。
描述该定律的文章表明,过度依赖抽象,加上对底层过程的理解不足,实际上使得问题在某些情况下更加复杂。
参见:
真实的例子:
- Photoshop 启动缓慢:我过去遇到过一个问题,就是 Photoshop 启动缓慢,有时需要几分钟。问题好像是 Photoshop 启动时,会读取当前默认打印机的一些信息。但是,如果该打印机实际上是一台网络打印机,则可能需要很长的时间。将网络打印机与本地打印机当作同样的抽象,导致连接不良的情况下出现问题。