相关文档
软件开发过程中的质量保证(4)
据我所知,FreeBSD的软件开发过程极大地得益于多头并进的开发模式。下面简单地介绍一下FreeBSD所采用的软件开发模式:
案例:FreeBSD开发模式中对于多头并进的应用
FreeBSD包括了两个主要的开发分支:4-STABLE和5-CURRENT,以及若干安全分支。其中,4-STABLE(RELENG_4分支)代表的是FreeBSD 4.x系列的开发,其关注的焦点是系统的稳定性和性能;5-CURRENT(HEAD分支)代表的是FreeBSD 5.x系列的开发,它关注的焦点是尽可能多地引入最新的操作系统特性,全新的设计思想,等等。除此之外,还有一些被称作安全分支的分支,它们分别代表FreeBSD 2-STABLE, 3-STABLE, 4.6-RELEASE, 4.7-RELEASE, 4.8-RELEASE以及即将推出的4.9-RELEASE等等,但这些分支完全不引入任何新的特性,只有安全更新能够被加入到这些分支中。
FreeBSD的“安全分支”是一个非常重要的概念,在FreeBSD的开发中,这些分支基本上只由一个包括了少量开发者(目前只有两人)的,被称为“FreeBSD安全官”的团队维护。对于很多用户来说,他们并不在乎操作系统是否拥有新的特性——他们不愿意尝试新版本的软件,因为现有的系统工作的非常好。这些用户使用“安全分支”的FreeBSD操作系统,因为他能够提供必要的安全更新,而操作系统特性并不会因此发生变化(无论这种变化是否能够改进性能,或提供一些眩目的功能,甚至支持新的硬件,因为用户的系统已经放在那里了)。
CURRENT分支走的是另外一个极端。所有的新特性,一旦被特定的工作人员(committer)测试通过(大的变化需要核心团队,即core team的批准,但这种情况并不是很多),就允许被引入CURRENT分支。尽管CURRENT分支在绝大多数时间都能够被正确地编译,但引入新特性有时会不可避免地带来一些问题,例如硬件适应性问题。
在这两个极端之间,有一条中间路线,即STABLE分支。在CURRENT分支中提交的代码通常会被指定一个MFC(Merge from -CURRENT)时间,在这个时间之后,如果没有人提交关于代码的问题,则这些代码会被引入STABLE分支。
这样,STABLE分支的代码几乎都是经过相当长时间测试的代码,对于大多数用户来说,STABLE分支是一个很好的选择。
一般来说,FreeBSD中的代码会经历下面的历程:
代码被引入CURRENT分支
相关开发者获得来自用户的反馈; 在确认基本没有问题的情况下,代码被引入STABLE分支
大多数最终用户使用STABLE分支的代码来支持他们的计算机
我们可以看到,上面的开发模式同时照顾到了开发者和用户群体的利益。一方面,活跃的开发不会因为影响到了大量的普通用户而遭到指责;另一方面,在开发分支(CURRENT)的代码经过一段时间被引入STABLE,最终用户能够得到那些新的操作系统功能。
事实上,上述开发模式已经被证明是相当成功的。由于开发过程中每一天都有相当多的人对新的CURRENT和STABLE分支的代码进行测试,因此,在最近的几年中,FreeBSD的开发一直呈现着良好的态势。
交付工程(Release Engineering)基础——特性冻结和代码冻结
许多参与过大型项目开发的读者可能都经历,至少是听说过特性冻结和代码冻结这样一个概念。所谓“特性冻结”实际上是一个开发者之间的约定,在这个阶段中,不再允许添加新的功能。
特性冻结(Feature Freeze)通常在一个开发分支(Development Branch)跃变为交付分支(Release Branch)的时候开始。之所以需要特性冻结,是因为增加新的特性很有可能引入新的问题,而这将给代码复审带来沉重的负担,甚至导致一次不成功的最后交付。
当然,对于那些已经明确地定义了特性表的小型软件工程项目(例如,传统的瀑布开发模型)来说,特性冻结没有什么意义,因为在这些工程中,详细设计完全是在编写代码之前进行的,这意味着,代码将要写成什么样子已经在详细设计中明确地定义。但在实际的项目中,详细设计往往会包括两类不同的类型要求——一部分是“必须实现的特性(Must have feature)”,另一部份则是“希望实现的特性(Desired Feature)”。在交付之前,所有“希望实现的特性”都会在特性冻结时被明确成“实现特性”和“不实现特性”。
我们注意到,这种情况下,某些特性被延迟到接近交付的时候才被明确成“必须实现”,而另一些“希望实现的功能”则被作为“不实现”,从而转化为我们先前熟悉的样子,即详细设计文档中明确地定义了软件中的所有特性。
这样做的结果是软件工程项目具有更大的灵活性。由客户需求产生的功能设计,很显然地,应该列为“必须实现的特性”,而那些开发团队提出的能够提高软件整体可扩展性、可伸缩性或其他性能的特性,则应列为“希望实现的特性”。在特性冻结之后,整个开发团队将专注于那些“实现特性”(尽管这些特性可能还没有被正式的实现)更加稳定,从而将生产出更高质量的软件。
根据我个人的经验,特性冻结应该发生在预期编码时间已经用去大约2/3的时候。这时,项目经理应该组织开发人员举行一次会议讨论特性冻结,而在特性冻结之后,在软件正式交付之前,任何开发人员都不应该再去考虑那些被列为“不实现特性”的功能。
代码冻结是一个与特性冻结类似的概念,在这个阶段,只允许对被冻结代码分支中的错误进行修正,而不允许任何其他的、涉及功能的修改。实践上,这个过程中,只有交付工程师(通常是一个或多个对于整个系统架构非常了解的、有丰富开发经验的代码复审员)被授予审查和批准代码提交的权力,任何代码修改,只要没有经过交付工程师的批准,就不能被提交到代码库中。
代码冻结的时间一般不需要太长。对于中等规模的项目,这一过程通常会持续一至两周,对于大型项目,这一过程则有可能持续一个月甚至更长的时间。在这个阶段,交付工程师主要负责代码复审,而测试工程师则有责任及时反馈集中的测试中暴露出的问题,并与相关的开发人员联系、解决这些问题。
技术上,代码冻结可以通过修改cvs中的配置来实现。不过,更好的办法是通过制度来保证代码冻结。
交付工程——编码阶段的总结
交付工程的好坏在某种意义上,是直接关系到用户利益的部分。前面已经说了相当多的关于软件开发过程中通过版本控制技术来提高开发效率的技巧和方法,这里我将继续说一说交付工程。
前面提到了每日构建中在代码上适当地打上版本标记,以及在划分版本分支时在切分点上增加版本标记,这些对于交付工程都具有非常重要的意义。交付工程,在软件工程项目中是一个融合了代码复审和集中测试的重要阶段。
交付工程的一般程序
在项目进行到某个特定的阶段,交付工程师同其他主要的项目管理者商议决定宣布代码冻结和交付工程开始。
交付工程师对代码进行集中的复审,而测试工程师则组织进行大规模的集中测试。
交付工程过程中,交付工程师每隔一段时间发布一个“交付候选版本(Release Candidate)”,测试工程师跟随安装并测试这些交付候选版本。
此间,测试工程师随时向交付工程师反馈问题,交付工程师将问题分类、整理,并约见相应的开发人员,予以解决。
最终,某个“交付候选版本”被最终指定为交付版本(Release)。代码冻结结束,软件被交付给客户。
一些读者可能已经注意到,交付工程的绝大多数任务事实上已经被融入了我前面所描述的开发过程——在编码阶段的整个过程中,代码复审、问题反馈和测试一直是持续地进行的,只是,在“交付工程”阶段,代码复审和测试被提升到了一个更为核心的地位,在这一阶段,开发的重要任务是查错和排错,而不再是将软件的功能推向一个崭新的水平。
总结——基于版本控制、每日构建的编码过程
前面我们已经介绍了通过引入版本控制系统改善软件工程中编码和测试阶段过程的一些方法。这些方法来自于我本人所参与的,以及通过一些其他途径了解到的实际项目的开发经验。文中介绍的内容以cvs (Concurrent Version System)为主,这是因为cvs比较容易得到(它本身是开放源代码软件),并且,比较成熟。另外,由于关于cvs本身的细节并没有涉及很深,因此,读者也很容易将这些经验套用在其他版本控制系统,如Bit Keeper, Perforce, Clear Case等等之上。
引入版本控制、每日构建之后,项目管理人员和开发者可以明显地感受到以下改善:
问题能够尽早暴露,并被解决。测试过程被渗透到开发过程中,有利于及早发现问题。日常的每日构建和测试意味着更多的测试者可以尽早地参加到测试工作中,并与开发团队并肩作战,及时地为他们提供第一手的资料;而最终的交付工程中进行的测试,只是验证软件的质量确实达到了设计要求,而不再肩负发现问题的重大责任,这意味着很难出现最后阶段发现严重问题而导致工期大大加长的尴尬局面。
每个人做了多少工作在版本控制系统中能够非常有效地体现,这对于更客观地评价一位开发者的能力,明确奖惩和提高员工积极性,都有非常积极的意义。
管理者能够随时观察工程的进度情况,并且,每日构建的到的版本也可以交付给客户,从而改善软件开发团队同客户之间的交流。
版本控制系统记录的软件工程的进展,对于今后的开发将是一笔宝贵的财富。
