软件交付的演进历程

编者按:本文来自微信公众号“InfoQ”(ID:infoqchina),作者Rory Madden,译者方彦,。
经常有人会问我什么是敏捷流程。我都会给出那个让人不尽满意的答案“没有一个单独的流程。它取决于每个团队的实际情况”。
为了更好的回答这个问题,我撰写该文介绍了软件交付的演进历史。我打算归纳成一个线性的发展,即使我知道它并不像我要表达的那样有序和线性。但我觉得参考它,能得到比前面那个“取决于”的答案更多的信息。希望它对你同样有用。

开始阶段
软件开发刚开始的时候,并没有很好的经验或思想来指导一个开发项目的运行。最开始,人们标识出软件开发的一些关键假设,映射到那时已有的可理解的流程上。
最初的假设如下:

软件开发需要很长的时间
软件发布不会频繁
软件构建后很难进行更改,所以确保第一次把事情做对
软件开发需要很多不同的、成本高昂的技能集

建筑行业也有着类似的假设。建筑需要很长的时间,竣工后不能简单的添加一层或把面积扩大。建筑也涉及到很多不同的专业,从设计师到开发商,到质量监理以及工人、电工和水暖工等等。从这些角色的命名可以看出,软件开发从建筑行业借鉴了很多。
建筑行业遵循的流程是,把端到端的项目分成不同的阶段,每个流程阶段由不同的专业人士来负责。这种在每个阶段赋予角色的做法有利于充分利用成本高昂的人力资源。

瀑布流程
这看起来是一个很棒的流程。瀑布模型在 20 世纪 60 年代后期开始采用,直到 80 年代中期它才成为事实上的软件交付标准。但在流程执行中出现了些问题。根据 2014 问题报告,31% 的瀑布项目在投入很多后被取消,更有 52% 的项目预算需要翻倍。
鉴于这种很低的成功概率,很多人开始各自提出新的、更好的方式来交付项目,以克服瀑布流程中的一些缺陷。
敏捷开发
人们不希望看到自己的工作被废弃掉,因此最初的一个思想是把大型项目分解成小的部分,逐步迭代出解决方案。这种方法让人们能对产品随时间的进展有更直观的印象,让团队可以收集反馈来看产品是否已经解决用户的问题。这种早期的反馈让团队按需进行纠正。
但是从瀑布模型转型到迭代交付很难,很多组织就把迭代开发解释成随时间增量交付解决方案。敏捷这个术语很灵活,按照设计,并没有什么敏捷流程——其关注点在于小型迭代、持续学习和反应性。尽管流程很容易遵守和实现,不过这些软技能很难掌握。对流程阐述不够,会让人们绕开一些比较困难的变革,实现“对他们有效”的敏捷流程,并起一个引人注目的名字,如 Wagile 或 WaterScrumFall。

敏捷开发
更好的透明度限制了出现严重超限的风险,但是它没有解决导致瀑布项目高失败率的根本问题。仍然有项目会花费比预期长的时间来进行构建,有些项目会因为不能交付预期价值的产品被取消。
为了实现到迭代交付的飞跃,我们需要改变对软件交付的假设。我们要承认,我们前期不知道要构建的产品是什么样的,因此我们需要将预先大量设计(Big Design Up Front,BDUF)阶段替换成增量设计。
这样可以让团队有能力在项目开展过程中进行学习,并在需要的时候改变设计。这里的挑战是,设计阶段是保证项目团队内外进行协调的关键阶段,并汇总实现解决方案所需的各种时间估计。一个公司的各个流程不是孤立的,所以要改变一个流程,就会影响另外一个看起来好像没有关联的流程。比如,从 BDUF 中得到的估计,会被其他支撑流程所需要,如资金、监管、资源分配和环境分配等等。
采用这些“对我们有效的敏捷”中的问题是,没有认识到或解决我们对软件交付做出的假设和现有情况的冲突。
假设

软件开发需要很长的时间
软件发布不会频繁
软件构建后很难进行更改,所以确保第一次把事情做对
前期不可能确切知道要构建成什么样的产品,因此把大型开发分解为小部分,并在项目进行中不断学习
软件开发需要很多不同的、成本高昂的技能集

如果前期并不能确切知道要构建怎样的产品,我们怎么才能做到一次把事情做对呢?软件的大设计和最终产品经常有很大的出入——这就产生了不能预期的挑战,即要求设计根据不断出现的新需求进行调整。这说明,和建筑行业不一样,软件的变更在构建后并不困难,不需要像实体建筑那样前期做缜密的设计。我们可以简单的添加(软件)层数,改变层高或是扩大面积,而不需要推倒重来。因此,假设 2 实际是不正确的。
(真正的)敏捷开发
如果设计可以随着迭代过程中的学习进行更改,那么只做每次迭代所需的设计就会有利于减少可能的返工。

这其实是最难的一步,因为它不仅要求改变项目团队中的一些职能部门的工作方式,还包括支持部门工作方式的改变。

我们没有足够的架构师,无法为每个团队都配备一个,指导他们进行持续的架构选择。架构师们需要定义好实践、原则和强制措施,确保设计符合指定的约束条件,而不是定义一个固定的架构。
开发工程师们将被赋予更多的责任。他们要完成针对问题给出最佳解决方案的任务,而不仅仅是按照需求规格说明书进行软件构建。架构师们不再面对交付的挑战,因此他们的假设经常不正确。最前线的开发人员在面临挑战时往往能提出更好的解决方案。
不进行预先的大量设计,就很难预估时间和成本。在瀑布项目里,时间和成本是基于项目启动时的估计确定的。在增量开发中,项目范围会根据实际遇到的新情况进行调整。时间和成本估计仍可以根据对交付的大致理解和团队规模进行,不过因为项目范围会有变化,投资回报率(ROI)和价值实现进度(benefits realisation schedule)无法在前期给出。

这些不是能轻松解决的任务,不过还是可以解决的。我会在后续的文章中详细谈到如何解决这些困难。
现在,我们再更新下我们的假设。
假设:

软件开发需要很长的时间
软件发布不会频繁
前期不可能确切知道要构建成什么样的产品,因此把大型开发分解为小部分,并在项目进行中不断学习
软件开发需要很多不同的、成本高昂的技能集
实现团队负责在一定的边界条件下进行设计

持续集成
迭代交付的好处很大程度上是因为它可以获得关于产品的早期反馈。为了获取这些反馈,需要有一个软件的工作版本,解决了客户的问题,能够进行演示,并获得实际的反馈。为了交付这样一个软件版本,主要有两个挑战需要克服——软件开发怎样进行优先排序和怎样进行测试。
传统的瀑布项目中,最有效的方法是按组件构建产品——构建完美的轮胎、完美的底盘,最后组装到汽车上。上下文切换会耗费时间,因此,切换越少就可以越高效地利用开发时间。这种组件开发方式在开发团队中根深蒂固,即使他们采用了敏捷开发,实际的构建方式仍相同。问题是,如果客户想从 A 点到 B 地点,而我们给客户展示的是一个完成了的车轮,客户没法给出任何有价值的反馈。这解决不了他们的问题。我们需要从基于组件的开发转换到迭代开发方式,这要求有一个思想上的转换,即关注于客户问题而不是解决方案。只有不再做预先的大量设计,并承认前期我们并不很清楚需要构建的是什么,这种转变才可能实现。但即使如此,团队仍需要培训,因为它会影响到需求文档的编写和开发的进行。

价值增量 (Courtesy of Henrik Kniberg)
开发人员的时间是软件开发中一项很高的成本,产品定义改变是否值得呢?除了 31% 的失败率,微软的分析指出,高达 66% 的功能没有实现预定的商业价值。考虑到失败率,确保我们是否做对了事情远比开发效率更重要。我们会很快回到这一点,因为它即将影响到我们的下一个假设。
第二个挑战是关于测试的。为了得到有价值的反馈,我们需要让软件在客户面前工作起来,而不仅只作为演示。但是这需要测试,要花费很多时间和努力来完成的一项工作。过去,只在每次大的发布上执行一次测试,则自动化测试用例并不划算。
但是有两件事改变了测试的这种情况。第一,现在的软件为商业的各个环节所需要,过去那种一年花很多天进行一次发布的情况已经不见了。第二,和开发人员的时间一样,项目中最大的浪费就是开发了错误的东西,而自动化测试让我们可以更频繁的测试客户的想法,它带来的益处超过了其成本。自动化测试周期让团队在整个开发过程中,可以持续开发“可发布”的代码。100% 的自动化测试是个很难达到的目标,因此在软件发布前还有会小量的手动验收测试,但其质量已经足够验证解决方案。
瀑布流程中,保证不同团队高效是一个很关键的假设,这样才能降低成本。但是对于软件,因为软件发布频率增大,效率的经济性也随之发生了改变。现在的重点是保证端到端流程的有效性,而不再是保证每个职能部门的高效。这对软件来说并不新鲜——这种方法和技术是直接从精益生产运动中借鉴过来的。
持续交付 / 部署 (DevOps)
持续集成的好处在于代码在任何阶段都是可供部署的。这样即使项目即将被叫停,我们也

企鹅电竞:6ZIZ ;企鹅号:闫亚鹏 ;微信公众号:1.天游玩 2.Nana电影;百家号:6ZIZ

THE END
分享