Jim Bird 是一位经验丰富的软件开发经理、项目经理与 CTO,专注于软件开发与维护、软件质量与安全等领域中疑难问题的解决。在过去的 15 年间,Jim 曾管理过团队建设并主导过高性能的财务系统的建设。他的主要兴趣在于如何提升小团队的效率以构建真正的软件:高质量、安全、可靠、高性能及适应性强。近日,Jim 撰写了一篇博文,谈到了软件开发中变更所带来的影响以及真正的代价,同时还谈到了如何降低变更的代价。
当软件已经设计、编码、测试与实现完毕后,如果要对其进行修改或是修复,那么代价是怎样的呢?关于这个问题存在两种截然相反的观点。一种观点认为越晚修改成本就越高,修改的代价会达到指数级;另一种观点则认为应该尽可能晚地做修改,因为修改软件的代价本质上是水平变化的。那么究竟哪种观点才是正确的呢?我们该如何做呢?
指数级的变更代价
回到上个世纪80 年代初,Barry Boehm 发布了一些统计数字( Software Engineering Economics, 1981 ),表明修改或修复软件的代价会随着时间的流逝呈现出指数级的变化,可以在这里查看变化曲线。
Boehm 的这个结论是根据 70 年代在 TRW 与 IBM 采用瀑布模型的项目数据而得出的,他发现当从需求分析转到架构、设计、编码、测试与部署阶段时,修改软件的成本会逐步增加。当尚处在需求定义阶段时,如果发现了需求上的错误而进行修改时,其代价几乎可以忽略不计。不过,如果等到完成了设计、编码和测试并将软件交付给客户后,那修改的代价可以达到之前的 100 倍以上。
这里要补充几点。首先,大型项目的代价曲线会更高一些(在小型项目中,代价曲线差不多是 1:4 而不是 1:100)。修改成本能达到 100 倍的项目并不常见,Boehm 称之为架构崩溃,这指的是项目基础的架构就是完全错误的(可伸缩性、性能以及可靠性等),而且是在客户已经开始使用系统并遇到严重的操作问题时才发现的。这些分析基于的是 30 年前的少量数据采样,那时编写代码的成本非常高,也很消耗时间,同时缺乏高效的工具。
从那之后还有不少人做了相关的研究,结果也都与 Boehm 的发现很类似,至少基本的观点是一致的,那就是发现问题的时间越晚,修复问题的代价就越高。这些研究成果被很多书籍所引用,比如说 Steve McConnell 的代码大全等,用于证明尽早执行审查和测试的重要性:
总而言之,原则就是发现错误的时间越早,修改的成本就越低。Bug 在软件生态链中存活的时间越长,它对整个软件造成破坏性就越大。由于需求是最先确定的,因此需求上的缺陷就可能驻留系统更长的时间,修改的代价也更高。
水平的变更代价
规则随着开发逐步转向迭代式和增量式而发生了变化。
Boehm 认为如果我们能够提前考虑清楚风险并以增量的方式设计和构建软件(使用他称之为的螺旋模型而不是顺序化的瀑布式模型),那么我们就能尽早发现错误了。
更加现代化、轻量级的敏捷开发方式背后也是同样的想法。在 Extreme Programming Explained(第 1 版)中,Kent Beck 认为最小化修改的代价是极限编程的一个目标,水平化的修改代价曲线是“XP 的技术前提”:
- 在某些情况下,随着时间的流逝而导致的指数级的修改代价可以水平化。如果我们能将代价曲线水平化,那么关于开发软件的最佳方式的旧假设就站不住脚了。
- 你可以在过程的后期做出重大的决策,推迟决策的代价,从而尽可能确保决策的正确性。你只需要实现需要实现的东西,你可以引入能够简化现有代码并使得后续编码变得更简单的设计元素。
重要的是你要知道 Beck 并没有说 XP 会将代价曲线水平化,他的意思是如果团队向着这个方向努力,那么是可以将修改代价曲线变成水平的。
反馈的重要性
Scott Amber 认为在敏捷开发中代价曲线是可以水平化的,不过这并非因为简单设计,而是因为对于迭代式、增量开发很重要的反馈循环。敏捷方法优化了团队中的反馈,开发者与客户坐在一起进行持续的面对面沟通。诸如测试先行的开发、结对编程与持续集成等技术实践使得这些反馈变得更加紧密。
不过,真正重要的是从使用系统的用户当中获得反馈信息,只有这样你才能确定自己是否是正确的,是否遗漏了某些东西。设计、构建以及从真正的用户获得反馈的时间越久,将软件交付给用户所需的时间和工作量就会越多,变更的成本也会越高。
变更的真正代价
变更的代价真的是指数级么,还是水平化的。答案其实是介于二者之间的一个状态。
时至今日,软件变更的代价肯定不如 30 年前那么高了。我们现在可以做得更好,使用更好的工具、更好的开发方式。降低变更成本的关键因素有下面几点:
- 尽快将软件交付给客户使用。我不相信有哪个组织每天会对软件做 10 次、50 次,甚至是 100 次变更,不过你肯定也不想等待几个月,甚至是几年才收到用户的反馈吧。少量交付,频繁交付。
- 我们知道即便事先做了周密的规划和设计也无法确保一切都是正确无误的。请在理解需求和设计上花上足够的时间,这样可以确保我们是基本正确的,能够在后面帮助我们节省大量的时间。
- 无论是采用迭代、增量的开发模式还是顺序开发模式,不管是通过测试先行的开发与结对,还是需求讲座和代码审查,只要有可能就提早找出错误,这样会降低后期的修改成本。
评论