工程开发的本质与瀑布模型
自然界的系统大致可以分为两种主要的类型,一种是自然形成的,一种是人工制造的。我们在这里只关注人工制造的系统。因为其涉及到工程开发,所以,可以将其称为:工程系统(Engineering System)。工程系统实现的过程就是工程开发的过程。
所有的工程开发,起点都始于需求。无论是一部手机,还是一架飞机,甚至是一栋建筑,它们被开发出来的目的都是为了满足某种需求。因为,如果这些系统不能满足某种特定的需求,就不会有人去花费时间、金钱和体力去实现它。
当需求基本确定了之后,接下来要做的就是进行设计。此时需要做的是确定这个系统使用在什么样的环境内,有哪些主要的组成部分(组件),它们之间是怎么连接(结构)的,需要满足哪些标准(原则)等。这个相当于系统架构的设计,或者是系统的详细设计。如果系统复杂到需要多个人参与设计,那么架构设计就是必不可少的。负责设计架构的人把系统分为多个子系统,并规定好每个子系统的边界和接口等一系列要求,再由相应的人进行更详细的设计。
设计完成之后,就是开始实现了。这个时候,施工队入场了,不同的人负责不同的工作。对于电子产品来说,要有软件、硬件工程师。对于建筑来说,需要泥瓦工、水电、油漆等工种。不论产品如何,这个阶段大家都是按照上面的设计来进行实现。
施工完成后,需要做的是验收。不管产品是哪一种,验收都可以分为两类:验证(Verification)和确认(Validation)。验证活动检查的是产品是不是按照设计实现了,确认检查的是产品是不是确实是用户想要的。对于建筑物来说,设计的时候是10层楼,结果盖成了9层楼,那么就是不合格的,因为不符合设计。可是如果设计的时候就注明了每层楼高2米,而客户需要的是3米的层高,那么即使验证合格了,确认环节也不合格。
在验收结束后,产品就可以交付给用户使用了。在一段时间内,产品的提供方还需要持续的对产品进行维护,产品出了问题时,产品的提供方就需要及时给解决。这个过程相当于售后的质保。
以上的过程就可以采用瀑布模型(Waterfall Model)进行表示。
瀑布模型的发展经历了几个阶段,1956年在一篇关于软件开发的论文中首次提到。在接下来的几十年里,它被不断完善,最后被美国国防部采用,作为承包商需要遵循的标准。瀑布模型描述了一种按照一定顺序处理开发过程步骤的方法。
瀑布模型中,所有的工作都是顺序的,是一层层流下来的,像瀑布的水流一样,是单向的。纯粹的瀑布模型的本质是,在进入下一个步骤之前,必须完全完成本步骤的所有任务。看起来逻辑很通顺,但实际应用的时候却可能会遇到很多问题。因为,需求(Requirement)可能不全或有错误,设计(Design)的过程中可能会出错,实现(Implementation)也可能会出错,从而导致理想的瀑布模型会不适用于很多复杂的场景。如果完全按照这种模式开发,就可能出现不断重启所有环节的情况。
实际的开发过程中,往往很少完全按照瀑布模型开展,产品一般都要经历多次迭代。我们所熟悉的水果手机也不是在一出现就这么NB的,而是从1,2,3,4……一代代发展而来的。
从上面的讨论我们可以看出,所有的工程开发都是从需求开始的,要经历需求-设计-实现-验证-维护的阶段。瀑布模型反映的就是这个本质。
敏捷开发
开发背景下的敏捷(Agile)一词最早出现在2001年的犹他州的雪鸟会议上。在这场传奇性的会议上,一些软件人士聚集在一起,讨论软件编程的革命性方法。虽然那时极限编程(与Scrum相当相似)已经建立,但许多人仍然对沉重的软件开发过程和非常长的开发时间感到沮丧。复杂的系统如航天飞机的开发时间超过了20年。
犹他州的那些人创造了敏捷宣言 [ https://agilemanifesto.org/],描述了敏捷开发的主要原则,但其根源可以追溯到20世纪60年代人们开始尝试快速开发之时。Scrum这种最流行的敏捷方法之一,也是在1995年初开发的。
《敏捷宣言》描述了12条原则,如下:
- 客户的满意是最优先的。
- 在整个开发周期中,需求可以被改变。
- 在较短的周期内频繁地交付工作软件。
- 开发人员和业务人员需要有很好的联系。
- 能够对开发人员产生信任和激励的支持性环境是关键。
- 自组织的团队是高质量的关键。
- 团队本身定期反思改进自己。
- 面对面的会议和同地办公始终是首选。
- 可以工作的软件是衡量成功的主要标准。
- 卓越的技术和强大的设计是持续关注的焦点。
- 简洁性是必不可少的。
- 可持续发展和持续的步伐是敏捷的本质。
敏捷是项目管理和开发过程的混合物。Scrum以及Kanban可以被认为是纯粹的项目管理方法。其他的敏捷方法,如测试驱动开发、结对编程和持续集成,则是在软件开发或是质量保证方面。
敏捷开发中,与软件有关的和与人有关的主题被很好的整合了。这就是敏捷的关键因素之一:工程师和他们的合作是成功的关键。对于那些习惯于以孤立的方式工作而不合作的人来说,他们无法通过Scrum这样的项目管理方式来管理。
敏捷开发方法的主要特点是通过小型团队的合作来实现快速迭代。但仍然遵循着需求、设计、实现、验证的流程,这一点与瀑布式并无不同。与瀑布式开发不同的是,它的每一轮迭代的周期要小得多,通常以周为单位。它们的创建是为了快速交付并从用户或利益相关者那里获得早期反馈。这样做的好处是,产品能更快地到最终用户手中,而且反馈也能更快地回到开发团队中。团队致力于根据反馈和优先级迅速调整方向,所以上述所有问题都通过短的反馈周期和透明度来解决。最后,团队致力于持续改进。每个冲刺结束时都有一个回顾会,每个人都有机会发言,讨论下一轮可能进行的改进。
敏捷还是瀑布?
究竟应该采用哪种开发方式?这个问题就像一个人问:应该吃蔬菜还是肉呢?如果笼统的回答,就只能是:看情况了。
不同的公司、不同的项目有不同的特点和要求,无法一概而论。简单而言,敏捷更适合那种需要不断快速试错的项目,而且对团队能力的要求很高。当需求不清楚或实现方案不清楚的时候,采用敏捷方式可以快速交付原型产品,得到客户的反馈,并能够让团队聚焦在高优先级的任务上,从而提升交付效率。
然而,对于那些需求清晰、团队规模大的项目,敏捷则并不一定能够发挥很好的作用。这种情况下,如果有很好的架构设计,每个模块或子系统的接口、边界和需求都清晰的时候,每个子团队完全可以按部就班的开展工作,每个人都有明确的职责和角色,也无需每两周就交付一个版本,只需要按照既定的里程碑工作即可。此时,传统的类似瀑布式的开发可能更为合适。尤其是在那些增量型的项目中:很多人在一个平台上修修补补,只要大家能够各司其职,有人在统一管理也就没有问题了。
敏捷在很大程度上还涉及团队精神、团队授权和合作。如果一个团队中的氛围不好,也没有得到充分授权,那么采用敏捷也无法提升效率。另外,假如每个工程师都需要同时负责多个项目的事情,敏捷也没有办法开展起来。
在有些人的眼中,瀑布就代表着落后,敏捷就代表着先进,这个未免有失偏颇。如同青菜与肉、跑车与拖拉机一样,没有好坏,只有适合与否。而且,我还从没有看到过那个项目是完全按照瀑布式开发的。所有的项目都是按照计划在最终版发布前有多个过程版本发布的,这也就是说,实际工程开发中也是按照敏捷的思想在开展的,只不过形式不同,迭代的周期不同而已。
当你的软件项目有几十个开发人员,产品规模远大于一个团队所能开发的规模,而且还需要快速地进行交付,那该怎么办?业界已经定义了一些方法来将Scrum扩展到更大的软件产品。扩展的Scrum方法包括Nexus、LeSS(Large Scale Scrum)和SAFe®(Scaled Agile Framework)。基本的思想是:小的开发团队向更高层次的团队交付,以此类推,直到完整的产品完成。可能需要一些新的规则、工件、团队和会议。
在古老的汽车行业,虽然软件越来越重要,但软件不是汽车中的唯一组件,软件还需要与硬件和机械相结合才能有用武之地,软件的开发也要匹配整车开发的时间线和SOP节点的要求。
总结
1. 开发的本质都是要从需求开始,经历需求-设计-实现-验证-维护的阶段。只不过不同的项目或不同的组织选择了不同的迭代周期和开发方式。不同复杂度的产品经历的迭代轮次不同,开发周期也不同,但目的都是相同的:满足需求,交付系统!
2. 如果从大的时间尺度来看,所有被持续更新的工程系统都是逐渐增长起来的,这与敏捷的思想很接近。产品都是从简单到复杂的,功能是逐渐增长的,大楼也是一层的盖起来的,汽车在刚刚出现的时候与现在所看到的完全不同,Windows操作系统也是逐渐演进的,控制器的软件也是演进而来的。
3. Kanban和Sprint等都是一种工具或方法,而工具和方法都必然有自己的适用范围,在不同的情况下,要灵活使用,没有万能的工具。
4. 选择敏捷还是瀑布,需要考虑的点很多,至少包括:团队规模,项目规模,开发需求是否明确,人员能力,人员稳定性,团队氛围,项目是否需要持续维护等。
5. 当需求明确,技术方案也明确,也就是比较简单的时候,使用瀑布。当需求不明确或技术方案不明确,使用敏捷。
6. 敏捷的好处是减少试错成本,快速交付,不断优化开发过程(资源、能力、流程等)。
7. 敏捷也是一种流程,而非没有流程。
8. 敏捷与瀑布并非对立的,如同青菜与肉一样,两者的适度结合才能有更好地产出。敏捷是一种思想和意识,而非教条。
最后,想说的两点是:
1.如果你的项目不是一锤子买卖,也就是还需要不断迭代升级和维护,那么还是老老实实写好文档。这与敏捷还是瀑布无关,因为你的团队不可能没有人员变动,人员也不可能永远都清楚地记得自己几年前做了什么。
2.看清事物本质就不会迷茫,盲目的采用敏捷并不能保证效率一定高。瀑布还是敏捷,本质上都是一种方式,灵活的在不同的时期采用不同的方式才是明智之举。固执的认为某种方式可以普适于所有情况,就是守株待兔、刻舟求剑、枉曲直凑!