代码简单性的定义与实现之道

本文深入探讨软件简单性的定义,指出简单性意味着代码易于阅读、理解和正确修改,并分析导致复杂性的两大主因:缺乏代码所有权和时间压力,强调简单性本质上是一个人类因素而非技术问题。

代码简单性的定义

多年前,我写了一篇博客文章解释计算机的问题所在,基本上是说问题是复杂性。几年后,我出版了《代码简单性》,这基本上是一篇论文,描述了简单性为何以及如何成为软件最重要的质量。

又过了许多年,我坐在一间满是世界上最有经验的软件工程师的房间里,制定我们想要构建软件开发的指导方针和原则,在询问了整个房间后,我得出了一个可怕的认识:没有人曾经定义过软件的“简单性”是什么。

我可能天真地认为这是一个已知的事实——当我说“简单性”时,每个人都明白我的意思。在某种程度上,老实说,这是真的。当你说“简单性”这个词时,人们至少会有一些概念。但我注意到人们会以许多不同的方式应用它,其中一些完全不是我想要的。我会看到人们指着一个函数或文件说:“看,它现在代码行数更少,因此更简单!”或者说:“看,这个系统使用了某某设计模式,因此现在更简单了!”或者更糟的是,“这个系统现在完全通用,遵循了‘大家都知道’你应该对软件做的所有事情,所以这很简单,对吧?”

于是,我开始寻找某种有效的简单性定义。最终,我不得不自己提出一个。实际上,我在几年前就想出来了,我一直想写一篇博客文章来讨论它,但就是没有做。那么,这个伟大谜题的答案是什么?对于软件来说,什么是简单性?

对于软件,“简单”意味着易于阅读、理解和正确修改。

关于这个定义有几个重要点。

首先,简单性根本上是一个人类因素。它不是由机器引起的,也不是为机器做的。只有人类阅读和理解软件。至于“正确修改”,是的,这可以由计算机完成,并且在简单性的某些方面,你可能正在使自动重构工具等更容易修改代码。但重要的部分是我们希望人们能够正确修改软件。

这立刻告诉你,你永远不会编写一个能够神奇地完成所有软件简化的计算机程序。工具绝对有助于人们简化和使代码易于理解。但它们不能完成所有工作。当有人想要在他们公司承担简化软件的任务时,如果他们的唯一解决方案是工具解决方案,要非常怀疑。如果他们说,“我们想通过改进工具来鼓励这种更好的实践”,那很好!这是一个人类因素。实践涉及人。但永远不要忽视这样一个事实:简化软件总是涉及人类主动行动来发展这种简单性(通常是通过删除或修改难以理解的内容,使其变得更容易理解)。

这也告诉我们,永远不会有自动分析系统告诉我们软件是否复杂。这是致力于软件简单性的人们经常提出的问题——我如何衡量某物的简单程度?简单性是一种只有人类才能体验到的质量。除了观察者的观点之外,它没有内在的真理。代码没有称为“简单性”的内在质量。你无法在纸上写下一个数字来说明你的代码有多简单。你可以做的是从人们那里了解他们觉得一段代码有多简单或多复杂。(顺便说一句,你通常不能直接问他们有多复杂,但你可以询问他们的情绪反应,这通常是复杂程度的最佳指标。如果他们发现某些代码或系统令人沮丧、害怕、愤怒、绝望等,这通常是复杂性的好迹象。)因此,任何软件简单性的测量都必须包括通过从人们那里了解情况来进行测量。一旦你通过人们完成了测量,你可能会发现某些模式或系统几乎普遍是糟糕或复杂的,你可以编写禁止或修复这些模式的工具。但对复杂性及其有效性的理解来自于了解人们用代码做什么、他们对代码的看法、他们的感受等等。

这告诉我们的一件事是,当一个人花一些时间关注代码的简单性时,简单性往往会出现。这听起来很明显,但如果你观察许多软件团队的行为,你会发现他们并非基于这一事实运作。具体来说,这意味着某个人负责一段代码(不是“为此负责”意义上的负责,而是“拥有它并积极处理它”意义上的负责)几乎是发展简单性所必需的。这在实际中也是如此。你可以看到,阅读、理解和修改未维护、无人拥有的代码几乎总是随着时间的推移变得越来越困难。我只说“几乎总是”是因为我没有看过世界上每一段代码,而且为了完全正确,你必须无限期地观察它(也就是说,它未维护的时间越长,往往变得越来越复杂,所以有时它必须未维护很长时间你才会真正遇到这种情况)。但在我见过的每一种情况下都是如此——我不知道有任何反例,即一段代码在未维护的时间越长时变得更简单。当你让软件无人拥有时,你就是在允许它随着时间的推移变得越来越难以阅读、理解和维护。

除了缺乏所有权之外,复杂性的另一个主要原因是时间压缩。事实上,这是复杂性最常见的原因——可能是复杂性的唯一真正原因。我所说的“时间压缩”基本上是指让人们感觉他们没有足够的时间。有趣的是,这最常由程序员自己对自己做。他们说这是由管理层做的(“他们给了我这些截止日期,现在我不得不偷工减料”),有时这是真的。但更多时候,开发人员自己只是感到一种“完成”这项工作的压力。他们觉得需要完成某事,否则有人会生气,或者他们会遇到麻烦,或者他们不够快,或者有人会认为他们是糟糕的程序员,或者,或者,或者……但通常这些都不是真的,实际情况是他们完全有自由多花一点时间以正确的方式做某事。

如果你认为这不正确,下次你看到一个临时解决方案时,问问开发人员为什么他们这样做。他们要么会告诉你他们不理解自己在做什么(复杂性的另一个主要原因),要么他们会告诉你类似这样的话:“嗯,那个其他库很难用,而且工作不正常,所以我不得不这样做。”但仔细想想。开发人员通常是在说,“我不想花时间修复那个其他库。”哇,你说,这很苛刻!修复那个其他库可能工作量很大!没错,但他们真的有时间做吗?也许他们有。也可以说,“我觉得对那个库没有责任”,这再次看到责任在复杂性原因中的作用。也许它“超出了他们的控制”,比如它在另一家公司之类的。好吧,这仍然是对他们愿意承担的责任水平的声明。我不是说那里的决定不好,只是你必须认识到你正在有意识地决定承担多少责任(你可以联系另一家公司,向他们报告,与他们合作修复它等等),并且你故意决定制造复杂性,而不是花时间发展简单性。

无论如何,我希望这能让你更好地理解简单性是什么以及实际上是什么导致了它。记住,当你与某人谈论简单性时,首先要确保他们知道你真正谈论的是使代码更易于阅读、理解和正确维护!

-Max

评论

Steven Gordon, PhD 说: 2020年5月20日凌晨4:47 软件开发主要是一个人的问题,而不是技术问题(不确定谁最先说的),所以简单性不是技术性的东西是完全合理的。但是,这带来了人类问题的所有混乱。对一个人“易于阅读、理解和正确修改”的代码可能对另一个人不容易(反之亦然)。这使得鼓励或允许单个人“拥有”代码库的任何部分都存在问题,因为那个人认为的容易可能相当 idiosyncratic。鼓励诸如共享所有权、频繁配对甚至群体编程等实践的最佳原因之一是促进产生许多人都认为简单的代码,而不是只有“所有者”认为简单的代码。

顺便说一句,我用于代码简单性的一个“技术”标准是,它与所需注释的数量成反比。

回复

Max Kanat-Alexander 说: 2020年6月3日上午8:32 嘿 Steven!完全同意这对每个人都是不同的。我也同意你可以在什么是简单上达成一些一致,而且结对编程和代码审查都有助于这一点!这实际上有点像写作,理解读者的观点是有帮助的。

就像物理宇宙中的每一个问题一样,对此没有“完美”的解决方案,但有_好的_解决方案。在实际实践中,肯定可以为预期的读者在上下文中使事情变得简单。

-Max

回复

Steven Gordon, PhD 说: 2020年6月3日下午2:11 有很多问题有完美的解决方案,只是没有涉及人类的问题。

我文章的主要观点是反驳“某个人负责一段代码(不是‘为此负责’意义上的负责,而是‘拥有它并积极处理它’意义上的负责)几乎是发展简单性所必需的”。在40多年的经验中,我发现代码库的个体所有权几乎总是导致 idiosyncratic 复杂性。老派的解决方案是代码审查,但这发生得太晚且太不频繁。通过结对和群体编程实现的共享代码所有权在实现可维护性和简单性方面已被证明比个体所有权有效得多。

回复

Kurt Guntheroth 说: 2020年5月20日上午7:51 即使提出的简单性定义也不充分。不要用“容易”,试试“尽可能容易”。这解释了一个事实,即操作系统内核模块永远不可能像具有相同行数的 CRUD 屏幕那样简单,因为内核模块在更多约束下工作。

即使这个对简单性的描述也未能成为一个定义,因为你甚至原则上无法用它来判断一段软件是否简单。我认为,如果我们原则上无法构建一台机器来确定一段软件是否简单,那一定是因为我们实际上并不理解简单的含义。也许我们可以解决“更简单”这个较小的问题。我们至少应该能够判断一段软件是否比另一段产生相同输出的软件更简单。

回复

Steven Gordon, PhD 说: 2020年5月20日上午11:19 Kurt,

一个描述不必可测量才能有资格成为定义。拥有一个可测量的定义会很好,但除非你有一个好的候选方案,否则指责一个定义不可测量是不公平的。

回复

Max Kanat-Alexander 说: 2020年6月3日上午8:34 嘿 Kurt。确实,不同的事物以不同的方式简单。这没关系。物理宇宙中任何地方都没有绝对。这只是另一个案例(就像所有情况,对于所有事情一样),你必须以灰度思维而不是黑白思维。

-Max

回复

Nelson Ferragut 说: 2020年5月20日上午8:34 出色的概念分解——谢谢!如果我要给“易于阅读、理解和正确修改”附加一个词,我会用“可维护性”。你会说“简单性”和“可维护性”有区别吗?

回复

Max Kanat-Alexander 说: 2020年6月3日上午8:35 嘿 Nelson!我想我通过说“正确修改”以更实际的方式捕捉了可维护性,因为这捕捉了人们试图用维护做什么——进行与他们打算做的更改相匹配的更改。

-Max

回复

Nelson Ferragut 说: 2020年6月3日下午12:11 嗨 Max,有道理。可维护性在其核心包含的内容比简单性少。我可以接受这一点。再次感谢。

回复

Jay Kishan 说: 2020年10月27日凌晨2:53 你好 max。你提交的博客非常好,你如何解释使代码简单易懂。所以,感谢分享这篇博客。它对我帮助很大。

回复

Ashik Rahman 说: 2021年1月9日晚上9:16 我为我的论文读了这篇文章。这篇文章真的帮了我很多。感谢作者写了这么好的文章。

回复

adamwilson1234 说: 2022年6月5日上午9:38 “当每个人都负责时,没有人真正负责。”――阿尔伯特·班杜拉,《道德控制的选择性激活与脱离》

我见过团队负责系统的不同部分,但有时只在代码审查阶段。其他团队会修改代码,然后获得所有者(们)的批准。如果你必须这样做,更大的组织至少应该促进团队间的关系建立、信任建立,并灌输对一套核心“简单性”原则的认同。这只是良好的入职实践。不要指望个人主动去联系他人。

回复

adamwilson1234 说: 2022年6月5日上午9:40 顺便说一句,我喜欢这篇文章。

回复

BugRaptors 说: 2024年1月22日凌晨4:34 你好 Max,你的博客很棒!你简化和解释代码的方式真的很有帮助。感谢分享这个宝贵的资源;它对我来说非常有益。

回复

Software Tester 说: 2024年12月24日上午10:39 感谢分享这篇博客,Max!刚刚下载了你的免费电子书。

回复

The Psychology of Patrick Star: Is He Really Dumb or Just Carefree? - The Cartoon Journal 说: 2025年3月20日上午9:51 […] 派大星是一个体现人性复杂性的人物——愚蠢与深刻简单性的混合体。他无忧无虑的生活态度提供了一种清新的视角,鼓励我们重新评估我们的[…]

回复

发表回复

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计