例一,汽车生产。原材料、配件等采购完毕(我这里说到了采购配件,这相当于把部分功能的生产转交给其他职能公司。对应到软件生产的(子)项目外包。这个话题在本文就不扩展了),进入生产、组装、测试车间,进行一系列规定的工作流程。正常情况下,如果不发生不可抗拒的事件,那么可以按时完成合同规定的交付。这中间不会有什么变动性和不可预测性。
例二,再来看一个例子,比如某人想盖一栋房子,他想使用环保材料,当开发商给出房子的草图、价格预算,交给他时,他可能会改变主意。在建造房子的过程中,他的一些想法会逐渐明朗化。当房子盖好之后,实物呈现在他眼前时,原先他的那套装修想法也可能根据房子的实际样子来做调整,比如厨房的布局、主卧的装潢等。总的来说,事先的计划遇上了变化,站在“客户至上”的位置上,开发商业就要改变计划,满足客户的新需要。至于如何操作,那是合同谈判的事。客户改变想法是有理由的,因为原先那一套东西都是构筑在设计中的(纸质设计图,有的开发上会提供3D图形或动画),客户直到见到实物,才会有他进一步的,更明确的想法。
总的来说,软件生产的本质是具备创新性的新产品开发。
新产品开发有那些特征呢?
与创新性新产品开发对应的就是具备可预见性的制造。它可以有笨重的前期规格说明、估算、推测计划等。而新产品开发拒绝这些“可靠的”前期规格说明,理由是:
客户或者用户不可能明确知道他们到底要什么。(需要通过逐步的交流和引导让其明确起来)
1.近年来软件项目的一些统计数据以及一般性结论
正是因为软件开发不是循规蹈矩的可预见性的生产活动,而是具创新性的新产品开发活动,所以很多采用遵循可预见性产品生产方式的软件项目最终都以失败收场,不管是小企业还是知名企业。这是新产品开发肯定会有的情况,当然也有方法论的问题。
让我们来看一组软件开发领域的研究和统计数据,这些数据显示了近年来软件项目开发的基本情况:
图2.显示了软件项目开展过程中增加进来的变动性因素的情况。项目大小以功能点来衡量,在图中对应横坐标;纵坐标表示需求的变动,仍以功能点为单位。(Jones97Jones,C.1997.AppliedSoftwareMeasurement.McGrawHill)
图2.需求变更和项目大小之间的关系图
从这个图中我们可以看出需求变动无法规避,典型地,一个项目肯定要面对需求变更的情况,犹如前面的盖房例子。需求变更也影响到项目的成功率。(这里的成功依旧遵从前面的定义。)
图3.是需求管理中的要求实现的功能点在软件产品交付之后实际被使用情况的比率,这个比率非常惊人地表明几乎一半的功能甚至从为被使用过,相当多一部分功能也很少被使用。在竞争性产品市场上,这些功能点可能是卖点,从而也增加了项目的体积、复杂性,影响到项目的成功率,交付日期。非竞争性领域,对这些需求应该再考虑考虑:-)按20-80原则,20%的功能具备了产品的80%的重要内容)(Johnson02Johnson,J.2002.Keynotespeech,XP2002,Sardinia,Italy.)。另外,基于风险和客户驱动,可以最大化最常使用的功能。从而一个项目甚至在完成了其20%功能时,就可以成为一个较为有用的阶段性发布。
图3.产品中要求的功能点在实际中的使用情况
另外,有证据显示,随着功能点的增多,每个开发人员的生产效率下降,每个开发人员的错误率上升。(Jones00Jones,C.2000.SoftwareAssessments,Benchmarks,andBestPractices.Addison-Wesley)。此外有证据显示失败项目中很大一部分是采用瀑布模型的。
2.瀑布模型vs.迭代模型
应对变动性产生了截然相反的两种态度。
通过分阶段的确定输入、输出来规避变动性,先确认输入是固定不变的(经评审的),这样就可以设计产生想要的下一个输出。这就是所谓“推(Push)”方式,这种方式似乎规避了变动性,注意,我们先前的图2.说过即便是需求功能点变更也是常有的情况,所以对这种变动性的认识和响应实际上是被推迟到了项目的后期客户验收阶段。
另外一种态度就是积极响应这种变动性,项目开展的整个过程中都鼓励加入新的需求这种方式。
如果忽略许多争论不休的地方,大体上,试图规避或者说想一步到位获取需求的线性开发方式就是对应到“瀑布模型(WaterfallModel)”,而积极响应变化的通过多次反复的增量式过程就是“迭代模型(InterativeModel)”。有必要说明一点,瀑布模型的发明者本人说他是迭代模型的拥护着,它只是认为瀑布模型是软件开发中的最简单的一种模型。
我们来看一些图,直观地看一下这两种模型。
图4.瀑布模型及其高风险示图
随着越来越多的证据证明了瀑布模型的高风险和高失败率之后,瀑布模型自身也发生了一些变化,以致继续有人采用这种模型的变体来进行项目开发。正如我以前写过的一个文档,这个模型一般来说不适合于是软件开发上。
图5.瀑布模型的变动性的总体代价
这种模型的一个重要问题就是缺乏反馈。他是一种通过单向的控制来完成的,并且相信这种控制都正确的,比如从ANALYSIS-->DESIGN这个过程,根据分析的决议来做设计,并且相信这个ANALYSIS是正确的。这类似于行军打仗,每个上级都认为他的指令被正确的执行,这种指令的正确性暂且不谈(这涉及到每层的控制人员的专业素养),显然会出现将在外军令有所不受的情况,或者失之毫厘,谬以千里。它的控制流程是Push式的,一层层往下推,如图6.这里只截取了其中一个部分。
图6.Push模式中的一个片段
学过控制理论的人都知道一个最简单的道理,“没有反馈(feedback),就没有控制”。反馈的基本原理就是把输出反馈给输入,如果偏差很大,就得调整控制过程,最终使得输出满足输入的需求。总体上看,软件开发的输入是客户,输出是软件产品,控制过程是软件项目的开发过程。如果只是一次性地把软件产品交付给客户,显然就是没有反馈。其过程是线形的:“客户-->项目实施-->产品”这样一个过程,风险很大,所以应该与客户协作,多进行几此这样的过程,让整个开发过程自适应化,最终交付成功得产品。如图7.所示:
图7.有反馈的,自适应过程
图7.的过程,在项目开发过程中,就是多次的迭代。每个迭代过程都是具体而微的“需求-设计-实现-测试”单调过程。正是这样的多次迭代,降低了最终交付产品时的风险。
让我们看看迭代过程,下图:
图8.迭代过程示意图
每个迭代过程都是具体而微的“需求-设计-实现-测试”,通过这样多次的小步迭代,逐渐构筑成一个完整的系统。如图9.多次的迭代,系统增量式地完善起来。
图9.多次迭代,系统增量式完善起来
每次迭代,完成客户要求的优先级别高的风险大的功能点(对应到user-stories)。每次确定user-stories的时候都允许加入新的需求,一旦确定了下一个迭代过程要实现的user-stories列表之后,直到这个迭代过程结束,都不允许变动这个列表。顺便说一下,所有user-stories的列表就是最终功能测试和验收测试的依据。User-sotiry不同于user-case,简单说,可以将user-story看成是user-case的描述部分,便于编写。而细节则在每次迭代的迭代设计阶段细化规格,再简单地设计,刚够满足应用就行。复杂的设计会有很多问题哦,做集体项目,并不是让你表现代码技巧的时候。
图10.迭代过程中引入变化的总体成本走势
每次迭代开始都欢迎加入新的需求变化,这样,就逐步的减小了产品完成时候的风险,迭代模型对于变化的总体成本示意图如图10.所示。
另外:可以研究一下《敏捷迭代开发-管理者指南》上提到的如何签定两阶段合同的问题:如果我是甲方,我就会在第一阶段让准备竞标的各公司给出我的需求的一个原型(可以是草图的),最终中标的,对这部分工作也买单。至于合同方面的事,具体的操作由市场部方面研究研究如何操作:p)
总之,Waterfall-likeModel的实施,需要经验丰富的把关者,无论哪个阶段都是如此。(经验和不确定性的关系我们可以看图12。)比如需求分析阶段,获取需求的能力,分析需求的能力;设计阶段更是如此,甚至在整个项目成型之前,在这个设计师脑中就已经存在了一棵枝繁叶茂的项目树,无所不包,甚至包括了哪个枝干的哪个枝丫上果子的大小,颜色,成熟度以及一阵x方向的风吹来如何做运动等等细节。如果不是做过相同的项目,有具备这样精确设计的设计师,你告诉我,我立马去拜访求教。更何况技术普通的一个项目团对呢?!。导师斯大林说:制定了正确的政策,就要靠党的干部执行下去。且不说有个无所不能的领袖人物,还要有忠贞不二的业务水准高的众多干部。每下一个过程都不得有异议(异议是某种反馈)地执行。类瀑布模型就是这套体制,似乎落伍了。(团队成员都知道我有几个精辟的软件工程和软件开发的比喻,不知道大家认为这个比喻怎么样/(^o^)/,比如说为什么多重继承麻烦且对象模型难于实作等。)
图12.经验和(估算、推测性设计的)不确定性之间的关系图
迭代模型适合于应对变动性的,技术水平一般的,但有进取心的积极求胜的中小项目团队。在复杂性面前强调简单性,在质量保证方面强调反馈的重要性,在决策方面强调群策群力和交流,在技术难点和技术风险上强调的是勇气。没有价值信念,很难让团队成员行动起来驱除惰性。Push模式下的成员,习惯性的成了等待工作任务的“代码员(coder)”(尤其是项目处在审核、需求分析、概要设计、详细设计、文档评审阶段,coder在干吗?),而不是“软件工程师”。在这个满街都是“客户经理”、“销售工程师”的时代,叫一个专业学历的人做个普通的“代码员”,即使薪金有吸引力,职业前景也不见得明朗。有进取心的人会有动动的想法。这是合情合理的。
3.迭代模式的几种重要方法(以XP为例子)走马观花一把
敏捷方法在坐标图的位置如图13。纵坐标是瀑布模型的严格程度;横坐标是文档的正规程度。图中可见UP(统一过程)是迭代模型,它有比较正式的文档,如果你使用过UP过程,就会发现它会形成大量的文档,图表,UMLuse-case等,迭代周期可伸缩范围较大。其实作以RUP最为著名。
图13.XP与其他几种敏捷方法的示意图
让我们重点看一下XP(ExtremeProgramming),是KentBeck创建的一种增量式迭代(IID)开发方法。这种方法通过快速创建高价值的软件、技能化和平稳的软件开发技术以及灵活响应变化等方面来提高用户满意度。它主要适用于中小团队,交付日期为一年左右的项目。极限的意思就是把各种好的实践发挥到极至,我在单元测试讲座中提过。
文档方面只有一些非正式的工件,例如归总的特征需求索引卡片,称为story-cards。
Xp的重要实践(围绕这些实践,应该进行培训哦:-*):
图14.XP的重要实践
每个实践都值得去研究。对于有争议的地方,寻求个妥协方案出来,总比没有方案好。我就不细说了。可以对比图15.看一下这些实践的实施:
图15.Xp的反馈
这么多的实践,要由人督促指导实行这种方式。所以刚开始实行XP的团队都配备一名教练。更重要的使让大家认同这种方式。孟夫子说“无恒产者无恒心!”。斗胆小辈我加一句“人无价值信念无恒心”。一个开发团队,一种开发模式要建立起一个信念,一种价值观,下面是XP的价值观,也是XP最看重的:
交流的重要性不言而喻,但仍然要鼓励再鼓励。项目组成员的每天10分钟站立式会议,了解当天的任务和项目的状况。开发人员之间的即刻交流做设计和编码等。客户的参与与促进同客户的沟通,其方式为编写验收测试和计划游戏。总之,没有交流就没有软件开发。意义够大了吧。
反馈保证了质量和自适应。客户编写user-story-card时,程序员立刻就可以进行评估,这样客户就知道工作量。测试先行有反馈,小步迭代有反馈,持续集成有反馈。项目跟踪人员每日得到user-sotries-list上完成情况的跟踪记录反馈,客户每个迭代结束得到重要反馈等。
面对一堆代码,即使你是你写的,你敢做变动吗,你做了变动之后有信心说不会有问题吗?再进一步,你敢做重大的变动吗?没有前面的价值信念和实践,你肯定不敢说有信心。我们的信念和实践现在已经做了很多事:单元测试,验收测试,持续集成,经常性的重构代码,一致的编码规范。有了这些保证,你跟以前相比勇气大多了:)。勇气除了面对激进的代码变动,还包括探求新知。面对新技术,要保持一颗年轻的心哦!
XP的生命周期:
目的:-充分评估第一次迭代的story-cards
-可行性保证
活动:-建立原型(20%的需求就是最重要的基础架构性的,前面论述过了)
-技术等方面的试探性论证
-sotry-cards的编写和评估
目的:-对第一次迭代的日期和story-cards达成共识
活动:-发布计划活动
-故事卡片(story-cards)的编写和评估
目的:-明确本次的迭代任务
活动:-用户从userstories中确定最有价值的特征作为本次迭代的目标
-加入上次迭代未通过验收测试的user-stories
目的:-在一个迭代周期内实现user-stories
活动:-简单设计、测试、结对编程、重构、迭代期验收以及在需求细节上与客户不断沟通协作
(如果没有完成发布前的工作,返回到迭代计划游戏阶段)
目的:-产品化,发布产品
活动:-产品文档、技能培训和团队知识共享,排除项目中的“知识孤岛”现象(其实轮换配对减少了知识孤岛的存在,知识孤岛让开发人员都不知道软件其他部分,这对维护期是个灾难)
-发布产品
(略)
XP的工件、角色和实践:
工件(没有文档,除了软件,项目产生了其他什么吗?)
1)story-cards-记录简明特征需求(非use-case和场景)的纸质卡片,预示着需要进一步与客户讨论具体细节,粒度2-10天。XP是特征驱动不是用例驱动。
2)任务列表–每次迭代中针对story编写的任务列表卡片或白板上的表格,任务粒度1-2天。
3)可视化图表-用于便于沟通。
角色
客户
-编写故事(stories)和验收测试
-挑选用于发布和迭代的故事
开发-程序员
-编写测试、设计、和代码
-重构
-确定、领取任务和估算
开发-测试员
-帮助客户编写和开发测试
管理-教练(有经验的XP团队可不设置)
-过程辅导
-过程定制
-干预和培训
管理-项目跟踪者
-收集度量情况
-报告进度
-根据简单的估算进行反馈
其他-顾问等
-技术咨询和指导
实践
对应到需求:(谁说XP不做需求,而且是持续获取需求!)
-计划游戏
-现场客户
-验收测试
设计:
-系统隐喻
-频繁重构
-简单设计
实现:
-编码标准(一致的风格、文档化(如doxygen)注释,这可以是最好的设计和实现文档)
-结对编程
-代码的所有权归团队
测试和验证:
-验收测试,客户测试
-测试先行的开发单元测试
项目管理:
-小版本发布
-平稳的工作进度
配置并改变管理环境:
-持续继承
-公用房间
核心实践和描述:(摘自CraigLarmanAgileandIterativeDevelopment:AManager'sGuide)
不翻译,看点原味的吧。
其他实践和价值观:
文字太多了,还是看些图表吧,一切尽在不言中!
图16.是极限编程项目过程总览
图16.Xp项目总览
下图是XP迭代过程。
图17.XP的Iteration
下图是XP的开发图
图18.XP的Deveopment图
下图是XP的集体代码所有图,其实讲的是如何合作开发。
图19.XP的集体代码所有图
4.我们的方向和要重点研究的几个问题
首先明确的是类瀑布模型肯定不适合软件开发。XP也不是黑客的编写边改方式。借鉴迭代模型和敏捷开发方法势在必行,并且在过去的项目上曾经使用过全部或者部分重要方法和实践(我所知道的是SworkCao&RobinQiu的项目上)。其实分解开来,这些重要实践是每个方法或多或少都包含的。
总的来说,在这样的团队中,项目成员能够得到锻炼和知识积累,而不象在Push模式下单纯接受任务的coder这样一个枯燥,缺乏交流和自信,缺乏勇气和疲于应付Bugs的局面。从而可以进入到一种积极向上的,心情轻松的,良好交流的、具合作氛围的、不断克服困难后得到成就感的良好循环。
软件开发中有苦闷也有快乐。我的一个同时曾经独自一个人对付一个子项目,三个月闷头干活,至见到计算机就要吐的地步,毫无乐趣,枯燥乏味,项目也没怎么完成好。身为程序员的我们要会找点乐子自娱自乐。比如Sunwah最合格的程序员DanielCao就playviolin,过去是驴叫,现在应该有旋律了吧?!。
5.XP的场景和样板
XP有样板工程,但我没去进一步查看能获得那些信息。
我没能搜集到更多的图,下面是一些,还有一个重要链接,大家务必看一下,如果全部复制过来,篇幅太大了。
图20.常见的开发现场,空出所有的墙面备用
图21.每日10分钟的站立会议
篇幅太大了,看个重要的链接
图22.XP团队工作室一角
6.附录
敏捷软件开发宣言
也就是说,虽然也具有价值,但我们认为左边的项具有更大的价值。
敏捷软件开发的原则我们遵循以下的原则:
1)我们最先要做的是通过尽早地、持续地交付有价值的软件来使客户满意。
2)即使到了开发的后期,也欢迎改变需求。敏捷过程利用变化来为客户创造竞争优势。
4)在整个项目开发期间,业务人员和开发人员必须天天都在一起工作。
5)围绕被激励起来的个体来构建项目。给他们提供所需的环境和支持,并且信任他们能够完成工作。
6)在团队内部以及团队之间,最有效果并且最富有效率的传递信息的方式,就是面对面的交谈。
7)可以工作的软件是首要的进度度量标准。
8)敏捷过程提倡平稳的开发。
9)发起人、开发者和用户应该能够保持一个长期的、恒定的开发速度。