2008年1月2日星期三

软件开发方法浅谈(一)

很久没用中文写文章了,这篇就用中文吧。

做事情要有方法论指导,否则就是瞎做,乱做。在软件行业,有着别其他行业更多的方法论。在过去的几年中,我接触了一些,实践了一些,对各种软件开发方法有了一定的了解。正值岁末,我就来简单地整理一下,首先说说软件开发过程。

首先了解一下概念,一个软件的开发要经过的一系列的环节,一般的开发主要包括分析,设计,编码,测试和发布(或部署)这几个环节,在这个行业的人都知道。但是如何区分这几个环节呢?这几个环节每个环节的输入是什么?输出是什么?

为了回答这些问题,人们开始制定一些标准或准则,用来规定各个环节的工作以及产出。毕竟,一个软件的开发是为了赚钱,如果没有产出,如何赚钱呢?这种标准就是软件工程中说的软件开发过程。也有人称之为软件生民周期。但是这两个概念还是有所不同。前者着重一个东西从无到有的过程,后者着重时间的发展。但我这里还是把两个概念并成一个,主要介绍过程,因为过程也包括了时间的发展。

很显然的,这个过程设计的好坏会直接影响到东西的质量,更会影响到这个东西能带来的利益好坏。因此,很早以前,国外很多公司就成立了QA部门,定义一些自己的过程来确保质量。有一些过程名声显赫,最终成为了一个时代的标准。

1. 瀑布模型(Waterfall Model)

这个名字软件行业的人耳熟能详,但现在已经成为了贬义词。如果你公司使用瀑布模型,估计会遭人白眼。为什么,因为使用瀑布模型而失败的项目不计其数。但是,要知道,这是第一个把软件生命周期明确定义出来的模型,现在的很多开发过程,只不过是把这几个阶段拆分,打散,拉长,缩短来适应需求而已。再把眼睛往后看30年,那个时候的软件远远没有这么复杂,需求简单而明确,因此瀑布模型还是很适合的。但是,现在的世界发展太快,人类的知识面和想像力都无限膨胀,对软件开发商的要求越来越多了,很好,这才是真正的产业。因此瀑布模型的缺点就出来了---简单的说,就是不能应付需求变更,或者更准确地说,应付需求变更的成本太大。瀑布模型中要求需求全部弄清楚之后才开始设计和开发,但是现在的软件大多数规模庞大,跨地域工作又提高了沟通成本,导致需求很难在一开始就全部弄清楚,但是时间不等人啊,根据瀑布模型就开始工作,到了后期,需求变更对于已经设计差不多完成的软件来说无疑是个灾难。很自然的,人们开始想到螺旋模型。

2. 螺旋模型(Spiral Model)
这个模型很简单,就是把一个大的瀑布模型拆分成多个小的瀑布模型。这很符合需求导向的软件开发实际情况。比如一开始掌握了20%左右的关键需求就开始了第一个瀑布模型,完成这个阶段之后再开始后面的20%或者30%需求。很明显,这样提高了质量,减少了需求变更的成本。而且在每个阶段也不需要投入非常多的人力了。试想一下,原本三个月做100%需求可能需要6个人,现在1个月做20%的需求可能只要1个人了。这是多大的节省啊。老板们开始期待软件项目的成功了。可是,他们很无奈的发现,螺旋模型也有缺点--每个周期结束没有明确的输出,这可能导致后面的周期无法正常开始,最后的集成往往产生很大问题。往往螺旋模型一开始很顺利,到后面越来越难转下去,就想一个陀螺一样。我一开始就说过,开发过程是一些准则和标准。因此,人们决定要把螺旋模型改造一下,定义其开始标志和结束标志(输入和输出)。于是,迭代模型产生了。

3. 迭代模型(Iteration Model)
迭代模型是一个很有意义的进步,他每个阶段的设计都非常灵活。通常来说,每个公司都有自己的迭代模型,但是有一点不会变,就是迭代模型明确规定了各个阶段的开始标志,输入条件,输出内容和结束标志。当然,其中最重要的还是输入的内容和结束标志。每个阶段的结束都称为Milestone。迭代是很灵活的,对于小规模的开发,迭代是线性的,也就是一个迭代完成再进入下一个迭代。而对于大规模开发,可能就是并行的。各个子系统并行迭代,每个子系统内部再进行线性迭代。




然后每个迭代也不能就这么叫迭代了。对于一个软件项目,总归会有需求分析阶段,设计阶段,开发阶段,验证阶段和发布阶段。这些阶段都不是纯粹的做单一的工作,比如需求分析阶段,不是单纯的做需求分析,也有一些少量的开发,同时一些测试用例也开始设计起来。但是这个阶段主要还是做需求分析,因此就叫做需求分析阶段。类似的,开发阶段的主要工作还是开发,但是也有一定量的需求分析工作。简单的说,就是谁占主导地位,就叫谁的名。对于阶段的名称,每个公司都不同,每种开发过程也都不同,不用去特别的记忆,因为背后做的事情就是这些。但是对于大的项目,往往每个大阶段里面还有小的迭代。比如一个需求分析阶段就会有1~2个迭代,开发有2~3个迭代等等。这要根据实际情况来。

那么每个迭代干什么事情呢?其实每个迭代也犹如一个小的软件生命周期,基本上都包括了需求分析,开发,测试等阶段。但是每个阶段时间很短。因为实践证明,一个迭代不要超过4~6周,因此在开发阶段往往是2~3天分析这个迭代要做的事情,1~2周进行开发,1周进行测试,然后几天进行发布。但是再需求分析阶段,需求才是最重要的事情。因此在该阶段的迭代的特征是需求往往占据80%以上的迭代时间,剩下的是一些原型开发,不带测试和发布的迭代。

迭代的内容和内部时间比例是灵活的。但是输出却是固定的。在设计迭代的时候就已经定义好,每个迭代的输出是什么。这个标准在很多公司被称为迭代的退出条件(Exit Criteria)。达到这个条件,迭代就可以退出,向下面一个前进。比如在需求阶段,第一个迭代做了20%的需求分析,这些需求就是要在后面一个迭代进行开发的内容,因此这个迭代的输出就是需求分析文档和这部分的设计文档。需求文档需要非常详细,每个测试人员和开发人员要清楚的知道自己那部分的需求是什么。设计文档中软件规格说明书一般由PM编写,不涉及具体的技术细节,是用户需求到软件需求的一个转化。这部分也需要很详细。设计文档还包括SE编写的软件设计文档(系统架构,数据库设计,接口设计,类图,事件流程等),但是可以是一个初步的第一版的设计。如在开发阶段,那每个迭代的主要输出就是程序了。

刚接触迭代开发的人会觉得很简单,但是真正做了之后就发现根本无法估量后面的工作量。甚至后面的几个Milestone都无法确定时间,这真是件头疼的事情。事实上,这却是很难。在现实生活中,有这几种情况。一、项目是时间点驱动的。比如某某时间会开一个软件大会,某某时间是娱乐,游戏软件的黄金上市时间,某某时间是行业大会等等。这种情况下,时间就是确定的了。所要做的就是把这些时间里面能够完成的功能做出来。二、项目是有固定截至时间的,无论是合同规定还是成本要求都使这种情况最普遍。这种情况下面,首先把几个大的阶段分出来。只要粗略地分一下即可。但是对于需求分析阶段,却需要仔细的分配时间。因为往往需求阶段只有一个迭代。后面就直接进入设计阶段了。因为需求分析的这个迭代和设计阶段的第一个迭代需要在一开始就定义清楚退出条件的。这个阶段的需求包括系统总体的需求和一部分地层的,关键的需求。因此需要对所有的需求分优先级,然后完成一部分最高的。估算迭代的具体方法会在后续文章中详细介绍,这里就说一个宗旨,估算迭代只要估算清楚当前的和后面的一到两个即可。

有些公司在迭代模型的基础上,详细的定义了每个阶段的输出,并且附带实行的方法,可称之为一套完整的方法论,其代表就是RUP(Rational统一过程)和MSF(微软解决方案框架)。RUP把原先上面我说的一维阶段--需求,设计,开发等变成了两维的--时间和内容。时间分为初始、细化、构造和交付;内容则用工作流定义分为建模、需求、设计、实现、测试和部署这几个核心工作流和配置管理、变更管理、项目管理和环境这几个支持工作流。每个时间阶段里面都有一到多个迭代,每个迭代中都有不同的工作流,每个工作流的制品输出也不同。每个工作在不同时间的不同迭代里面占的比重不同。看下其概念图,很容易理解。


MSF的体系很复杂,包含了开发过程,团队合作,技术体系等一系列内容。这里不考虑其他的东西,仅仅考虑其开发过程。MS的开发过程分为planning, initialization,implementation,stabulization和release这几个阶段。其实这样的分法更科学。第一个是计划(planning)而不是需求更表明了他们在迭代开发时候的灵活性。这两套体系都是他们根据各自的多年经验积累而成的,但是选择使用却要符合自己公司的现状,不能照搬照套。

4. 敏捷开发(Agile)
敏捷开发严格来说不是一种开发模型,也不是一种严格的生命周期模型。我更倾向于称它为一种理念。敏捷开发门派众多,我所知,所用也是有限,因此就拣这些我接触过的来整理比较好。说它是理念,因为敏捷开发实际上仍然逃不出需求,设计,开发,测试和发布这几个基本元素。它只是把这些元素的具体实践方法做了一些改动,使其适应性更强,灵活性更高,交互性更好,时效性更强。比如XP(eXtremeProgramming),有12种实践方法用来提高各个阶段的输出质量。它提倡的是快速开发,做出可交付的产品,交由客户使用,获得反馈,然后继续下一轮迭代。但是注意,它不是随便做做,我们以前做原型都是报着可作可不坐的心态,但是XP提倡的是“可交付的产品”,这句话保证了其质量品级。XP提倡TDD(Test Driven Development)测试驱动开发也是一个非常有用的实践。通过写测试用例,程序员很清楚这个功能的需求是什么,要达到什么目标才算通过,有目标的行为,当然效率要高些。Scrum有15min standing meeting,提倡开会少而精,每天跟踪进度,让每个人清楚三件事情:昨天已经做好什么,今天要做什么,现在有什么问题!

敏捷开发现在正在慢慢被人接受,别人认可。但是在真正的应用上,我个人认为还是应该先练习“楷书”--传统过程,再学习“草书”--敏捷开发。这样才能以不变应万变,特别是对年轻的没有经验的团队。君不见发明Agile的都是那些大胡子秃顶的老头么?他们的经验何其丰富,草书再草也不会失去控制变成涂鸦。


总结一下,软件开发方法很多,但是经典的就这么几种。重要的不是方法本身,而是知道在什么时候使用什么方法。比如自己做个习作,就一两个月的时间,需求明确,那用瀑布模型是最省力省心的。总之两句话: Do right things! Do things right!

没有评论: