C++ Programmer's Cookbook

{C++ 基础} {C++ 高级} {C#界面,C++核心算法} {设计模式} {C#基础}

敏捷软件开发精彩问答

问:敏捷开发如何融入到现在在推行的CMMI中?
答:首先,我想说一下为什么会在CMM的基础上提出CMMI。Barry Boehm在其新作《Balancing Agility and Discipline: A Guide for the Perplexed》一书中对此进行了比较深入的阐述。从总体上来说,有两个主要原因:1、对CMM中那些容易导致官僚的部分进行了大幅度的更改;2、把风险驱动作为一个核心内容纳入到CMMI的框架之中,这样在CMMI的框架中就可以比较顺畅的制定出一些可以非常敏捷的过程了。但是,CMMI的敏捷性是很难刻画的,因为作为一个过程改进参考模型,它更加贴近一组需求而不是一组实践。也就是说,我们只能刻画那些为满足这些需求而开发出的过程。一般来说,CMMI在需求方面的约束少于SW-CMM。如果以更为宽广的观点去解释需求就可以获取更多的敏捷性。然而,如果在实施时采用了全面保守的做法并且使用了由SW-CMM所提供的重量级成熟度评估方法,那么所得出的CMMI兼容过程将是重型且非常计划驱动的。因此,我觉得敏捷本来就可以非常顺畅地融入到CMMI的模型中。如果说有问题的话,我觉得更多在于实施者对敏捷的排斥,而非其他。
 
问:敏捷开发流程是如何应对各种可预知和不可预知的风险? 例如:人员流动和变更,项目周期的变更,客户代表的变更等风险。
答:人员流动和变更、项目周期的变更以及客户代表的变更等风险是任何一个软件开发项目都不可避免要面临的。一个好的过程方法应该能够使得这些风险导致的损失最小化。敏捷方法试图营造一种非常舒适的开发环境,这是一种典型的craftsmanship文化。在这种文化中,人们都一自己的技艺为荣,以开发出高质量的软件为荣,并且不断追求技艺的提高。在这样的环境中,人员流动和变更的频度被大大地降低。另外,敏捷方法对面对面沟通、结对编程以及高质量代码和文档的强调也使得由于人员变动所导致的风险大大降低。
对于项目周期的变更,我想再也没有比快速、短的迭代更有效的应对方法了。正是这些快速的短迭代为我们带来的大量的反馈信息,使得我们对于项目的状况具有全面、深入并且是真实的了解。有了这个基础,我们在最小化项目周期变更风险方面就处于一个非常有利的位置。而快速的短迭代正是敏捷的重要特征。什么是敏捷呢?敏捷就是:“short cycles that are test-driven and feedback-driven, yielding constant improvements.”对于客户代表的变更,我不想多说。因为无论是对于敏捷方法还是计划驱动方法,客户代表的变更带来的风险都是一样的。如果,没有一个好的客户代表,那么肯定是一个失败的项目。
 
问:敏捷开发流程是否适用于大型、复杂的应用系统?因为对于一些架构比较简单,代码量小的系统,可以通过不断的代码重构进行改进,但对于一些体系结构比较复杂的系统在投入运行后,短时间内,由于客户业务的扩张导致的数据容量的增大或者网络访问量的增加, 而导致原有的核心架构设计已经不能满足用户的需求,而这些重要的架构在系统核心服务中起重要作用而很难进行变更。这种情况,变更这些方面的代价会很高,因此需要早期花费精力预期此类变更。而且这类软件的复杂性和规模会导致严格的代码重构代价过高而且容易出错。
答:首先我们得在什么是大型、复杂的应用系统这个问题上取得共识。Scrum方法应用的最大的一个项目是一个医疗图像信息系统,共有800人。XP方法应用的最大一个项目是一个企业资源综合管理系统,共有50人。当然,在人数增多时,就必须要采取一些变通的实践(否则就不敏捷了)。对于架构方面的问题,我觉得应该这样看。如果是一个相对成熟的领域,那么可以借鉴很多业界已有的经验,特别是一些相关的模式。这一点很重要,否则是要走很多弯路,付出很多代价的。比如:我觉得在并发、分布式通信领域,一个合格的系统工程师必须应该知道并理解《Pattern-Oriented Software Architecture, Volume 2》中的所有模式。但是,这只是为你提供了一个方向,一个防止你犯重大错误的方向。这些模式为你代码的重构和系统的演化提供了一个指引。如果不了解这些模式,基本不可能做出一个优秀的架构。了解了这些模式后,是不是就可以在一开始就把它们堆砌起来以形成一个能够适应未来的架构呢?当然不行。要想构建一个能够适应未来的架构,有两种途径,一种需要天才的系统架构师,一种是在领域模式的引导下,通过TDD和Refactoring的方式不断、逐步地修改。显然,第2种方法是一种切实可行的方法。

问:敏捷开发流程是否不支持创建可复用产品?对于一个工程型,可复用的产品对于节约成本和提高效率是极其重要的!
答:关于可复用性的问题,一直都是软件界讨论的热点。一般来说,有机制层面的复用,比如:一般的函数库或者类库,也有应用领域逻辑的复用,比如:各种领域相关的应用框架。第一种复用方法相对比较容易,但是带来的好处也相对较低。而第二种复用方法能给我们带来最大的好处,但是非常的困难。也正是因为这一点,在业界一度有“复用神话”的说法。无数实践表明,要想得到一个相对可用的领域框架,必须要经受至少3个同质领域实践的锤炼。并且,失败的数目要远远大于成功的。而试图在一开始就把可复用性作为目标的项目基本上没有取得成功的(这样的框架一般具有这样的特点:本来一件简单的任务,但在使用了该框架后却变得非常复杂。)。因此,现在业界比较一致的看法是,首先应该针对你开发的领域搭建一个特定于项目的、简单的框架。一开始不要考虑复用性,而关注于系统的清晰性和简单性。在另一个同质的项目中,通过重构、演化的方法在对这个框架进行修正,使之更具通用性,如此循环往复。在经历过多个项目后,可能你就得到了一个比较具有可复用性的框架。也就是说,应该关注于创建那些比较容易演化为可重用框架的东东,这个东东应该具有两个特点:1、针对具体问题;2、非常简单清晰。敏捷方法非常注重这种框架的形成,但是不会刻意去这样做,它的思路是在不断的循环、迭代中把它演化出来。在这个循环迭代中,敏捷方法以DRY(Don't Repeat Yourself)原则来逐步建立起更大规模重用的基础。

问:敏捷开发流程的质量保证机制是否足够满足开发有严格安全性和可靠性要求的软件?对于在电力,电信系统中一些有严格安全性要求的软件敏捷开发流程支持的质量控制机制似乎并没有证明来说服使用者软件是安全的。是否还需其它措施进行补充?
答:首先我要说的是,安全性和可靠性是属于用户需求的范畴,而敏捷方法中把客户满意放在了非常重要的位置上,单从过程方法的思想基础方面来说,没有那种方法能比敏捷方法更关注客户的满意度了。其次,安全性和可靠性不是通过一些条条框框说出来的,那些在系统方案中空洞地罗列一些安全性和可靠性方面的术语的做法,对于保证系统的可靠性和安全性没有任何用处。保证安全性和可靠性的唯一方法就是去检验,随着系统的演化,不断地检验。把用户在安全性和可靠性方面的需求通过测试用例的方式编写出来,频繁地去验证系统是否能够通过这些测试,如果不通过,就是一次集成失败。不知大家在保证系统可靠性和安全性方面是如何做的?

问:目前的项目和部门的组织架构,内部客户和外部客户离开发人员都很远,怎样能够达到零距离? 虽然单个客户和开发人员在一起工作可以有效对需求变更进行跟踪,及时响应需求变更,但如果系统面对的客户是不同的,如何避免开发期间一些需求变更的单一性和独特性?
答:无论项目采用任何方法,它对于客户都有同样的要求,就是这个客户必须是CRACK(Collaborative、Representative、Authorized、Committed、Knowledgeable)型的客户。鉴于目前我们所处的各种环境,完全的CRACK和现场客户可能不太可能。但是一个能够合格地担当其客户角色,并且能够比较频繁的参与到项目开发中来的人员对于项目的成功来说是必须的。另外,应对需求的变化正是敏捷方法的强项,如果这些变化是客户真正需要的,那么为何要避免呢?此时,我们应该利用这些变化取得优势。

问:如何避免开发人员利用够用文档这个借口偷懒少写文档?
答:处于敏捷文化中的人以高质量地完成任务为荣,如果写文档是高质量地完成任务的一部分,那么他肯定会高质量地写出这份文档。否则,写再多言之无物、只满足格式的文档又有什么用呢?敏捷实践都是能够真正提供开发人员技能的实践,敏捷方法强烈反对那些仅仅是为了防止开发人员“偷懒”而制定的规程。
 
问:开发人员面对面的交流过频繁,导致大会小会不断,如何把握这个度?
答:面对面交流不是开会。只要觉得需要就去交流。
 
问:简单设计的粒度如何把握,如果强调前期架构的简单设计,如何应对软件投入运行后,短时间内,由于客户业务的扩张导致的数据容量的增大或者网络访问量的增加,而导致原有的设计已经不能满足用户的需求?
答:请参见前面那个关于架构的回答。首先,你要有丰富的经验和知识,这些东西可以为你提供一个架构演化的方向。如果没有这些东西,基本上没有可能首次就找到正确的方向。有了方向后,下面就是TDD+Refactoring不断演化。
 
问:简单设计如何能保证实施测试驱动开发?如果设计的不够详细,如何对接口编写测试用例和测试代码?
答:首先,不是简单设计保证实施测试驱动开发,而是测试驱动开发可以促使你得到一个简单的设计。其次,是先有测试用例,然后才有设计和接口。
 
问:《敏捷》书中把创建验收测试作为一种设计系统架构的重要手段,也作为对最终用户的一种功能演示,但本质上还是对系统特性的一种模拟集成测试,并不能完全代表实际系统,这种验收测试与传统意义上的验收测试不同,这种验收测试可靠吗?
答:这里所指得传统意义上的验收测试是什么?是指有测试人员进行的测试吗?一般在敏捷方法中(特别是XP)所指的验收测试,都是由QA和客户代表共同编写的,如果通过就表明实现了客户需求。我觉得没有其他方法能比这个方法更可靠了。
 
问:测试驱动开发的例子中,开始也做了简单的设计,然后再编写测试用例,最后形成另外一种设计。开始时需要设计吗?如果需要,应该达到什么程度?开始不进行设计而纯粹依靠测试来驱动设计可能吗?我的理解是,测试驱动开发更适合于详细设计阶段,测试驱动开发适合于架构设计吗?文章中的测试驱动开发例子中,软件需求好像来自个人“随心所欲”的想象,这种测试用例的生成方法是否缺乏系统性和完备性?或者说,测试驱动开发的测试用例的产生是否也需要严密的设计呢?
答:什么是设计?这是一个必须首先达成共识的问题。TDD的核心就是持续设计,不断关注设计质量,这种关注是建立在频繁的、真实的反馈的基础之上的,而不是一些臆想。达到的程度就是“tuned to today and poised to strike at tomorrow.”通过一些想象画几张UML图,那不是设计,设计应该是可验证的,并且要通过反馈持续修正的。设计的验证正是通过测试用例进行的。测试用例可以是客户需求,这是验收测试。也可以是开发团队内部实现上的需求,这是开发团队内部的测试(一般也成为单元测试)。测试用例应该来自客户,这是勿庸置疑的。测试活动本来就是一项风险驱动活动,在测试投入到达一定水平后,它的效果会迅速降低。对于“系统性”、“完备性”以及“严密性”,我不知道具体指得是什么?能不能详细说明一下,并介绍大家是如何做到需求的“系统性”、“完备性”以及“严密性”。

问:敏捷设计开始设计的程序也可能是最简单,不具有灵活性,直到需要变化时,团队才抓住机会应用敏捷设计原则去改进设计。这里有几个前提,团队应该对不良设计足够敏感,才能抓住改进设计的机会;团队有足够的时间去改进设计。如果这两个前提不成立,如果进行敏捷设计?
答:怎样才具有灵活性呢?把东西做简单,简单的东西最具有灵活性!Kent Beck在《eXtreme Programming》一书中对什么是简单做过明确的定义。用一句话来说,就是:“clean code that works.”如果这些前提不成立的话,那么什么设计都做不了。很多敏捷实践的目的就是帮助我们通过学习、实践来培养这种敏感性。

问:测试驱动开发过程中如何把握“前进的步伐”,即,每个测试用例的粒度如何把握?粒度大,可以加快开发速度,但又可能漏掉某些bug;粒度小,又影响开发进度。如何看待测试驱动开发过程中的测试用例?是单元测试吗?还是粒度很大的集成测试?如果是单元测试,至少也不应该是传统意义上的单元测试,此时的单元测试是属于黑盒测试还是白盒测试,或者既不是黑盒也不是白盒?如何理解测试驱动开发可以改进设计?有何理论根据?能够从黑盒测试的理论阐述这个问题吗?
答:粒度就是一个独立的、可以验证的东西。Kent Beck在其《Test-Driven Development》一书中对使用TDD开发的节奏有详细的描述,我就不再赘述。写测试觉得不会影响开发进度,越是在时间压力大的情况下,越是如此。我想大家都有过这样的经历吧:“花20分钟完成了一项功能,然后花2个小时甚至更多的时间去调试。”在TDD中,测试用例只用两种,面向客户的验收测试用例,和面向开发团队内部的内部测试用例(一般也称为单元测试)。为什么一定要那么清楚地区分黑盒和白盒呢?测试驱动开发能够改善设计的思想基础在《Test-Driven Development》有详细阐述。这和黑盒测试没有任何关系。TDD更是一种设计方法,一种有反馈、有验证的真正的设计方法。

问:关于“软件之美”:对软件设计者来说,被简单、直观地分割,并具有最小内部耦合的内部结构就是美的。美的系统是灵活、易于理解的,构建、维护它们就是一种快乐。在软件领域,如何审美?“灵活、易于理解的”这个概念含有很多主观性,对某一具体的软件审美,不同的人的评价是不一样的,大师级别的人当然更准确些,但大师级别的人太少了,那么,有没有一些客观的、可以量化的指标?使得没有很多经验的人,也可以以此为指引,改进软件使之向美的方向发展?
答:《敏捷软件开发:原则、实践和模式》一书中给出了很多原则和实践方法,可以作为很好的参考。
 
问:极限编程只适用于轻量级团队和项目,还是也适用于重量级团队和项目?和CMM等有无矛盾?在推行极限编程哪些可行(如测试驱动开发),哪些不可行(如结对编程)?在重量级团队和项目中如何运用?
答:极限编程对于小型项目(10~20人)来说肯定没有问题。对于大型项目来说,照搬XP中的实践,肯定是会出问题的。所以需要一定程度的根据具体情况进行修正。关于和CMM有无矛盾的问题,这方面的讨论和文章有很多,基本上是见仁见智。不过,在提高开发质量这个目标上是肯定不矛盾的。其实,关于CMM本身该如何实施方面也存在很多不同意见,不同的评估师给出截然不同的结论的案例就有很多。其实也没有必要非得全盘照搬XP不可,我觉得可以在不更改团队现有运作流程的情况下,先引入小部分实践,TDD应该是首选。
 
问:5个重要的原则“单一职责原则、开放-封闭原则、Liskov替换原则、依赖倒置原则、接口隔离原则”虽然在此把它们表述为面向对象设计的原则,但是事实上它们只是软件工程中一直存在的原则的特例而已。那么,软件工程中一直存在的普遍性原则是什么?有哪些?在结构化编程还大量应用的嵌入式开发中,如何运用?“为使用而使用”设计原则会导致不必要的复杂性,设计原则是经验的总结,它必然是思考某个问题而得到的解决办法指导,那么,在编程当中,时刻要思考的问题有哪些?
答:首先我得说一下,越是具有普遍性得原则,越不具有可实施性,只有针对特定context和force的原则才具有更多的实际意义,这也是模式为何在传播优秀的设计经验方面得到普遍认可的重要原因。如果非要给出一个普遍原则的话,我觉得Grady Booch曾经说过的一句话可以作为参考:“The entire history of sw enginerering is one of rising levels of abstraction.”不论你使用结构化编程还是面向对象编程,了解多种编程范型肯定会对你的开发带来好处。设计原则和模式只能为你指引方向,最为重要的是要保持(设计)代码简单,时刻思考的问题就是,这段代码是不是清晰地表达了我的意图,也就是要intentional programming,要“Keep It DRY, Shy, and Tell the Other Guy.

posted on 2006-06-28 08:46 梦在天涯 阅读(615) 评论(0)  编辑 收藏 引用 所属分类: XP /AOP


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

EMail:itech001#126.com

导航

统计

  • 随笔 - 461
  • 文章 - 4
  • 评论 - 746
  • 引用 - 0

常用链接

随笔分类

随笔档案

收藏夹

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

积分与排名

  • 积分 - 1783954
  • 排名 - 5

最新评论

阅读排行榜