hacker-laws 的的中文翻译。php
对开发人员有用的定律,理论,原则和模式。(Laws, Theories, Principles and Patterns that developers will find useful.)git
为了方便阅读,维基百科增长了中文连接!github
英文连接表示 hacker-laws 项目还没有完成。正则表达式
github 地址数据库
当谈论到开发时,人们会谈到许多定律。 这个仓库收录了一些最多见的定律。请分享这个仓库并提交 PR !编程
❗: 这个仓库包含对一些定律、原则以及模式的解释,但不提倡其中任何一个。 它们的应用始终存在着争论,而且很大程度上取决于你正在作什么。安全
如今咱们开始吧!服务器
阿姆达尔定律是一个显示计算任务潜在加速能力的公式。这种能力能够经过增长系统资源来实现。 一般用于并行计算中,它能够预测增长处理器数量的实际好处。增长处理器数量会受到程序并行性的限制。markdown
举例说明:若是程序由两部分组成,部分 A 必须由单个处理器执行,部分 B 能够并行运行,那么咱们向执行程序的系统添加多个处理器只能得到有限的好处。 它能够极大地提高部分 B 的运行速度,但部分 A 的运行速度将保持不变。网络
下图展现了运行速度的潜能:
(图片来源: By Daniels220 at English Wikipedia, Creative Commons Attribution-Share Alike 3.0 Unported, en.wikipedia.org/wiki/File:A…)
能够看出,50% 并行化的程序仅仅受益于 10 个处理单元,而 95% 并行化的程序能够经过超过一千个处理单元显著提高速度。
随着摩尔定律减慢,以及单个处理器的速度增长缓慢,并行化是提升性能的关键。 图形编程是一个很好的例子,现代着色器能够并行渲染单个像素或片断。这也是为何现代显卡一般具备数千个处理核心(GPU 或着色器单元)的缘由。
参见:
布鲁克斯是《人月神话》的做者。
软件开发后期,添加人力只会使项目开发得更慢。
这个定律代表,在许多状况下,试图经过增长人力来加速延期项目的交付,将会使项目交付得更晚。 布鲁克斯也明白,这是一种过分简化。但通常的推理是,新资源的增长时间和通讯开销,会使开发速度减慢。 并且,许多任务是不可分的,好比更多的资源容易分配,这也意味着潜在的速度增长也更低。
谚语 九个女人不能在一个月内生一个孩子 与布鲁克斯法则同出一辙,特别是某些不可分割或者并行的工做。
参见:
系统的技术边界受制于组织的结构。在改进组织时,一般会提到它。康威定律代表,若是一个组织被分散成许多小型、无联系的单元,那么它开发的软件也是小而分散的。 若是一个组织更多地垂直创建在特性或服务周围,那么软件系统也会反映这一点。
参见:
即便考虑到侯世达定律,它也老是比你预期的要长。
在估计须要多长时间时,您可能会听到此定律。软件开发中彷佛不言而喻,咱们每每不能准确地估计须要多长时间才能完成。
咱们倾向于太高估计技术在短时间内的影响,并低估长期效应。
(罗伊阿马拉)
技术成熟度曲线是高德纳咨询公司最初制做的技术兴起和发展的直观表现。一图顶千言:
(图片来源: By Jeremykemp at English Wikipedia, CC BY-SA 3.0, commons.wikimedia.org/w/index.php…)
简而言之,这个周期代表,新技术及其潜在影响一般会引起一阵浪潮。 团队快速使用这些新技术,有时会对结果感到失望。 这多是由于该技术还不够成熟,或者现实应用尚未彻底实现。 通过一段时间后,技术的能力提升了,使用它的实际机会会增长,最终团队能够提升工做效率。 罗伊·阿马拉简洁地总结了这一点:咱们倾向于高估技术短时间内的影响,并低估长期效应。
有足够数量 API 的用户, 你在合同中的承诺并不重要: 你系统的全部可观察行为 将取决于某人。
(Hyrum Wright)
隐式接口定律代表,当你拥有足够数量的 API 用户时,API 的全部行为(即便那些未被定义为公共说明的一部分)最终都会被某人所依赖。 一个简单的例子,例如 API 的响应时间这种非功能性因素。 一个更微妙的例子是:用户使用正则表达式判断错误信息的类型。 即便 API 的公共说明没有说明消息的内容,来指示用户错误的类型。一些用户可能会使用该消息,而且更改消息,实际上会破坏用户的 API。
参见:
集成电路中的晶体管数量大约每两年翻一番。
一般用于说明半导体和芯片技术提升的绝对速度。从 20 世纪 70 年代到 21 世纪后期,摩尔的预测被证实是高度准确的。 近年来,这种趋势略有变化,部分缘由受到[量子隧穿效应](zh.wikipedia.org/wiki/量子穿隧效應… 然而,并行化计算的进步以及半导体技术和量子计算潜在的革命性变化,可能意味着摩尔定律在将来几十年内继续保持正确。
在工做可以完成的时限内,工做量会一直增长,直到全部可用时间都被填充为止。
基于官僚机构的研究背景,该定律被应用于软件开发中。该理论认为,团队在截止日期以前效率低下,而后在截止日期前赶忙完成工做,从而使实际截止日期有些随意。
将这个定理与[侯世达定律](#侯世达定律)相结合,则会得到更加悲观的观点: 工做将扩大以填补所需时间,而且须要比预期更长的时间。
参见:
技术由两类人主导,一类是管理人员, 一类是技术人员。
普特定律经常遵循普特推论:
每一个技术层次都会发展地逆转。
这些结论代表,因为各类选择标准和群体组织的趋势,技术组织的工做层面将有一些技术人员,以及一些不了解复杂性和挑战的管理人员。 这种现象多是因为 The Peter Principe 或者 Dilbert's Law 形成的。
可是,应该强调的是,诸如此类的定律是一种普遍的归纳,可能适用于某些类型的组织,而不适用于其余组织。
参见:
该定律代表系统中存在着必定程度的复杂性,而且不能减小。
系统中的某些复杂性是无心的。 这是因为结构不良,错误或者糟糕的建模形成的。 能够减小以及消除无心的复杂性。 然而,因为待解决问题固有的复杂性,某些复杂性是内在的。 这种复杂性能够移动,但不能消除。
一个该定律的有趣元素是,即便简化整个系统,内在的复杂性也不会下降。它会移动到用户,而且用户必须以更复杂的方式行事。
在某种程度上,全部非平凡的抽象都是漏洞。
(乔尔斯 波尔斯基)
该定律指出,一般用于简化复杂系统的抽象,某些状况下将在底层系统有漏洞,这使得抽象表现为意外的方式。
例如加载文件并读取其内容。 文件系统 API 是较低级别内核系统的抽象,它们自己是与磁盘(或 SSD 的闪存)上的数据更改相关的物理过程抽象。 在大多数状况下,处理文件(如二进制数据流)的抽象将起做用。 可是,对于磁盘驱动器,顺序读取数据将比随机访问快得多(因为页面错误的开销增长)。但对于 SSD 驱动器,此开销不会出现。 须要理解基础细节来处理这种状况(例如,数据库索引文件的良好结构能够减小随机访问的开销),开发人员须要合理的抽象,来处理不一样的细节。
当引入的抽象更多时,上面的例子会变得更复杂。 Linux 操做系统容许经过网络访问文件,但在本地表示为普通文件。 若是存在网络故障,这种抽象将有漏洞。 若是开发人员将这些文件视为普通文件,而不考虑它们可能会受到网络延迟和故障的影响,那么解决方案就会出错。
描述该定律的文章代表,过分依赖抽象,加上对底层过程的理解不足,实际上使得问题在某些状况下更加复杂。
参见:
真实的例子:
该定理显示,群体将给予更多的时间和注意力来处理琐碎的问题,而不是用来处理严肃而实质性的问题。
常见的虚构例子是委员会批准核电站的计划,他们大部分时间都在讨论自行车棚的结构,而不是电厂自己等更为重要的设计。 若是没有大量的专业知识或者准备,很难给很是大的复杂主题讨论提供宝贵的意见。 可是,人们但愿看到宝贵的意见。 所以,倾向于将过多的时间集中在小细节上,这很容易推理,但不必定特别重要。
上面的虚构例子致使使用Bike Shedding这个词,做为在琐碎细节上浪费时间的表达。
Unix 哲学是软件组件应该很小,并专一于作一件特定的事情。 将小型、简单以及定义良好的单元组合在一块儿,而不是使用大型、复杂以及多用途程序,能够更轻松地构建系统。
像微服务架构这种现代实践能够被认为是这种哲学的应用,其中服务很小,集中于作一件特定的事情,由简单的构建块组成复杂的行为。
Spotify 模型是团队和组织结构的一种方法,已被 Spotify 实验室推广。 在此模型中,团队围绕功能而非技术进行组织。
Spotify 模型还普及了部落、行会以及章节的概念,这些是其组织结构的其余组成部分。
任何语言设计中,讨论下面列表中某个要素所花费的总时间与其位置上的两个要素成正比。
- 语义
- 语法
- 词法
- 评论词法
(简而言之,对于语义上花费的每个小时,将在评论词法上花费 8 小时)。
与 帕金森琐碎定理 相似, 沃德勒定律指出,在设计语言时,与这些特征的重要性相比,花在语言结构上的时间至关多。
参见:
原则一般是与设计相关的准则。
对本身所作的事情要保守,对本身接受的人要宽容。
一般应用于服务器应用程序开发中,该原则指出,你发送给其余人的内容应尽量小且符合要求,而且处理不符合要求的输入。
该原则的目标是构建稳健的系统。若是能够理解意图,它们能够处理不良的输入。 可是,接受错误格式的输入可能存在安全隐患,特别是此类的输入未通过充分测试。
这是一个缩写,指的是:
这些是 Object-Oriented Programming 的关键原则。 诸如此类的设计原则可以帮助开发人员构建更易于维护的系统。
每一个模块或者类只应该有一项功能。
SOLID 的第一个原则。 这个原则代表模块后者类只应该作一件事。 实际上,这意味着对程序功能的单个小更改,应该只须要更改一个组件。 例如,更改密码验证复杂性的方式应该只须要更改程序的一部分。
理论上讲,这使代码更健壮,更容易更改。 知道正在更改的组件只有一个功能,这意味着测试更改更容易。 使用前面的例子,更改密码复杂性组件应该只影响与密码复杂性相关的功能。 变动具备许多功能的组件可能要困可贵多。
参见:
实体应开放扩展并关闭修改。
SOLID 的第二个原则。 这个原则指出实体(能够是类,模块,函数等)应该可以使它们的行为进行扩展,可是它们的扩展行为不该该被修改。
举一个假设的例子,想象一个可以将 Markdown 转换为 HTML 的模块。 若是能够扩展模块以处理新的 markdown 特征,而无需修改内部模块,则能够认为是开放扩展。 若是用户不能修改模块以处理现有的 Markdown 特征,那么它被认为是关闭修改。
这个原则与面向对象编程紧密相关,咱们能够设计对象以便于扩展,可是能够避免以意想不到的方式改变其现有对象的行为。
参见:
能够在不破坏系统的状况下,用子类型替换类型。
SOLID 的第三个原则。 该原则指出,若是组件依赖于类型,那么它应该可以使用该类型的子类型,而不会致使系统失败或者必须知道该子类型的详细信息。
举个例子,假设咱们有一个方法,读取 XML 文档。 若是该方法使用基类型 file,则从 file 派生的任何内容,都能用在该方法中。 若是 file 支持反向搜索,而且 xml 解析器使用该函数,可是派生类型 network file 尝试反向搜索时失败,则 network file 将违反该原则。
该原则与面向对象编程特别有关,必须仔细建模类型层次,以免混淆系统用户。
参见
不该该强迫客户端依赖它不使用的方法。
SOLID 的第四个原则。 该原则指出组件的消费者不该该依赖于它实际上不使用的组件功能。
举一个例子,假设咱们有一个方法,读取 XML 文档。 它只须要读取文件中的字节,向前移动或向后移动。 若是因为文件结构不相关(例如更新文件安全性的权限模型),须要更新此方法,则原则已失效。 文件最好实现 搜索流 接口,并让 XML 读取器使用它。
该原则与面向对象编程紧密相关,其中接口,层次结构和抽象类型用于不一样组件的 minimise the coupling。 Duck typing 是一种经过消除显式接口来强制执行该原则的方法。
参见:
高级模块不该该依赖于低级实现。
SOLID 的第五个原则。 该原则指出,更高级别的协调组件不该该知道其依赖关系的细节。
举个例子,假设咱们有一个从网站读取元数据的程序。咱们假设主要组件必须知道下载网页内容的组件,以及能够读取元数据的组件。若是咱们考虑依赖反转,主要组件将仅依赖于能够获取字节数据的抽象组件,而后是一个可以从字节流中读取元数据的抽象组件。主要组件不须要了解 TCP、IP、HTTP、HTML 等。
这个原则很复杂,由于它彷佛能够反转系统的预期依赖性(所以得名)。实践中,这也意味着,单独的编排组件必须确保抽象类型的正确实现被使用(例如在前面的例子中,必须提供元数据读取器组件、HTTP 文件下载功能和 HTML 元标签读取器)。而后,这涉及诸如 Inversion of Control 和 Dependency Injection 之类的模式。
该项目还没有编写完成,最新进展请查看 github.com/nusr/hacker…