软件开发的常见认知规律和原则 - Reflectoring


本文列举了一些可以应用于软件开发的最流行的规则和原则。对于每条定律,我们将快速讨论其主要命题,然后探讨如何将其应用于软件开发。
 
帕累托原则(80/20 规则)
帕累托原则指出,通常80% 的结果来自 20% 的原因。数字 80 和 20 无论如何都不是精确的,但该原则的总体思路是结果通常分布不均。
我们可以在生活的许多领域遵守这条规则,例如:

  • 世界上最富有的 20% 的人创造了世界 80% 的收入,
  • 80%的犯罪是由20%的罪犯所为
  • 自 2020 年以来,我们知道 80% 的病毒传播来自 20% 的受感染人群。

我们可以从帕累托原则中获得的主要好处是专注。它可以帮助我们专注于重要的事情(20%),而不是在不重要的事情(其他 80%)上浪费时间和精力。不重要的事情对我们来说往往很重要,因为有太多(而且看起来很紧急)。但是最好的结果往往是通过关注重要的少数来实现的。
在软件开发中,我们可以使用它来专注于构建正确的功能,例如:
  • 专注于构成产品价值 80% 的产品功能的 20%,
  • 专注于导致 80% 用户沮丧的 20% 错误,
  • 专注于 80% 的产品功能需要 20% 的总时间来构建,

关注“现在最重要的事情是什么?” 可以帮助建立下一个最重要的事情,而不是下一个最紧急的事情。
顺便说一下,敏捷和 DevOps 等现代开发方法有助于获得这种关注!具有定期用户反馈的快速迭代允许对重要事项进行数据驱动的决策。像基于主干的开发与功能标记这样的实践可以帮助软件团队实现目标。
 
破窗定理
破碎的窗户会招致故意破坏,因此很快就会损坏所有窗户。
一般来说:混乱会招致更多的混乱。
如果我们的环境是原始的,我们就会有动力保持这种状态。环境中的混乱越多,我们添加混乱的门槛就越低。毕竟已经混乱了……谁在乎我们是否再添加一点呢?
我们可以从这条规则中获得的主要好处是我们应该意识到我们周围的混乱。如果它达到人们习惯于不再关心它的程度,那么最好给混乱带来一些秩序。
在软件开发中,我们可以将其应用于代码质量:我们引入代码库的每一种代码味道都会降低我们添加更多代码味道的门槛。我们应该 [[Start Clean]] 并保持代码库干净以避免这种情况发生。许多代码库如此难以理解和维护的原因是,破窗已经悄然出现并且没有足够快地修复。
我们也可以将这个原则应用到测试覆盖率上:一旦有一定数量的代码进入了未被测试覆盖的代码库,就会添加更多未被覆盖的代码。这是保持100% 代码覆盖率(应该覆盖的代码的)的论据,因此我们可以在窗口破裂之前看到裂缝。
 
奥卡姆剃刀
哲学剃刀是一种通过消除(或“削除”)不太可能的解释来帮助解释某些事情的原则。
奥卡姆剃刀说,如果有多个假设,我们应该选择假设最少的假设(这很可能是解释最简单的假设)。
我们可以在事件分析中应用奥卡姆剃刀。您可能遇到过这样的情况:用户报告了您的应用程序存在问题,但您不知道导致问题的原因。因此,您正在搜索日志和指标,试图找到根本原因。
下次用户报告错误时,请维护事件调查文档。写下您对导致问题的原因的假设。然后,对于每个假设,列出事实和假设。如果一个假设被证明是正确的,则将其标记为事实。如果一个假设被证明是错误的,请将其从文档中删除或将其标记为错误。在任何时候,您现在都可以将时间集中在最可能的假设上,而不是浪费时间追逐红鲱鱼。
 
邓宁-克鲁格效应
邓宁-克鲁格效应表明,没有经验的人往往会高估自己的能力,而有经验的人往往会低估自己的能力。
如果你不擅长某件事,你会认为你擅长它。如果你擅长某事,你会认为你不擅长 - 这可能导致冒名顶替综合症,这让你非常怀疑自己的能力,以至于你在其他具有相似技能的人中感到不舒服 - 不必要地害怕被暴露诈骗。
意识到这种认知偏差已经是朝着正确方向迈出的重要一步。它将帮助您更好地评估自己的技能,以便您可以寻求帮助,或者克服自我怀疑并自己动手。
有助于消除邓宁-克鲁格效应和冒名顶替综合症的一种做法是结对或群体编程。你不是独自工作,沉浸在自我怀疑或优越感中,而是与他人密切合作,在工作的同时交流思想、学习和教学。
不过,这只适用于安全的环境。在个人主义被美化的环境中,结对或群体编程会导致更多的自我怀疑或更多的优越感妄想。
 
彼得原理
彼得原理指出,只要你成功,你就会得到晋升,直到你最终得到一份你不称职的工作。
既然你不再成功,你就不会再得到提升,这意味着你将生活在一份不会给你带来满足感或成功的工作中,贯穿你的一生中。
在软件开发中,当您将角色从开发人员职业转换为管理职业时,彼得原则通常适用。然而,成为一名优秀的开发人员并不一定意味着你是一名优秀的经理。或者,您可能是一名优秀的经理,但只是不要从开发人员工作中获得的经理工作中获得满足感,这意味着您没有全力以赴(这就是我的情况)。在任何情况下,你都很痛苦,在你的职业道路上看不到任何未来的发展。
在这种情况下,退后一步,决定你希望你的职业是什么样子。然后,转换角色(或公司,如果需要)以获得您想要的角色。
 
帕金森定律
帕金森定律指出,工作总是会填满分配给它的时间。如果您的项目在两周内有截止日期,则该项目将不会在此之前完成。可能需要更长的时间,是的,但绝不会少于我们为它分配的时间,因为我们正在用不必要的工作或拖延来填补时间。
帕金森定律的主要驱动因素是:
  • 拖延症(“截止日期太远了,所以我现在不需要匆忙……”),以及
  • 范围蔓延(“当然,我们可以添加这个小功能,它不会花费我们太多时间......”)。

为了对抗拖延,我们可以在几天而不是几周或几个月内设定最后期限。在接下来的 2-3 天内需要做什么才能朝着目标前进?一个(健康的!)截止日期可以给我们足够的动力,不要陷入拖延症的低谷。
为了防止范围蔓延,我们应该非常清楚地了解我们试图通过项目实现的目标。成功的衡量标准是什么?这个新功能是否会增加这些指标?那么如果每个人都明白这项工作需要更长的时间,我们应该添加它。如果新功能与使命宣言不符,就让它不存在。
 
霍夫施塔特定律
霍夫施塔特定律指出**“它总是比您预期的要长,即使您考虑了霍夫施塔特定律”。
即使您了解了这条规则,并增加了项目的时间分配,它仍然会比您预期的要长。这与帕金森定律密切相关,即工作总是会填满分配给它的时间。只有霍夫施塔特定律说它填充的时间超过了分配的时间。
这条定律得到了心理学的支持。我们容易出现所谓的“规划谬误”,即在估算工作时,我们通常不会考虑所有可用信息,即使我们认为我们已经考虑了。我们的估计几乎总是主观的,很少是正确的。
在软件开发中(以及任何其他基于项目的工作,真的),我们人类的乐观主义占了上风。估计几乎总是过于乐观。
为了减少霍夫施塔特定律的影响,我们可以尝试尽可能客观地进行估计。
写下关于项目的假设和事实。将每个项目标记为假设或事实,以使数据质量可见并管理预期。
不要依赖直觉,因为每个人的感受都不一样。写下估算值,让你的大脑思考它们。将它们与其他人的估计进行比较,然后讨论差异。
即便如此,它仍然只是一个估计,很可能不能反映现实。如果估算不是基于统计数据或其他历史数据,那么它的价值就非常低,因此与要求您估算的人一起管理预期总是好的 - 总是会出错。如果你让它尽可能客观,它就会减少错误。
 
康威定律
康威定律指出,组织创建的任何系统都将类似于该组织的团队和沟通结构。
系统将有接口,构建系统的团队有接口。如果您有 10 个团队在一个系统上工作,您很可能会得到 10 个相互通信的子系统。
我们可以应用所谓的逆康威机动:创建最能支持我们想要构建的系统架构的组织结构。(banq注:业务决定架构,还是架构决定业务,康威定律是业务决定架构,逆康威其实就是想实现架构决定业务,蒸汽机的工业机器决定了大批工人的生存方式。)
没有固定的团队结构,而是要有足够的灵活性来创建和解散团队,这对系统的当前状态是最好的。
 
墨菲定律
墨菲著名的定律说,任何可能出错的事情,都会出错。它经常在意外发生后被引用。
软件开发是一个很多事情都会出错的职业。出错的主要来源是错误。没有任何软件不存在测试用户耐心的错误或事件。
我们可以通过在日常软件开发实践中养成习惯来减少错误的影响,从而抵御墨菲定律。我们不能完全避免错误,但我们可以而且应该减少它们对用户的影响。
对抗墨菲定律最有用的做法是特征标记。如果我们使用功能标记平台,我们可以在功能标记后面将更改部署到生产中。然后,我们可以使用有针对性的推出来激活内部 dogfooding 的标志,然后为少量友好的 Beta 用户激活它,最后将其发布给所有用户。通过这种方式,我们可以从越来越关键的用户群体那里获得关于变化的反馈。如果更改出错(并且在某些时候会出错),影响很小,因为只有一小部分用户组会受到它的影响。而且,该标志可以快速关闭。
 
布鲁克定律
在经典著作《人月神话》中,弗雷德·布鲁克 (Fred Brook) 有句名言:为迟到的项目增加人力会使其更晚。
尽管本书讨论的是软件项目,但它适用于大多数类型的项目,甚至是软件开发之外的项目。
添加人员不会提高项目速度的原因是项目的通信开销随着添加到项目中的每个人呈指数增长。2个人有1条通信路径,5个人已经有5条了!= 120 条可能的通信路径。新人安顿下来并确定他们需要的沟通路径需要时间,这就是为什么在项目中添加新人时,迟到的项目会更晚。
解决办法很简单:更改截止日期,而不是将人员添加到已经迟到的项目中。
对在软件项目中增加新人的期望要切合实际。将人员添加到项目中可能会在某个时候提高速度,但并非总是如此,当然也不是立即。人员和团队需要时间来适应工作程序,而在某些时候,工作无法充分并行化,因此增加更多人是没有意义的。仔细考虑一个新人应该做哪些任务,以及在将该人添加到项目中时您期望什么。
 
波斯特定律
Postel 定律也被称为稳健性原则,它规定你应该“在你所做的事情上保守,在你接受别人的事情上自由”。
换句话说,您可以接受多种不同形式的数据,以使您的软件尽可能灵活,但在处理这些数据时应非常小心,以免因无效或恶意数据而损害您的软件。
该定律源于软件开发,因此非常直接适用。
您的软件与其他软件或人类之间的接口应允许不同形式的输入以实现稳健性:
  • 为了向后兼容,新版本的接口应该接受旧版本和新版本的数据,
  • 为了更好的用户体验,UI 中的表单应该接受不同格式的数据,这样用户就不必担心格式。

但是,如果我们愿意接受不同格式的数据,我们在处理这些数据时就必须保守。我们必须审查无效值,并确保我们不会因为允许太多不同的格式而损害系统的安全性。SQL 注入是一种可能的攻击,它是通过对用户输入过于宽松而启用的。
 
克奇霍夫原理
Kerchkhoff 的原则指出,加密系统应该是安全的,即使它的方法是公知的。只有您用来解密某些东西的密钥才需要是私有的。
永远不要相信要求一种方法是私有的加密系统。这被称为“默默无闻的安全”。这样的系统本质上是不安全的。一旦该方法向公众公开,它就容易受到攻击。
相反,依靠公开审查和信任的对称和非对称加密系统,在可以公开审查的开源包中实施。每个想知道他们内部如何工作的人都可以查看代码并验证它们是否安全。
 
莱纳斯定律
据报道,莱纳斯·托瓦兹 (Linus Torvalds) 说“如果有足够的眼球,所有错误都是浅薄的”。
这意味着如果很多人看代码比很少人看代码可以更好地暴露代码中的错误。
如果您想摆脱错误,请让其他人查看您的代码。
源自开源社区的一种常见做法是让开发人员提出包含代码更改的拉取请求,然后让其他开发人员在将拉取请求合并到主分支之前审查该拉取请求。这种做法也进入了闭源开发,但根据 Linus 莱纳斯定律,拉取请求在闭源环境(只有少数人查看它)中的作用不如在开源环境中(其中可能很多贡献者都在看它)。
为代码添加更多眼球的其他做法是结对编程和 mob 编程。至少在闭源环境中,这些在避免错误方面比拉取请求审查更有效,因为每个人都参与了代码的初始阶段,这为每个人提供了更好的上下文来理解代码和潜在的错误。
 
沃斯定律
沃斯定律指出,软件变慢的速度比硬件变快的速度要快。
不要依赖强大的硬件来运行性能不佳的代码。相反,编写经过优化以表现良好的代码。
这必须与 [[软件开发定律Knuth 的优化原则]] 的格言相平衡,该格言说“过早的优化是万恶之源”。与为用户构建新功能所花费的精力相比,不要在使代码运行得更快上花费更多的精力。
通常,这是一种平衡行为。( 算法信仰的力量:改进算法能提升多少性能?
 
Knuth 的优化原则
Donald Knuth 在他的一部作品中写了“过早优化是万恶之源”这句话,这句话经常断章取意,被用作根本不关心优化代码的借口。
根据 Knuth 定律,我们不应该浪费精力过早地优化代码。然而,根据沃斯定律,我们也不应该依赖硬件足够快来执行优化不当的代码。
最后,这就是我从这些原则中得出的结论:
  • 优化可以轻松完成的代码,无需太多努力:例如,编写几行额外代码以避免经历可能包含大量项目的循环
  • 优化一直执行的代码路径中的代码
  • 除此之外,不要在优化代码上花费太多精力,除非您已经确定了性能瓶颈。

 
最后:保持怀疑
规则和原则是好的。这使我们能够从某个角度评估某些情况,如果没有它们,我们可能不会拥有这些情况。
然而,盲目地将规则和原则应用于每种情况是行不通的。每一种情况都会带来微妙之处,这可能意味着某个原则不能或不应该被应用。
对你遇到的原则和规则保持怀疑。世界不是非黑即白的。