原文地址

在软件开发项目中一个常见的争论, 花时间在提高软件质量, 还是专注于发布更有价值的功能. 通常来说, 提供新功能主导着讨论, 导致很多开发人员抱怨他们没有时间花在架构和代码质量上.

Betteridge 的头条新闻定律告诉我们, 任何标题以问号结尾的文章都可以用"不"来概括. 那些熟悉我的人不会怀疑我想违背这个定律. 但是这篇文章走远了 - 它直接颠覆了这个问题. 这个问题假设在质量和成本之间是有取舍的. 但是这个情况并不适用于软件开发: 高质量的软件其实会在开发时消耗更低的成本.

虽然我的大部分文章都是针对专业的软件开发人员的, 但是本文不会假设你有任何有关软件开发机制的知识. 我希望这篇文章能够对任何与软件相关工作有关的人都有帮助, 尤其是作为软件开发团队的商业领袖.

我们习惯在质量和成本之间做取舍

就像我在开头提到的, 我们习惯在质量和成本之间做取舍. 当我在更换智能手机时, 我可以选择更昂贵的型号,具有更快的处理器,更好的屏幕和更多的内存. 或者我可以放弃其中的一些"质量"来省钱. (Or I can give up some of those qualities to pay less money.) 这其中并没有一个绝对的规则, 有时我们可以用便宜的价格买到质量好的商品. 更多情况下, 我们有不同衡量价值的标准: 有些人其实不会真正意识到这个屏幕比另一个更好. 但是大多数情况下这种假设是正确的: 更好的质量通常会花费更多.

软件质量意味着很多事情

在我讨论软件质量之前, 我需要解释一下它是什么. 这里有一个复杂的问题: 很多东西都可以算作软件质量. 我能想到 UI: 他是否能轻松引导我需要做的任务, 并且使我更加高效而且减少挫折? 我能想到可靠性: 它包含可能会造成错误的缺陷吗? 架构是它的另一个方面: 源码是否被分为清晰的模块, 能够使程序员轻易地理解他们这周所要工作的代码.

这三个质量的例子并不是一个详细的列表, 但是他们足够表明一个重要的观点. 如果我是软件的客户或用户, 我不会称赞那些我们称之为质量的东西. 用户会判断 UI 是不是好. 高管能判断他的员工是不是更加高效. 用户和客户会注意到缺陷, 特别是在丢失数据和系统不工作时. 但是客户和用户不会感知到软件的架构.

因此, 我把软件质量分为外部(UI 和缺陷)和内部(架构). 区别在于用户和客户能够区分出一个软件产品有高的外部质量, 而无法区分出高或者低的内部质量.

乍一看, 内部质量对用户来说无关紧要

既然内部质量是客户和用户看不见的, 那它重要吗? 让我们想象一下 Rebecca 和我写一个追踪和预测航班延误的应用. 我们的应用都是做了一样的核心功能, 都有优雅的 UI, 也都几乎没有缺陷. 唯一的不同是她的代码是被整洁地整理过的, 而我的是一团糟. 然后这还另外一个不同: 我卖 $6, 她卖 $10.

既然客户不会看到源码, 而且源码也不会对应用的运行有影响, 那为什么额有人会为 Rebecca 的软件多付$4 呢? 换句话说, 为更好的内部质量付钱是不值得的.

我的另一种表达方式是: 为了外部质量付出是有意义的, 而为内部质量付出是没有意义的. 用户会判断他们是不是会为更好的 UI 花更多的钱,因为他们能够看到 UI 是否是够好以至于能够值那些钱. 但是哟哦那个户看不到软件内部的结构, 更别说判断它是不是更好了. 为什么要为没有效果的东西付出更多?既然如此 - 为什么软件开发人员应该花时间和精力来提高工作的内部质量?

内部质量可以更轻松地增强软件

所以为什么软件开发者还提出内部质量的问题呢? 程序员将最多的时间花在了修改代码上. 甚至在一个新系统中, 几乎所有的编程工作也都是在一个已有代码基础的环境里进行的. 当我想为软件增加新功能时, 我的第一个任务时找出如何将这个新特性整合进当前软件的工作流程中。然后我需要改变这个流程使我的功能整合进去. 我经常使用应用中已经存在的数据, 所以我需要理解这些数据代表着什么, 它和它周围的数据有怎样的关系,为了我的新功能我需要什么数据.

所有的这些都和我理解已存在的代码有关. 但是软件经常变得很难理解. 逻辑非常乱, 数据难以理解, 在六个月前某个命名可能对 Tony 有意义, 但是现在对于我来说, 它和 Tony 离职的原因一样神秘. 这些形式都是程序员所指的 cruft - 当前代码的样子和它理想中样子的差别.

客户只关心新功能快速的上线

让我们看一下为什么内部质量对于用户和客户来说是有意义的. 更好的内部质量可以使新特性的增加变得简单, 因此变得更快和更便宜. Rebecca 和我也许现在都有一个一样的应用, 但是在接下来的几个月里, Rebecca 更高的质量可以让她可以每星期更快得增加一些新特性, 而我一值卡在处理一些 cruft, 只为了作出一些很简单的特性. 我无法和 Rebecca 的开发速度做竞争, 很快她的软件比我的更具有特色. 然后我所有的用户卸载了我的应用, 转而用 Rebecca 的, 尽管她又提高了她软件的价格.

crufts

如果我们将一个有很多 cruft 的系统和另一个等价的,但是没有 cruft 的系统相比. Cruft 意味着新特性会花费更多的时间, 花费多余的时间是 cruft 的代价, 而且每次做新特性时都会有. 没有 cruft, 新特性可以更快地加进去.

可视化内部质量的影响

内部质量的基本作用是降低未来变化的成本. 但是编写好的软件需要额外的努力, 这在短期内会产生一些成本.

一种可视化的方法是看我绘制的软件积累功能以及时间(和成本)的假想图. 对于大多数的软件工作, 曲线看起来是这样的.

curve with cumulative functionality and time

纵轴: 功能累计, 横轴: 时间.
对于大多数的软件系统来说, 随着时间的推移增加新功能变得越来越难. 这意味着需要较长的时间才能够体现出成本的增加.

这就是内部质量差的情况. 进度在一开始很快, 但是随着时间的推移, 增加新功能变得越来越难. 甚至一个小改动都需要程序员理解大量的代码, 而且是难以理解的代码. 当他们作出改变的时候, 会造成预期外的问题, 使得需要大量时间的来测试和修复问题.

注意高的内部质量就是为了减少生产力的下降. 事实上,在有些产品会产生相反的效果,开发人员可以通过利用先前的工作轻松构建新功能. 因为它需要一支技术精湛,训练有素的团队来实现这一目标. 但是我们只有偶尔会见到这样.

compare

纵轴: 功能累计, 横轴: 时间.
高质量的软件在一开始时, 开发速度明没有那么快. 但是以后会更快, 更便宜. 这个点在几周内就会发生, 而不是几个月.

这里有一个微妙的地方: 有一段时间里, 低质量是比高质量更具有生产力的. 在这个时间段是可以在质量和成本之间里做一些 trade-off. 当然, 问题在这: 这个时期到底会有多长.

这里我们要弄明白为什么这是一个假想图. 我们无法量化软件团队提供的产出。 由于无法量化产出,从而无法量化生产率,因此无法对低内部质量的后果(这也很难量化)提出可靠的数字。 无法量化产出在专业工作中非常普遍 - 我们如何量化律师或医生的生产力?

我通过征求我所知道熟练开发人员的意见,来评估交叉点的. 答案让很多人感到惊讶. 开发者发现低质量的代码会在几周内显著得降低他们的生产力. 因此,内部质量和成本之间的权衡取舍并不. 即使小的项目也能从好的软件实践中获益, 这也能从我的经历中证明.

即使最棒的团队也会产生 cruft

许多非开发人员倾向于认为只有当开发团队粗心大意并且犯错时才会制造 cruft, 但即使是最优秀的团队也会在工作时不可避免地产生一些 cruft.

我想用一个当我和我们最好的技术团队领导聊天的故事来说明这一点. 他刚刚完成了一个被广泛认为是非常成功的项目. 无论是在功能, 施工时间和成本方面, 客户都对交付的系统感到满意. 我们的员工对该项目的工作经验持积极态度. 技术领导确实很高兴, 但也承认系统的架构并不好. 我的反应是"怎么可能 - 你是我们最好的架构师之一." 他的答复是任何一位经验丰富的软件架构师都熟悉的答案:“我们做出了很好的决定, 但现在才真正明白我们应该如何构建它”.

很多人, 包括一些软件行业的一些人, 会把构建软件比作建造大教堂或者摩天大楼 - 毕竟这是我们把高级程序员称作架构师的原因. 但是构建软件需要在一个充满着不确定的未知世界中, 而不是一个物理世界.

高质量的软件生产成本更低

总结一下上面所说的:

  • 忽视内部质量会导致 cruft 的快速堆积
  • cruft 拖慢了 feature 的开发
  • 即使是是优秀的团队也会产生 cruft, 但是通过保持高的内部质量, cruft 才能够变得可控
  • 高的内部质量使 cruft 保持在最少, 从而允许团队可以用少的人力, 时间和成本来增加新 feature

可悲的是,软件开发人员通常不能很好地解释这种情况. 我和开发团队讨论过很多次, 她们说"他们(管理层)不让我们写高质量的代码, 因为这会耗费太多的时间". Developers often justify attention to quality by justifying through the need for proper professionalism. (开发者经常用"专业性的体现"来正当化高质量的代码?) 但是这暗示了高质量是有代价的, 这注定了他们的论点. 令人讨厌的是, 由此产生的繁琐代码既使开发人员的生活更艰难, 又使客户付出了很多钱. 在考虑内部质量时, 我强调我们仅应将其视为一种经济论点. 较高的内部质量降低了将来功能的成本, 这意味着花时间编写好的代码实际上降低了成本.

这就是为什么问题一开始没有指出重点. 高质量软件带来的"成本"是负的(不会带来成本, 反而会减少成本). 我们习惯于在生活是对大多数质量和成本之间做取舍, 但是这对软件的质量来说是没有意义的. (他对于外部质量是有意义的, 比如说一个精心设计的 UE.) 由于成本和内部质量之间的关系不同寻常而且违反直觉, 因此很难被接受. 但是了解这一点对于最大效率的开发软件至关重要.

(完)