软件简单性的定义与实现之道

本文深入探讨了软件简单性的真正含义,指出简单性意味着代码易于阅读、理解和正确修改,并分析了导致复杂性的两大主因:缺乏代码所有权和时间压力,为提升代码质量提供了实用指导。

代码简单性:定义与实现

简单性的定义

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

又过了许多年,我在一个聚集了世界上最有经验的软件工程师的房间里,讨论我们想要围绕哪些指导方针和原则来构建软件开发。在询问了整个房间后,我意识到一个可怕的事实:从来没有人定义过软件的"简单性"是什么。

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

于是我开始寻找某种有效的简单性定义。最终,我不得不自己提出一个。实际上,我在几年前就想出了这个定义,一直想写篇博客文章,但一直没有完成。

那么,这个伟大谜题的答案是什么?对于软件来说,什么是简单性?

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

定义的重要方面

关于这个定义有几个重要事项。

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

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

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

简单性的实现条件

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

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

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

总结

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

读者评论精选

Steven Gordon, PhD 说: 软件开发主要是一个人员问题而不是技术问题(不确定谁最先说的),所以简单性不是技术问题是完全合理的。但是,这带来了人类问题的所有混乱。

对一个人"易于阅读、理解和正确修改"的代码可能对另一个人不容易(反之亦然)。这使得鼓励或允许单个人"拥有"代码库的任何部分都存在问题,因为这个人认为的简单可能相当特殊。鼓励诸如共享所有权、频繁配对甚至群体编程等实践的最佳原因之一是促进产生许多人都认为简单的代码,而不是只有"所有者"认为简单的代码。

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

Max Kanat-Alexander 回复: 嘿 Steven!完全同意这对每个人都是不同的。我也同意你可以在什么是简单的问题上达成一些一致,而且配对编程和代码审查都有助于这一点!这实际上有点像写作,理解读者的观点是有帮助的。

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

Kurt Guntheroth 说: 即使提出的简单性定义也不充分。不要用"容易”,试试"尽可能容易”。这解释了一个事实,即操作系统内核模块永远不可能与具有相同行数的 CRUD 屏幕一样简单,因为内核模块在更多的约束条件下工作。

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

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

Max Kanat-Alexander 回复: 嘿 Nelson!我想我通过说"正确修改"以更实际的方式捕捉了可维护性,因为这捕捉了人们试图通过维护做的事情——进行与他们打算做的更改匹配的更改。

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