在围绕软件开发的讨论中,几乎不可能避免引用一两条定律。
“这行不通,因为‘X法则’!” 你可能听过人们说。或者“你不知道‘Y原则’吗? 你是哪种软件开发人员?”。
有许多法律和原则可以引用,其中大部分都基于真理。然而,盲目地使用像上面这样的绝对陈述来应用它们肯定会导致自负和失败。
本文列举了一些可以应用于软件开发的最流行的规律和原则。对于每条规律,我们将快速讨论其主要命题,然后探讨如何将其应用于软件开发(也许何时不应该)。
帕累托原则(80/20 规则)
解释
帕累托原则指出,通常 80% 的结果来自 20% 的原因。数字 80 和 20 无论如何都不是精确的,但该原理的总体思路是结果通常分布不均。
我们可以在生活的许多领域遵守这条规则,例如:
- 世界上最富有的 20% 的人创造了世界上 80% 的收入,
- 80%的犯罪是由20%的罪犯所为
- 自 2020 年以来,我们知道 80% 的病毒传播来自 20% 的受感染人群。
在软件开发中的应用
我们可以从帕累托原则中获得的主要好处是专注。它可以帮助我们专注于重要的事情(20%),而不是在不重要的事情(其他 80%)上浪费时间和精力。不重要的事情对我们来说似乎很重要,因为有太多(而且看起来很紧急)。但最好的结果往往是通过专注于重要的少数来实现的。
在软件开发中,我们可以基于这个原则来专注于构建正确的功能,例如:
- 专注于构成产品价值 80% 的 20% 的产品功能,
- 专注于导致 80% 用户沮丧的 20% 错误,
- 专注于 80% 的产品功能需要 20% 的总时间来构建,
- ……
只是问“现在最重要的事情是什么?” 能够帮助你完成下一个最重要的事情,而不是下一个最紧急的事情。
顺便说一下,敏捷和 DevOps 等现代开发方法有助于获得这种关注!具有定期用户反馈的快速迭代允许对重要事项进行数据驱动的决策。诸如基于主干的带有功能标记的开发(例如使用 LaunchDarkly)之类的实践可以帮助软件团队实现目标。
破窗定理
解释
一扇被打破的窗户会招来恶意破坏,所以用不了多久,所有的窗户都被打破了。
一般来说:混乱会带来更多的混乱。
如果我们的环境是原始的,我们就会有动力保持这种状态。环境中的混乱越多,我们添加混乱的门槛就越低。毕竟已经混乱了……谁在乎我们是否再添加一点呢?
我们可以从这条规则中获得的主要好处是我们应该意识到我们周围的混乱。如果人们习惯于它,不再关心它了,那么最好为混乱带来一些秩序。
在软件开发中的应用
在软件开发中,我们可以将其应用于代码质量:我们引入代码库的每一种代码异味都会降低我们添加更多代码异味的门槛。我们应该 [[开始清理]] 并保持代码库干净以避免这种情况发生。许多代码库如此难以理解和维护的原因是,破窗已经悄然出现并且没有足够快地修复。
我们也可以将这个原则应用到测试覆盖率上:一旦有一定数量的代码进入了未被测试覆盖的代码库,就会添加更多未被覆盖的代码。这是保持 100% 代码覆盖率(应该覆盖的代码的)的论据,因此我们可以在窗口破裂之前看到裂缝。
奥卡姆剃刀
解释
剃刀哲学是一种原理,它通过消除(或“削除”)不可能的解释来帮助解释某些事情。
奥卡姆剃刀指出,如果有多个假设,我们应该选择假设最少的假设(这很可能是解释最简单的假设)。
在软件开发中的应用
我们可以在事件分析中应用奥卡姆剃刀。您可能遇到过这样的情况:用户报告了您的应用程序存在问题,但您不知道导致问题的原因。因此,您搜索日志和指标,试图找到根本原因。
下次用户报告错误时,维护一个事件调查文档。写下您对导致问题的原因的假设。然后,对于每个假设,列出事实和假设。如果一个假设被证明是正确的,则将其标记为事实。如果某个假设被证明是错误的,请将其从文档中删除或将其标记为错误。在任何时候,您都可以将时间集中在最可能的假设上,而不是浪费时间寻找不相干的东西。
达克效应
解释
邓宁-克鲁格效应表明,没有经验的人往往会高估自己的能力,而有经验的人往往会低估自己的能力。
如果你不擅长某件事,你会认为你擅长它。如果你擅长某事,你认为你不擅长 – 这可能导致骗子综合症,这让你非常怀疑自己的能力,以至于你在其他具有相似技能的人中感到不舒服 – 不必要地害怕被质疑是一个骗子。
在软件开发中的应用
意识到这种认知偏差已经是朝着正确方向迈出的重要一步。它将帮助您更好地评估自己的技能,以便您可以寻求帮助,或克服自我怀疑并自己动手。
有助于消除达克效应和骗子综合症的一种做法是结对或群体编程。你不是独自工作,沉浸在自我怀疑或优越感中,而是与其他人密切合作,边工作边交流思想、学习和教学。
不过,这只适用于安全的环境。在个人主义被美化的环境中,结对或群体编程会导致更多的自我怀疑或更多的优越感妄想。
彼得原则
解释
彼得原则指出,只要你成功,你就会得到晋升,直到你最终得到一份你不胜任的工作。由于您不再成功,您将不再获得晋升,这意味着您将生活在一份不会给您带来满足感或成功的工作中,通常这种感觉将在一直伴随在您的余生。
前景黯淡。
在软件开发中的应用
在软件开发中,当您将角色从开发人员职业转换为管理职业时,彼得原则通常适用。然而,成为一名优秀的开发人员并不一定意味着你是一名优秀的经理。或者,您可能是一名优秀的经理,但却不能从经理工作中获得开发工作中所能获得的满足感,这意味着您没有全力以赴(这就是我的情况)。在任何情况下,你都很悲惨,在你面前的职业道路上看不到任何未来的发展。
在这种情况下,退后一步,决定你想要什么样的职业生涯。然后,转换角色(或公司,如果需要)以获得您想要的角色。
帕金森定律
解释
帕金森定律指出,工作总是会占据分配给它的时间。如果您的项目在两周的截止日期,则该项目将不会在此之前完成。 可能需要更长的时间,是的,但绝不会少于我们为它分配的时间,因为我们正在用不必要的工作或拖延来填补时间。
在软件开发中的应用
帕金森定律的主要驱动因素是:
- 拖延症(“截止日期太远了,所以我现在不需要赶时间……”),还有
- 范围蔓延(“当然,我们可以添加这个小功能,它不会花费我们太多时间……”)。
为了战胜拖延症,我们可以把最后期限设置为几天而不是几周或内个月。在接下来的 2-3 天内需要做什么才能朝着目标前进?一个(健康的!)截止日期可以给我们足够的动力,让我们不要陷入拖延症的泥潭。
为了防止范围蔓延,我们应该非常清楚地知道我们想要通过项目实现什么。成功的衡量标准是什么? 这个新功能是否会增强这些指标?那么如果每个人都明白这项工作需要更长的时间,我们应该添加它。如果新功能不符合使命,那就不用管它。
霍夫施塔特定律
解释
霍夫施塔特定律指出:“即使考虑了霍夫施塔特定律,它所花的时间也比你预期的长”。
即使您了解了这条法律,并增加了项目的时间分配,它仍然会比您预期的要长。这与帕金森定律密切相关,即工作总是会填满分配给它的时间。只是霍夫施塔特定律说它填充的时间超过了分配的时间。
这条定律得到了心理学的支持。我们容易犯所谓的“计划谬误”,即在估算工作量时,我们通常不会考虑所有可用信息,即使我们认为我们已经考虑了。我们的估计几乎总是主观的,很少是正确的。
在软件开发中的应用
在软件开发(以及任何其他基于项目的工作)中,我们人类的乐观情绪发挥了很大作用。评估几乎总是过于乐观。
为了减少霍夫施塔特定律的影响,我们可以尝试尽可能客观地进行估计。
写下关于项目的假设和事实。将每个项目标记为假设或事实,以使数据质量可见并管理预期。
不要依赖直觉,因为每个人的感受都不一样。写下估算值,让你的大脑思考它们。将它们与其他人的估计进行比较,然后讨论差异。
即便如此,它仍然只是一个估计,很可能不能反映现实。如果估算不是基于统计数据或其他历史数据,那么它的价值就非常低,因此与要求您估算的人一起管理预期总是好的——这总是会出错的。如果你让它尽可能客观,它就会减少错误。
康威定律
解释
康威定律指出,一个组织创建的任何系统都与该组织的团队和沟通结构相似。系统将在构建系统的团队有接口的地方具备接口。如果你有 10 个团队在一个系统上工作,你很可能会得到 10 个相互通信的子系统。
在软件开发中的应用
我们可以应用所谓的逆康威策略:创建最能支持我们想要构建的系统架构的组织结构。
没有固定的团队结构,而是要有足够的灵活性来创建和解散团队,这对系统的当前状态是最好的。
墨菲定律
解释
墨菲定律说,任何可能出错的事情,都会出错。它经常在意外发生后被引用。
在软件开发中的应用
软件开发是一个容易出错的职业。出错的主要来源是错误。没有任何一款软件不存在漏洞或事故,从而考验测试用户的耐心。
我们可以通过在日常软件开发实践中养成减少错误影响的习惯来抵御墨菲定律。我们无法完全避免错误,但我们可以而且应该减少它们对用户的影响。
对抗墨菲定律最有用的做法是特征标记。如果我们使用像 LaunchDarkly 这样的功能标记平台,我们可以在功能标记后面将更改部署到生产中。然后,我们可以使用有针对性的推出来激活内部 dogfooding 的标志,然后为少量友好的 Beta 用户激活它,最后将其发布给所有用户。这样,我们可以从越来越挑剔的用户群体那里获得关于变更的反馈。如果更改出错(并且在某些时候会出错)影响就很小,因为只有一小部分用户组会受到它的影响。而且,该标志可以快速关闭。
布鲁克定律
解释
在经典著作《人月神话》中,弗雷德·布鲁克 (Fred Brook) 有句名言:为延期的项目增加人力会使项目延期更多。
尽管本书讨论的是软件项目,但它适用于大多数类型的项目,甚至是软件开发之外的项目。
添加人员不会提高项目速度的原因是项目的通信开销随着添加到项目中的每个人呈指数增长。2 个人有 1 条通信路径,5个人已经有 5! = 120 条可能的通信路径。新人安顿下来并确定他们需要的沟通路径需要时间,这就是为什么在项目中添加新人时,迟到的项目会更晚。
在软件开发中的应用
很简单。改变截止日期,而不是在已经延期的项目中增加人力。
对于向软件项目中增加新人的期望要切合实际。将人员添加到项目中可能会在某个时候提高速度,但并非总是如此,当然也不是立竿见影。人员和团队需要时间来适应日常工作,而在某些时候,工作无法充分并行化,因此增加更多人是没有意义的。 仔细考虑一个新人应该完成什么任务,以及在将该人添加到项目中时您期望什么。
波斯特定律
解释
波斯特定律也被称为稳健性原则,它指出你应该“在你所做的事情上保守,在你接受别人的事情上自由”。
换句话说,您可以接受多种不同形式的数据,以使您的软件尽可能灵活,但您在处理这些数据时应该非常小心,以免因无效或恶意数据而损害您的软件。
在软件开发中的应用
该定律源于软件开发,因此非常适于直接使用。
为了增强健壮性,您的软件与其他软件或人之间的接口应允许不同形式的输入:
- 为了向后兼容,新版本的接口应该接受旧版本和新版本的数据,
- 为了更好的用户体验,UI 中的表单应该接受不同格式的数据,这样用户就不必担心格式。
但是,如果我们愿意接受不同格式的数据,我们在处理这些数据时就必须保守。我们必须审查无效值,并确保我们不会因为允许太多不同的格式而损害系统的安全性。SQL 注入是一种可能的攻击,它是通过对用户输入过于宽松而启用的。
克希霍夫原理
解释
克希霍夫原理指出,加密系统应该是安全的,即使它的方法是公知的。只有您用来解密某些东西的密钥才需要是私有的。
在软件开发中的应用
这很简单,真的。永远不要相信要求其方法是私有的加密系统。这被称为“隐藏的安全”。像这样的系统本质上是不安全的。一旦该方法向公众公开,它就容易受到攻击。
相反,依靠公开审查和可信的对称和非对称加密系统,这些系统是在可以公开审查的开源包中实现的。每个想知道他们内部如何工作的人都可以查看代码并验证它们是否安全。
莱纳斯定律
解释
在关于 Linux 内核开发的《教堂与集市》一书中,埃里克·雷蒙德 (Eric Raymond) 写道:“只要有足够的眼光,所有 bug 都是微不足道的”。他将此称为“莱纳斯定律”以纪念莱纳斯·托瓦兹。
意思是,如果很多人看代码,那么相比很少人看代码而言,可以更好地揭露代码中的错误。
在软件开发中的应用
如果您想摆脱 bug,请让其他人查看您的代码。
源于开源社区的一种常见做法是让开发人员提出包含代码更改的拉取请求(pull request),然后让其他开发人员在将拉取请求合并到主分支之前审查该拉取请求。这种做法也进入了闭源开发,但根据 Linus 定律,拉取请求在闭源环境(只有少数人查看它)中的作用不如在开源环境中(其中 可能很多贡献者都在看它)。
其他为代码添加更多眼球的做法是结对编程和群体编程。至少在闭源环境中,这些在避免错误方面比拉取请求审查更有效,因为每个人都参与了代码的初始阶段,这为每个人提供了更好的上下文来理解代码和潜在的错误。
沃斯定律
解释
沃斯定律指出,软件变慢的速度比硬件变快的速度要快。
在软件开发中的应用
不要依赖强大的硬件来运行性能不佳的代码。相反,代码要加强性能优化。
这必须与 [[软件开发定律#Knuth 的优化原则]] 的格言相平衡,该格言说“过早的优化是万恶之源”。要把精力花在为用户构建新功能上,而不是用于代码的性能优化上。
通常,这是一种平衡的艺术。
克努斯**优化原则**
解释
唐纳德·克努斯 (Donald Knuth) 在他的一部作品中写下了“过早优化是万恶之源”这句话,这句话经常断章取意,并被用作根本不关心优化代码的借口。
在软件开发中的应用
根据克努斯定律,我们不应该浪费精力过早地优化代码。然而,根据沃斯定律,我们也不应该依赖硬件足够快来执行未经优化的代码。
最后,这就是我从这些原则中得出的结论:
- 优化可以轻松完成且不需要太多努力的代码:例如,编写几行额外代码以避免经历可能有很多项的循环
- 优化一直在执行的代码路径中的代码
- 除此之外,不要在优化代码上花太多精力,除非你已经确定了一个性能瓶颈。
保持怀疑
定律和原则是好的。它允许我们从某个角度评估某些情况,如果没有它们,我们可能不会有这些情况。
然而,盲目地将法律和原则应用于每种情况是行不通的。每一种情况都会带来微妙的变化,这可能意味着某个原则不能或不应该被应用。
对你遇到的原则和定律保持怀疑。世界并不是非黑即白的。
本文译自: Laws and Principles of Software Development – Reflectoring