LoveUnix » 行业应用 项目实施 » 极限编程(Extreme Programming)-XP之旅
让LU留住您的每

一天 让LU博客留住您的每一天
2004-3-22 10:14 99大话王
什么是Extreme Programming(一)<br />waltson 2002.05.11<br /><!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->Extreme Programming(极限编程,简称XP)是由Kent Beck在1996年提出的。Kent Beck在九十年代初 <br />期与Ward Cunningham共事时,就一直共同探索着新的软件开发方法,希望能使软件开发更加简单而有 <br />效。Kent仔细地观察和分析了各种简化软件开发的前提条件、可能行以及面临的困难。1996年三月, <br />Kent终于在为DaimlerChrysler所做的一个项目中引入了新的软件开发观念——XP。 <br /><br />XP是一个轻量级的、灵巧的软件开发方法;同时它也是一个非常严谨和周密的方法。它的基础和价值观 <br />是交流、朴素、反馈和勇气;即,任何一个软件项目都可以从四个方面入手进行改善:加强交流;从简 <br />单做起;寻求反馈;勇于实事求是。XP是一种近螺旋式的开发方法,它将复杂的开发过程分解为一个个 <br />相对比较简单的小周期;通过积极的交流、反馈以及其它一系列的方法,开发人员和客户可以非常清楚 <br />开发进度、变化、待解决的问题和潜在的困难等,并根据实际情况及时地调整开发过程。 <br /><br /><br /><br />什么是软件开发 <br /><br />软件开发的内容是:需求、设计、编程和测试! <br />需求:不仅仅是用户需求,应该是开发中遇到的所有的需求。比如,你首先要知道做这个项目是为了解 <br />决什么问题;测试案例中应该输入什么数据……为了清楚地知道这些需求,你经常要和客户、项目经理 <br />等交流。 <br />设计:编码前,肯定有个计划告诉你要做什么,结构是怎样等等。你一定要按照这个来做,否则可能会 <br />一团糟。 <br />编程:如果在项目截止日,你的程序不能跑起来或达不到客户的要求,你就拿不到钱。 <br />测试:目的是让你知道,什么时候算是完成了。如果你聪明,你就应该先写测试,这样可以及时知道你 <br />是否真地完成了。否则,你经常会不知道,到底有哪些功能是真正完成了,离预期目标还差多远。 <br /><br />软件开发中,客户和开发人员都有自己的基本权利和义务。 <br />客户: <br /> • 定义每个用户需求的商业优先级; <br /> • 制订总体计划,包括用多少投资、经过多长时间、达到什么目的; <br /> • 在项目开发过程中的每个工作周,都能让投资获得最大的收益; <br /> • 通过重复运行你所指定的功能测试,准确地掌握项目进展情况; <br /> • 能随时改变需求、功能或优先级,同时避免昂贵的再投资;能够根据各种变化及时调整项目计划; <br /> • 能够随时取消项目;项目取消时,以前的开发工作不是一堆垃圾,已开发完的功能是合乎要求的, <br />正在进行或未完成的的工作则应该是不难接手的。 <br />开发人员: <br /> • 知道要做什么,以及要优先做什么; <br /> • 工作有效率; <br /> • 有问题或困难时,能得到客户、同事、上级的回答或帮助; <br /> • 对工作做评估,并根据周围情况的变化及时重新评估; <br /> • 积极承担工作,而不是消极接受分配; <br /> • 一周40小时工作制,不加班。 <br /><br />这就是软件开发,除此之外再还有其它要关心的问题! <br /><br /><br /><br />灵巧的轻量级软件开发方法 <br /><br />一套软件开发方法是由一系列与开发相关的规则、规范和惯例。重量级的开发方法严格定义了许多的规 <br />则、流程和相关的文档工作。灵巧的轻量级开发方法,其规则和文档相对较少,流程更加灵活,实施起 <br />来相对较容易。 <br /><br />在软件工程概念出现以前,程序员们按照自己喜欢的方式开发软件。程序的质量很难控制,调试程序很 <br />繁琐,程序员之间也很难读懂对方写的代码。1968年,Edsger Dijkstra给CACM写了一封题为GOTO&amp;nbsp; <br />Statement Considered Harmful 的信,软件工程的概念由此诞生。程序员们开始摒弃以前的做法,转 <br />而使用更系统、更严格的开发方法。为了使控制软件开发和控制其它产品生产一样严格,人们陆续制定 <br />了很多规则和做法,发明了很多软件工程方法,软件质量开始得到大幅度提高。随着遇到的问题更多, <br />规则和流程也越来越精细和复杂。 <br /><br />到了今天,在实际开发过程中,很多规则已经难于遵循,很多流程复杂而难于理解,很多项目中文档的 <br />制作过程正在失去控制。人们试图提出更全面更好的一揽子方案,或者寄希望于更复杂的、功能更强大 <br />的辅助开发工具(Case Tools),但总是不能成功,而且开发规范和流程变得越来越复杂和难以实施。 <br />为了赶进度,程序员们经常跳过一些指定的流程,很少人能全面遵循那些重量级开发方法。 <br /><br />失败的原因很简单,这个世界没有万能药。因此,一些人提出,将重量级开发方法中的规则和流程进行 <br />删减、重整和优化,这样就产生了很多适应不同需要的轻量级流程。在这些流程中,合乎实际需要的规 <br />则被保留下来,不必要的复杂化开发的规被抛弃。而且,和传统的开发方法相比,轻量级流程不再象流 <br />水生产线,而是更加灵活。 <br /><br />Extreme Programming(XP)就是这样一种灵巧的轻量级软件开发方法。 <br /><br /><br /><br />为什么称为“Extreme”(极限)&amp;nbsp; <br /><br />“Extreme”(极限) 是指,对比传统的项目开发方式,XP强调把它列出的每个方法和思想做到极限、 <br />做到最好;其它XP所不提倡的,则一概忽略(如开发前期的整体设计等)。一个严格实施XP的项目,其 <br />开发过程应该是平稳的、高效的和快速的,能够做到一周40小时工作制而不拖延项目进度。&amp;nbsp; <br /><br /><br /><br />XP的软件开发是什么样 <br /><br />1 极限的工作环境 <br /><br />为了在软件开发过程中最大程度地实现和满足客户和开发人员的基本权利和义务,XP要求把工作环境也 <br />做得最好。每个参加项目开发的人都将担任一个角色(项目经理、项目监督人等等)并履行相应的权利 <br />和义务。所有的人都在同一个开放的开发环境中工作,最好是所有人在同一个大房子中工作,还有茶点 <br />供应;每周40小时,不提倡加班;每天早晨,所有人一起站着开个短会;墙上有一些大白板,所有的 <br />Story卡、CRC卡等都贴在上面,讨论问题的时候可以在上面写写画画;下班后大家可以一起玩电脑游 <br />戏……。 <br /><br />2 极限的需求 <br /><br />客户应该是项目开发队伍中的一员,而不是和开发人员分开的;因为从项目的计划到最后验收,客户一 <br />直起着很重要的作用。开发人员和客户一起,把各种需求变成一个个小的需求模块(User Story),例 <br />如“计算年级的总人数,就是把该年级所有班的人数累加。”;这些模块又会根据实际情况被组合在一 <br />起或者被分解成更小的模块;它们都被记录在一些小卡片(Story Card)上,之后分别被程序员们在各 <br />个小的周期开发中(Iteration,通常不超过3个星期)实现;客户根据每个模块的商业价值来指定它们 <br />的优先级;开发人员要做的是确定每个需求模块的开发风险,风险高的(通常是因为缺乏类似的经验) <br />需求模块将被优先研究、探索和开发;经过开发人员和客户分别从不同的角度评估每个模块后,它们被 <br />安排在不同的开发周期里,客户将得到一个尽可能准确的开发计划;客户为每个需求模块指定验收测试 <br />(功能测试)。 <br /><br />每发布一次开发的软件(经过一个开发周期),用户都能得到一个可以开始使用的系统,这个系统全面 <br />实现了相应的计划中的所有需求。而在一些传统的开发模式中,无论什么功能,用户都要等到所有开发 <br />完成后才能开始使用。&amp;nbsp; <br /><br />3 极限的设计&amp;nbsp; <br /><br />从具体开发的角度来看,XP内层的过程是一个个基于测试驱动的开发(Test Driven Development)周 <br />期,诸如计划和设计等外层的过程都是围绕这些展开的。每个开发周期都有很多相应的单元测试 <br />(Unit Test)。刚开始,因为什么都没有实现,所以所有的单元测试都是失败的;随着一个个小的需 <br />求模块的完成,通过的单元测试也越来越多。通过这种方式,客户和开发人员都很容易检验,是否履行 <br />了对客户的承诺。XP提倡对于简单的设计(Simple Design),就是用最简单的方式,使得为每个简单 <br />的需求写出来的程序可以通过所有相关的单元测试。XP强调抛弃那种一揽子详细设计方式(Big&amp;nbsp; <br />Design Up Front),因为这种设计中有很多内容是你现在或最近都根本不需要的。XP还大力提倡设计 <br />复核(Review)、代码复核以及重整和优化(Refectory),所有的这些过程其实也是优化设计的过 <br />程;在这些过程中不断运行单元测试和功能测试,可以保证经过重整和优化后的系统仍然符合所有需 <br />求。&amp;nbsp; <br /><br />4 极限的编程&amp;nbsp; <br /><br />既然编程很重要,XP就提倡两个人一起写同一段程序(Pair Programming),而且代码所有权是归于整 <br />个开发队伍(Collective Code Ownership)。程序员在写程序和重整优化程序的时候,都要严格遵守 <br />编程规范。任何人都可以修改其他人写的程序,修改后要确定新程序能通过单元测试。&amp;nbsp; <br /><br />5 极限的测试&amp;nbsp; <br /><br />既然测试很重要,XP就提倡在开始写程序之前先写单元测试。开发人员应该经常把开发好的模块整合到 <br />一起(Continuous Integration),每次整合后都要运行单元测试;做任何的代码复核和修改,都要运 <br />行单元测试;发现了BUG,就要增加相应的测试(因此XP方法不需要BUG数据库)。除了单元测试之外, <br />还有整合测试,功能测试、负荷测试和系统测试等。所有这些测试,是XP开发过程中最重要的文档之 <br />一,也是最终交付给用户的内容之一。&amp;nbsp; <!--QuoteEnd--></div><!--QuoteEEnd--><br /><a href='http://www.chinaxp.org/' target='_blank'>http://www.chinaxp.org/</a>

2004-3-22 10:15 99大话王
什么是Extreme Programming(二)<br /><!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->XP中的重要惯例和规则 <br /><br />1 项目开发小组(Team) <br /><br />在XP中,每个对项目做贡献的人都应该是项目开发小组中的一员。而且,这个小组中必须至少有一个人 <br />对用户需求非常清晰,能够提出需求、决定各个需求的商业价值(优先级)、根据需求等的变化调整项 <br />目计划等。这个人扮演的是“客户”这个角色,当然最好就是实际的最终用户,因为整个项目就是围绕 <br />最终用户的需求而展开的。程序员是项目开发小组中必不可少的成员。小组中可以有测试员,他们帮助 <br />客户制订验收测试;有分析员,帮助客户确定需求;通常还有个Coach(教练),负责跟踪开发进度、 <br />解决开发中遇到的一些问题、推动项目进行;还可以又一个项目经理,负责调配资源、协助项目内外的 <br />交流沟通等等。项目小组中有这么多角色,但并不是说,每个人做的工作是别人不能插手或干预的,XP <br />鼓励每个人尽可能地为项目多做贡献。平等相处,取长补短;这就是最好的XP开发小组。 <br /><br />2 计划项目(Planning Game)、验收测试、小规模发布(Small Releases) <br /><br />XP开发小组使用简单的方式进行项目计划和开发跟踪,并以次预测项目进展情况和决定未来的步骤。根 <br />据需求的商业价值,开发小组针对一组组的需求进行一系列的开发和整合,每次开发都会产生一个通过 <br />测试的、可以使用的系统。 <br /><br />•&nbsp; 计划项目 <br /><br />XP的计划过程主要针对软件开发中的两个问题:预测在交付日期前可以完成多少工作;现在和下一步该 <br />做些什么。不断的回答这两个问题,就是直接服务于如何实施及调整开发过程;与此相比,希望一开始 <br />就精确定义整个开发过程要做什么事情以及每件事情要花多少时间,则事倍功半。针对这两个问题,XP <br />中又两个主要的相应过程: <br /><br />软件发布计划(Release Planning)。客户阐述需求,开发人员估算开发成本和风险。客户根据开发成 <br />本、风险和每个需求的重要性,制订一个大致的项目计划。最初的项目计划没有必要(也没有可能)非 <br />常准确,因为每个需求的开发成本、风险及其重要性都不是一成不变的。而且,这个计划会在实施过程 <br />中被不断地调整以趋精确。 <br /><br />周期开发计划(Iteration Planning)。开发过程中,应该有很多阶段计划(比如每三个星期一个计 <br />划)。开发人员可能在某个周期对系统进行内部的重整和优化(代码和设计),而在某个周期增加了新 <br />功能,或者会在一个周期内同时做两方面的工作。但是,经过每个开发周期,用户都应该能得到一个已 <br />经实现了一些功能的系统。而且,每经过一个周期,客户就会再提出确定下一个周期要完成的需求。在 <br />每个开发周期中,开发人员会把需求分解成一个个很小的任务,然后估计每个任务的开发成本和风险。 <br />这些估算是基于实际开发经验的,项目做得多了,估算自然更加准确和精确;在同一个项目中,每经过 <br />一个开发周期,下一次的估算都会有更过的经验、参照和依据,从而更加准确。 <br />这些简单的步骤对客户提供了丰富的、足够的信息,使之能灵活有效地调控开发进程。每过两三个星 <br />期,客户总能够实实在在地看到开发人员已经完成的需求。在XP里,没有什么“快要完成了”、“完成 <br />了90%”的模糊说法,要不是完成了,要不就是没完成。这种做法看起来好象有利有弊:好处是客户可以 <br />马上知道完成了哪些、做出来的东西是否合用、下面还要做些什么或改进什么等等;坏处是客户看到做 <br />出来的东西,可能会很不满意甚至中止合同。实际上,XP的这种做法是为了及早发现问题、解决问题, <br />而不是等到过了几个月,用户终于看到开发完的系统了,然后才告诉你这个不行、那个变了、还要增加 <br />哪个内容等等。 <br /><br />•&nbsp; 验收测试 <br /><br />客户对每个需求都定义了一些验收测试。通过运行验收测试,开发人员和客户可以知道开发出来的软件 <br />是否符合要求。XP开发人员把这些验收测试看得和单元测试一样重要。为了不浪费宝贵的时间,最好能 <br />将这些测试过程自动化。 <br /><br />•&nbsp; 频繁地小规模发布软件(Small Releases) <br /><br />每个周期(Iteration)开发的需求都是用户最需要的东西。在XP中,对于每个周期完成时发布的系 <br />统,用户都应该可以很容易地进行评估,或者已经能够投入实际使用。这样,软件开发对于客户来说, <br />不再是看不见摸不着的东西,而是实实在在的。XP要求频繁地发布软件,如果有可能,应该每天都发布 <br />一个新版本;而且在完成任何一个改动、整合或者新需求后,就应该立即发布一个新版本。这些版本的 <br />一致性和可靠性,是靠验收测试和测试驱动的开发来保证的。 <br /><br />3 简单设计,Pair Programming,测试驱动开发,重整和优化 <br /><br />XP程序员不但做为一个开发小组共同工作,还以两个人为一个小开发单元编写同一个程序。开发人员们 <br />进行简单的设计,编写单元测试后再编写符合测试要求的代码,并在满足需求的前提下不断地优化设 <br />计。 <br /><br />•&nbsp; 简单设计 <br /><br />XP中让初学者感到最困惑的就是这点。XP要求用最简单的办法实现每个小需求,前提是按照这些简单设 <br />计开发出来的软件必须通过测试。这些设计只要能满足系统和客户在当下的需求就可以了,不需要任何 <br />画蛇添足的设计,而且所有这些设计都将在后续的开发过程中就被不断地重整和优化。 <br /><br />在XP中,没有那种传统开发模式中一次性的、针对所有需求的总体设计。在XP中,设计过程几乎一直贯 <br />穿着整个项目开发:从制订项目的计划,到制订每个开发周期(Iteration)的计划,到针对每个需求 <br />模块的简捷设计,到设计的复核,以及一直不间断的设计重整和优化。整个设计过程是个螺旋式的、不 <br />断前进和发展的过程。从这个角度看,XP是把设计做到了极致。 <br /><br />•&nbsp; Pair Programming <br /><br />XP中,所有的代码都是由两个程序员在同一台机器上一起写的——这是XP中让人争议最多、也是最难实 <br />施的一点。这保证了所有的代码、设计和单元测试至少被另一个人复核过,代码、设计和测试的质量因 <br />此得到提高。看起来这样象是在浪费人力资源,但是各种研究表明事实恰恰相反。—— 这种工作方式 <br />极大地提高了工作强度和工作效率。 <br /><br />很多程序员一开始是被迫尝试这点的(XP也需要行政命令的支持)。开始时总是不习惯的,而且两个人 <br />的效率不会比一个人的效率高。这种做法的效果往往要坚持几个星期或一两个月后才能很显著。据统 <br />计,在所有刚开始Pair Programming的程序员中,90%的人在两个月以后都很认为这种工作方式更加高 <br />效。 <br /><br />项目开发中,每个人会不断地更换合作编程的伙伴。因此,Pair Programming不但提高了软件质量,还 <br />增强了相互之间的知识交流和更新,增强了相互之间的沟通和理解。这不但有利于个人,也有利于整个 <br />项目、开发队伍和公司。从这点看,Pair Programming不仅仅适用于XP,也适用于所有其它的软件开发 <br />方法。 <br /><br />•&nbsp; 测试驱动开发 <br /><br />反馈是XP的四个基本的价值观之一——在软件开发中,只有通过充分的测试才能获得充分的反馈。XP中 <br />提出的测试,在其它软件开发方法中都可以见到,比如功能测试、单元测试、系统测试和负荷测试等; <br />与众不同的是,XP将测试结合到它独特的螺旋式增量型开发过程中,测试随着项目的进展而不断积累。 <br />另外,由于强调整个开发小组拥有代码,测试也是由大家共同维护的。即,任何人在往代码库中放程序 <br />(Check In)前,都应该运行一遍所有的测试;任何人如果发现了一个BUG,都应该立即为这个BUG增加 <br />一个测试,而不是等待写那个程序的人来完成;任何人接手其他人的任务,或者修改其他人的代码和设 <br />计,改动完以后如果能通过所有测试,就证明他的工作没有破坏愿系统。这样,测试才能真正起到帮助 <br />获得反馈的作用;而且,通过不断地优先编写和累积,测试应该可以基本覆盖全部的客户和开发需求, <br />因此开发人员和客户可以得到尽可能充足的反馈。 <br /><br />•&nbsp; 重整和优化 (Refactoring) <br /><br />XP强调简单的设计,但简单的设计并不是没有设计的流水帐式的程序,也不是没有结构、缺乏重用性的 <br />程序设计。开发人员虽然对每个USER STORY都进行简单设计,但同时也在不断地对设计进行改进,这个 <br />过程叫设计的重整和优化(Refactoring)。这个名字最早出现在Martin Fowler写的《Refactoring:&nbsp; <br />Improving the Design of Existing Code》这本书中。 <br /><br />Refactoring主要是努力减少程序和设计中重复出现的部分,增强程序和设计的可重用性。Refactoring <br />的概念并不是XP首创的,它已经被提出了近30年了,而且一直被认为是高质量的代码的特点之一。但XP <br />强调,把Refactoring做到极致,应该随时随地、尽可能地进行Refactoring,只要有可能,程序员都不 <br />应该心疼以前写的程序,而要毫不留情地改进程序。当然,每次改动后,程序员都应该运行测试程序, <br />保证新系统仍然符合预定的要求。 <br /><br />4 频繁地整合,集体拥有代码(Collective Code Ownership),编程规范 <br /><br />XP开发小组经常整合不同的模块。为了提高软件质量,除了测试驱动开发和Pair Programming以外,XP <br />要求每个人的代码都要遵守编程规范,任何人都可以修改其他人写的代码,而且所有人都应该主动检查 <br />其他人写的代码。 <br /><br />•&nbsp; 频繁地整合 (Integration ) <br /><br />在很多项目中,开发人员往往很迟才把各个模块整合在一起。在这些项目中,开发人员经常在整合过程 <br />中发现很多问题,但不能肯定到底是谁的程序出了问题;而且,只有整合完成后,开发人员才开始稍稍 <br />使用整个系统,然后就马上交付给客户验收。对于客户来说,即使这些系统能够通过终验收测试,因为 <br />使用时间短,客户门心里并没有多少把握。 <br /><br />为了解决这些问题,XP提出,整个项目过程中,应该频繁地,尽可能地整合已经开发完的USER STORY <br />(每次整合一个新的USER STORY)。每次整合,都要运行相应的单元测试和验收测试,保证符合客户和 <br />开发的要求。整合后,就发布一个新的应用系统。这样,整个项目开发过程中,几乎每隔一两天,都会 <br />发布一个新系统,有时甚至会一天发布好几个版本。通过这个过程,客户能非常清楚地掌握已经完成的 <br />功能和开发进度,并基于这些情况和开发人员进行有效地、及时地交流,以确保项目顺利完成。 <br /><br />•&nbsp; 集体拥有代码(Collective Code Ownership) <br /><br />在很多项目开发过程中,开发人员只维护自己的代码,而且很多人不喜欢其他人随意修改自己的代码。 <br />因此,即使可能有相应的比较详细的开发文档,但一个程序员却很少、也不太愿意去读其他程序员的代 <br />码;而且,因为不清楚其他人的程序到底实现了什么功能,一个程序员一般也不敢随便改动其他人的代 <br />码。同时,因为是自己维护自己的代码,可能因为时间紧张或技术水平的局限性,某些问题一直不能被 <br />发现或得到比较好的解决。针对这点,XP提倡大家共同拥有代码,每个人都有权利和义务阅读其他代 <br />码,发现和纠正错误,重整和优化代码。这样,这些代码就不仅仅是一两个人写的,而是由整个项目开 <br />发队伍共同完成的,错误会减少很多,重用性会尽可能地得到提高,代码质量是非常好。 <br /><br />为了防止修改其他人的代码而引起系统崩溃,每个人在修改后都应该运行测试程序。(从这点,我们可 <br />以再次看到,XP的各个惯例和规则是怎样有机地结合在一起的。) <br /><br />•&nbsp; 编程规范 <br /><br />XP开发小组中的所有人都遵循一个统一的编程标准,因此,所有的代码看起来好像是一个人写的。因为 <br />有了统一的编程规范,每个程序员更加容易读懂其他人写的代码,这是是实现Collective Code&nbsp; <br />Ownership的重要前提之一。 <br /><br />5 Metaphor(系统比喻),不加班 <br /><br />XP过程通过使用一些形象的比喻让所有人对系统有个共同的、简洁的认识。XP认为加班是不正常的,因 <br />为这说明关于项目进度的估计和安排有问题。&nbsp; <br /><br />•&nbsp; Metaphor(系统比喻) <br /><br />为了帮助每个人一致清楚地理解要完成的客户需求、要开发的系统功能,XP开发小组用很多形象的比喻 <br />来描述系统或功能模块是怎样工作的。比如,对于一个搜索引擎,它的Metaphor可能就是“一大群蜘 <br />蛛,在网上四处寻找要捕捉的东西,然后把东西带回巢穴。” <br /><br />•&nbsp; 不加班 <br /><br />大量的加班意味着原来的计划是不准确的,或者是程序远不清楚自己到底什么时候能完成什么工作。而 <br />且,开发管理人员和客户也因此无法准确掌握开发速度;开发人员也因此非常疲劳。XP认为,如果出现 <br />大量的加班现象,开发管理人员(比如Coach)应该和客户一起确定加班的原因,并及时调整项目计 <br />划、进度和资源。 <br /><!--QuoteEnd--></div><!--QuoteEEnd-->

2004-3-22 10:16 99大话王
什么是Extreme Programming(完)<br /><!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->XP中一些基本概念的简介 <br /><br />User Story:开发人员要求客户把所有的需求写成一个个独立的小故事,每个只需要几天时间就可以完 <br />成。开发过程中,客户可以随时提出新的User Story,或者更改以前的User Story。 <br /><br />Story Estimates和开发速度:开发小组对每个User Story进行估算,并根据每个开发周期 <br />(Iteration)中的实际情况反复计算开发速度。这样,开发人员和客户能知道每个星期到底能开发多 <br />少User Story。 <br /><br />Release Plan和Release Scope:整个开发过程中,开发人员将不断地发布新版本。开发人员和客户一 <br />起确定每个发布所包含的User Story。 <br /><br />Iteration(开发周期)和Iteration Plan:在一个Release过程中,开发人员要求客户选择最有价值的 <br />User Story作为未来一两个星期的开发内容。 <br /><br />The Seed:第一个开发周期(Iteration)完成后,提交给客户的系统。虽然这不是最终的产品,但它 <br />已经实现了几个客户认为是最重要的Story,开发人员将逐步在其基础上增加新的模块。 <br /><br />Continuous Integration(整合):把开发完的User Story的模块一个个拼装起来,一步步接近乃至最 <br />终完成最终产品。 <br /><br />验收测试(功能测试):对于每个User Story,客户将定义一些测试案例,开发人员将使运行这些测试 <br />案例的过程自动化。 <br /><br />Unit Test(单元测试):在开始写程序前,程序员针对大部分类的方法,先写出相应的测试程序。 <br /><br />Refactoring (重整和优化) :去掉代码中的冗余部分,增加代码的可重用性和伸缩性。&nbsp; <br /><br /><br /><br />小结 <br /><br />XP的一个成功因素是重视客户的反馈——开发的目的就是为了满足客户的需要。XP方法使开发人员始终 <br />都能自信地面对客户需求的变化。XP强调团队合作,经理、客户和开发人员都是开发团队中的一员。团 <br />队通过相互之间的充分交流和合作,使用XP这种简单但有效的方式,努力开发出高质量的软件。XP的设 <br />计简单而高效;程序员们通过测试获得客户反馈,并根据变化修改代码和设计,他们总是争取尽可能早 <br />地将软件交付给客户。XP程序员能够勇于面对需求和技术上的变化。 <br /><br />XP很象一个由很多小块拼起来的智力拼图,单独看每一小块都没有什么意义,但拼装好后,一幅美丽的 <br />图画就会呈现在你面前。&nbsp; <!--QuoteEnd--></div><!--QuoteEEnd-->

2004-3-22 10:25 99大话王
什么样人适合XP?<br />charles 2002.05.03<br /><!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->Extreme programming还要挑人,还有种族歧视?&nbsp; <br />&nbsp; &nbsp; 答案是“对” 也 “不对”。Extreme programming当然没有歧视任何人的,任何人都可以去尝试&nbsp; <br />和使用XP。可不幸的是,使用XP确实不是所有人都可以做的到,它对实施的和参与的程序员都提出了更 <br />高的要求。这种要求不是技术水平,也不是学历水平,水平不高的程序员一样可以XP,甚至可以是一很 <br />好的XP programmer。这种要求是对一个人的心智,道德,修养的更高要求(有点儿修道的样子哦)。&nbsp; <br />&nbsp; &nbsp; 一个XP programmer应该具备这样一些基本素质:诚实,公正,坦诚,open-minded,勇敢。&nbsp; <br />在这些素质的基础上,才是对技术水平,能力和天分等的要求。&nbsp; <br />&nbsp; &nbsp; 让我们一起来看一下为什么XP要要求这些基本素质。&nbsp; <br />&nbsp; &nbsp; 诚实:诚实其实是一个Programmeer的最基本要求,不管是XP还是传统或其他方法。在XP的项目计&nbsp; <br />划阶段,要求程序员能准确的估计一个Task的开发时间(小时为单位),在开发阶段,则要求程序员能 <br />根据自己的开发进度估计剩余的时间并汇报给Tracker。所有这些估计都是很主观的东西。而恰恰这些&nbsp; <br />准确的估计构成了XP规划的基础。如果程序员不能根据自己的能力做出准确诚实的估计,不但会影响自 <br />己,更重要是对整个Team和项目的损害。比如说如果一个程序员为了显示自己的能力,可能低估了Task <br />开发时间。或是在开发中为了面子而没能及时汇报Delay。当然XP的本身有针对的解决方法(Pair <br />programming),但是对诚实的要求仍然是必须的。&nbsp; <br />&nbsp; &nbsp; 公正:XP Team是一个紧密的团体,而group planning和pair programming都会有很多的意见的碰&nbsp; <br />撞。XP programmer必须能客观公正的看待问题。&nbsp; <br />&nbsp; &nbsp; 坦诚和Open-minded:XP的group planning,group design,pair programming, code review等都使 <br />个人的知识水平的不足或失误暴露出来。如果别人当面指出你的设计失误或编码错误,XP程序员需要能 <br />很坦率个开明的去看待别人的批评和自己的缺陷。我想我们在工作中也会遇到这种情况,一个人对别人 <br />的批评最基本的反映就是防卫和反击。很多时候这种放应不是建立在对和错的基础上,而是个人自尊。 <br />XP的解决方法是Colletive ownership,代码所有权共享。整个Team的所有程序员对所有的Code都有编&nbsp; <br />写和维护的权利和责任。尽管如此,坦诚和开明还是Team work的基本之一。其实这也就人和人的相处&nbsp; <br />之道:就事论事。一个XP programmer应该也必须能做到这点。&nbsp; <br />&nbsp; &nbsp; 勇敢:XP的开发是完全的Team work。在设计上和编码上采用的是也是team plannig 和 team&nbsp;&nbsp; <br />design。XP programmer因该主动勇敢的提出自己的意见,也需要能对Team lead或高级别程序员的设计 <br />提出疑问。在以往的环境中,往往是高级人员作出决定由其他人执行。如果有人有意见通常也很难提出 <br />不同意见,比如说你可能不会或不能够对System Architect的设计提出疑问因为他是高级人员和拥有独 <br />立的办公室。虽然很动公司提倡提意见,但是往往公司的氛围和文化或制度(系统设计师设计然后程序 <br />员编码)已经建立起一个无形的屏障。&nbsp; <!--QuoteEnd--></div><!--QuoteEEnd-->

2004-3-22 10:27 99大话王
XP中的用户需求分析<br />Planning Game 和 User Story —— 概述<br />waltson 2002.05.03<br /><!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->&nbsp; &nbsp; &nbsp; &nbsp; Extreme Programming 中的需求分析,是通过Planning Game 完成的。虽然我们从Planning&nbsp; <br />Game开始,讨论Extreme Project的具体过程,但实际上,Planning Game中的一些阶段几乎贯穿了项目 <br />开发的始终。(用Game这个词,可以让大家的心理放松些。) <br /><br />&nbsp; &nbsp; &nbsp; &nbsp; 做计划,是一件说起来容易做起来难的事情。做计划时,程序员考虑的是怎么样编程更快;项 <br />目经理考虑的是到底程序员多久才能做完这些事情;客户考虑的是多久时间后拿到多少东西……一开始 <br />就全面考虑这些问题当然没有什么不对,但计划和任何事情一样,都是一步步完成的。 <br /><br />Planning Game 分为三个阶段,探测、计划和调整。 <br /><br />探测阶段:客户和开发人员一起把需求分解成很多小的,可估算的部分。 <br />计划阶段:客户和开发人员一起制订发布计划。 <br />调整阶段:客户和开发人员一起,在开发过程中,根据实际情况,及时调整原有的计划或者制订新计 <br />划。 <br /><br />象所有的棋牌游戏一样,XP的Planning Game有它的牌(棋)、目标、玩家和游戏规则。 <br /><br />牌(棋):Planning Game中的牌(棋)是User Story。每个User Story都是一个很小的用户需求;经 <br />常是几个词或者一、两句话。每个User Story都写在一个卡片上,卡片上列出了它的商业价值和开发成 <br />本。因为一个User Story的商业价值与开发成本可能和另一个User Story的取舍密切相关,所以这些卡 <br />片有时候看起来比较复杂。 <br /><br />目标:如果我们把产品比作一个盒子,那么游戏的目标就是,在游戏结束时,使盒子中的Story卡上的 <br />商业价值总和尽可能地最大。 <br /><br />玩家:客户和开发人员。 <br /><br />游戏规则: <br /><br />写Story:游戏中的任何时候都可以将一个新的用户需求写成一个Story。每个Story除了包含它的商业 <br />价值(客户眼中的优先级)外,还有足够的内容以便开发人员估计开发成本。 <br /><br />估计Story:开发人员估计每个Story的理想开发周。如果大于2周,则应该把该Story分解(这个分解过 <br />程,可能会导致多个Iteration。)。如果估计开发时间很短(比如半个小时),则可以考虑在适当时 <br />候把它和另一个Story合并。 <br /><br />制订发布(Release)计划:客户和开发人员一起,决定哪些Story是这一次发布要完成的,哪些是下一 <br />次发布时要完成的,什么时候交付产品,产品应该包括哪些Story。制订发布计划时有两种出发点,基 <br />于Story和基于时间。 <br /><br />基于Story:客户把一些Story卡归为下一个发布计划要完成的内容。每放一张卡,客户描述这个Story <br />的内容,开发人员估算这个Story的开发时间和发布日期。 <br /><br />基于时间:客户指定了一个交付日期或者发布日期。开发人员估算从现在到那个日期之间,可以完成多 <br />少工作(多少个理想工作周),然后由客户来选择要完成哪些Story,所有选中的Story的总开发时间应 <br />该小于开发人员估算的理想工作周总数。 <br />商业价值和开发风险优先:尽量将商业价值高的Story安排在早期计划中(商业价值优先);尽量将高 <br />开发风险的Story安排在早期计划中(开发风险优先)。开发人员将Story排列后,应该可以承诺在几个 <br />星期内,给客户一个可工作的,但是比较粗略的系统。 <br /><br />纠正估算:比如,开发人员以前估计可以在交付日期之前完成20个Story,但是开发过程中,通过不断 <br />地计算开发速度和重新评估,发现只能完成15个Story。客户就从原来的20个Story中挑选5个放到下一 <br />期开发中。(有时候,客户也有可能为得到所有的Story而延迟交付日期。) <br /><br />更正商业价值:客户可以随时更改每个Story的商业价值(优先级)。相应地,开发人员根据这些更改 <br />调整Story的开发次序。 <br /><br />引入一个新Story:客户可以随时加入一个新Story。开发人员要估算开发成本和风险。如果客户要求在 <br />这次开发中完成这个Story,开发人员要和客户一起,按照商业价值和开发风险优先的原则,重新估算 <br />相关的Story。 <br /><br />分解一个Story:客户把一个大的或复杂的Story分解成两个或更多的小Story。客户要估计每个分解后 <br />得到的Story的商业价值;开发人员要估算开发成本。分解Story,通常是因为这个Story不可能在短期 <br />内由少数人完成。 <br /><br />Spike:客户可以让开发人员集中资源,用很短的时间(可能是两、三天)来证明一个想法的可行性或 <br />应付一个紧急情况(比如恢复数据)。如果这个需求比较复杂(不是打个小补丁),用户应该把它写成 <br />一个Story。这个Story也应该按照商业价值和开发风险优先的原则被评估。Spike通常都是会影响开发 <br />速度的。 <br /><br />重新估算:开发完一个Story后,开发人员重新估计剩下的Story,可能会发现以前过高估算了自己的开 <br />发能力,也有可能发现开发时间可以缩短。 <!--QuoteEnd--></div><!--QuoteEEnd-->

2004-3-22 10:30 99大话王
Martin Fowler的设计已死中文版<br /><!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->设计已死?<br />英文原文版权由Martin Fowler拥有<br />Original text is copyrighted by Martin Fowler<br /><br />Martin Fowler<br />Chief Scientist, ThoughtWorks<br /><br />原文出处| 繁体版 | 译者:Daimler Huang<br /><br />对很多粗略接触到 Extreme Programming 的人来说,XP 似乎 宣告了软件设计的死刑。不只很多的设计被嘲笑为 &quot;Big Up Front Design&quot;[译注1],连很多技术像UML、富有弹性的程序架构 (framework),甚至连模式 (pattern) 都不受重视,或是近似忽略了。事实上,XP内含很多设计理念,但是它与现有的软件流程有着不同的运作方式。XP藉由多种实务技巧 (practice) 赋予演进式设计 (evolutionary design) 崭新的风貌,让演进变成一种实用的设计方法。它也让设计者 (designer[译注2]) 面临新的挑战与技巧,学习如何使设计精简,如何使用重构来保持一个设计的清楚易懂,以及如何逐步地套用模式。<br /><br />(这篇文章是我在 XP2000 研讨会发表的演说,它会公布在研讨会讲义中。)<br /><br />&nbsp; &nbsp; &nbsp; Planned and Evolutionary Design (经过规划的设计与演进式的设计)<br /><br />&nbsp; &nbsp; &nbsp; The Enabling Practices of XP (XP有效的实作技巧)<br /><br />&nbsp; &nbsp; &nbsp; The value of Simplicity (简单的价值)<br /><br />&nbsp; &nbsp; &nbsp; What on Earth is Simplicity Anyway (究竟什么是简单)<br /><br />&nbsp; &nbsp; &nbsp; Does Refactoring Violate YAGNI? (重构违反了YAGNI吗?)<br /><br />&nbsp; &nbsp; &nbsp; Patterns and XP (模式与XP)<br /><br />&nbsp; &nbsp; &nbsp; Growing an Architecture (发展结构)<br /><br />&nbsp; &nbsp; &nbsp; UML and XP (UML与XP)<br /><br />&nbsp; &nbsp; &nbsp; On Metaphor (关于隐喻)<br /><br />&nbsp; &nbsp; &nbsp; Do you wanna be an Architect when you grow up? (你将来想成为一个软件结构师吗?)<br /><br />&nbsp; &nbsp; &nbsp; Things that are difficult to refactor in (很难重构的东西)<br /><br />&nbsp; &nbsp; &nbsp; So is Design Dead? (所以,设计死了吗?)<br /><br />&nbsp; &nbsp; &nbsp; Acknowledgements (致谢)<br /><br />&nbsp; &nbsp;&nbsp; Revision History (修订的记录)<br /><br />Extreme Programming (XP) 挑战很多软件开发常见的假设。其中最受争议的就是极力排斥 up-front design,而支持一种比较属于演进的方式。批评者说这是退回到了 &quot;code and fix&quot; 的开发方式,顶多只能算是一般急就章的程序设计罢了。支持者也常看到 XP 对于设计方法 (如 UML)、principle(设计准则)、patterns 等的排斥。别担心,仔细注意你的程序代码,你就会看到好的 design 浮现出来。<br /><br />我发现自己正陷于这个争论当中。我的工作着重在图形化设计语言 - UML 以及 patterns,事实上我也写过 UML 和 patterns 的书。我如此的拥抱 XP 是否表示我放弃了这些理论,或是将这些反渐进式 (counter-revolutionary) 的概念从脑中清除了?<br /><br />嗯... 我不想让你的心悬荡在这两种情境中。简单的说并不是;接下来的文章就让我来详细说明。<br /><br /> <br /><br />Planned and Evolutionary Design<br /><br /> <br /><br />我将在这篇文章中说明软件开发的两种设计方式是如何完成的。或许最常见的是演进式设计。它的本质是系统的设计随着软件开发的过程增长。设计 (design) 是撰写程序代码过程的一部份,随着程序代码的发展,设计也跟着调整。<br /><br />在常见的使用中,演进式设计实在是彻底的失败。设计的结果其实是一堆为了某些特殊条件而巧妙安排的决定所组成,每个条件都会让程序代码更难修改。从很多方面来看,你可能会批评这样根本就没有设计可言,无疑地这样的方式常会导致很差劲的设计。根据Kent的陈述,所谓的设计 (design) 是要能够让你可以长期很简单地修改软件。当设计 (design) 不如预期时,你应该能够做有效的更改。一段时间之后,设计变得越来越糟,你也体会到这个软件混乱的程度。这样的情形不仅使得软件本身难以修改,也容易产生难以追踪和彻底解决的 bug。随着计画的进行,bug 的数量呈指数地成长而必须花更多成本去解决,这就是 &quot;code and fix&quot; 的恶梦。<br /><br />Planned Design 的做法正好相反,并且含有取自其它工程的概念。如果你打算做一间狗屋,你只需要找齐木料以及在心中有一个大略的形象。但是如果你想要建一栋摩天大楼,照同样的做法,恐怕还不到一半的高度大楼就垮了。于是你先在一间像我太太在波士顿市区那样的办公室里完成工程图。她在设计图中确定所有的细节,一部份使用数学分析,但是大部分都是使用建筑规范。所谓的建筑规范就是根据成功的经验 (有些是数学分析) 制定出如何设计结构体的法则。当设计图完成,她们公司就可以将设计图交给另一个施工的公司按图施工。<br /><br />Planned Design 将同样的方式应用在软件开发。Designer 先定出重要的部份,程序代码不是由他们来撰写,因为软件并不是他们 &quot;建造[译注3]&quot; 的,他们只负责设计。所以 designer 可以利用像 UML 这样的技术,不需要太注重撰写程序代码的细节问题,而在一个比较属于抽象的层次上工作。一旦设计的部份完成了,他们就可以将它交给另一个团队 (或甚至是另一家公司) 去 &quot;建造&quot;。因为 designer 朝着大方向思考,所以他们能够避免因为策略方面不断的更改而导致软件的失序。Programmer 就可以依循设计好的方向 (如果有遵循设计) 写出好的系统。<br /><br />Planned design 方法从七○年代出现,而且很多人都用过它了。在很多方面它比 code and fix 渐进式设计要来的好,但是它也有一些缺点存在。第一个缺点是当你在撰写程序代码时,你不可能同时把所有必须处理的问题都想清楚。所以将无可避免的遇到一些让人对原先设计产生质疑的问题。可是如果 designer 在完成工作之后就转移到其它项目,那怎么办?Programmer 开始迁就设计来写程序,于是软件开始趋于混乱。就算找到 designer,花时间整理设计,变更设计图,然后修改程序代码。但是必须面临更短的时程以及更大的压力来修改问题,又是混乱的开端。<br /><br />此外,通常还有软件开发文化方面的问题。Designer 因为专精的技术和丰富的经验而成为一位 designer。然而,他们忙于从事设计而没有时间写程序代码。但是,开发软件的工具发展迅速,当你不再撰写程序代码时,你不只是错失了技术潮流所发生的改变,同时也失去了对于那些实际撰写程序代码的人的尊敬。<br /><br />建造者 (builder[译注3]) 和设计者之间这种微妙的关系在建筑界也看得到,只是在软件界更加凸显而已。之所以会如此强烈是因为一个关键性的差异。在建筑界,设计师和工程师的技术有清楚的分野;在软件界就比较分不清楚了[译注2]。任何在高度注重 design 的环境工作的 programmer 都必须具备良好的技术,他的能力足够对 designer 的设计提出质疑,尤其是当 designer 对于新的发展工具或平台越来越不熟悉的状况下。<br /><br />现在这些问题也许可以获得解决。也许我们可以处理人与人之间的互动问题。也许我们可以加强 designer 的技术来处理绝大部份的问题,并且订出一个依照准则去做就足够改变设计图的流程。但是仍然有另外一个问题:变更需求。变更需求是软件项目中最让我感到头痛的问题了。<br /><br />处理变更需求的方式之一是做有弹性的设计,于是当需求有所更改,你就可以轻易的变更设计。然而,这是需要先见之明去猜测将来你可能会做怎样的变更。一项预留处理易变性质的设计可能对于将来的需求变更有所帮助,但是对于意外的变化却没有帮助 (甚至有害)。所以你必须对于需求有足够的了解以隔离易变的部份。照我的观察,这是非常困难的。<br /><br />部份有关需求的问题应该归咎于对需求的了解不够清楚,所以有人专注于研究需求处理,希望得到适切的需求以避免后来对设计的修改。但是即使朝这个方向去做一样无法对症下药。很多无法预料的变更起因于瞬息万变的商场,你只有更加小心处理需求问题来应付无法避免的情况。<br /><br />这么说来,planned design 听起来像是不可能的任务。这种做法当然是一种很大的挑战。但是,跟演进式设计 (evolutionary design) 普遍以 code and fix 方式实作比较起来,我不觉得 planned design 会比较差。事实上,我也比较喜欢 planned design。因为我了解 planned design 的缺点,而且正在寻找更好的方法。<br /><br /> <br /><br />The Enabling Practices of XP<br /><br /> <br /><br />XP 因为许多原因而备受争议,其中之一就是它主张演进式设计 (evolutionary design) 而不是 planned design。我们也知道,演进式设计可能因为特定的设计或是软件开发趋于混乱而行不通。<br /><br />想了解这些争论的核心,就是软件研发异动曲线。曲线的变化说明,随着项目的进行,变更所需要的成本呈现指数的增加。这样的曲线常以一句话来表示:在分析阶段花一块钱所作的变更,发行之后要花数千元来补救。讽刺的是大部分的计画仍然没有分析过程而以非标准的方式进行,但是这种成本上的指数关系还是存在着。这种指数曲线意味着演进式设计可能行不通,它同时也说明着为什么 planned design 要小心翼翼地规划,因为任何的错误还是会面对同样的问题。<br /><br />XP 的基本假设是它可以将这种指数曲线拉平,这样演进式设计就行得通了。XP 使曲线更平缓并能运用这种优势。这是因为 XP 实作技巧之间的耦合效果:换句话说,不使用那些能够拉平软件开发曲线的实作技巧来工作,这条曲线也不会趋向平缓。这也是争论的来源,因为评论家不了解这其间的关系。通常这些批评是根据评论家自身的经验,他们并没有实行那些有效的实作技巧,当他们看到结果不如预期,对于 XP 的印象也就是这样了。<br /><br />这些有效的实作技巧有几个部份,主要是 Testing 和 Continuous Integration。如果没有 testing 提供保障,其它的 XP 实作技巧都不可行。Continuous Integration 可以保持团队成员信息同步,所以当你有改变的部份,不必担心与其它成员资料整合会有问题。同时运用这些实作技巧能够大大影响开发曲线。这让我再次想起在ThoughtWorks 导入 testing 和 continuous integration 之后,明显的改善了研发成果。改善的程度好到令人怀疑是不是像 XP 所主张的,必须要用到所有的实作技巧才能大幅改善效率。[译注4]<br /><br />Refactoring 具有类似的成效。那些曾经采用 XP 建议的原则来对程序代码进行refactoring 的人发现,这么做要比无章法或是特殊方式的 restructuring 明显的更有效率。那也曾经是 Kent 指导我适当的 refactor 得到的难忘经验,也因为这么一次巨大的转变促使我以这个主题写了一本书。<br /><br />Jim Highsmith 写了一篇很棒的文章 &quot;summary of XP&quot;,他把 planned design 和 refactoring 放在天秤的两端。大部份传统的做法假设构想不变,所以 planned design 占优势。而当你的成本越来越不允许变更,你就越倾向于采用 refactoring。Planned design 并不是完全消失,只是将这两种做法互相搭配运用取得平衡。对我来说,在设计进行 refactoring 之前,总觉得这个设计不够健全。<br /><br />Continuous integration、testing 和 refactoring 这些有效的实作方法让 evolutionary design 看似很有道理。但是我们尚未找出其间的平衡点。我相信,不论外界对 XP 存有什么印象,XP 不仅仅是 testing、coding 和 refactoring。在 coding 之前还有 design 的必要。部份的 design 在 coding 之前准备,大部份的 design 则发生在实作每一项详列的功能之前。总之,在 up-front design 和 refactoring 之间可以找到新的平衡。<br /><br /> <br /><br />The value of Simplicity<br /><br /> <br /><br />XP 大声疾呼的两个口号是 &quot;Do The Simplest Thing that Could Possibly Work&quot;(只做最简单可以正常运作的设计) 和 &quot;You Aren&#39;t Going to Need It&quot;(就是 YAGNI - 你将不会需要它)。两项都是XP实务中简单设计的表现形式。<br /><br />YAGNI 一词时常被讨论,它的意思是现在不要为了将来可能用到的功能加入任何程序代码。表面上听起来好象很简单,问题则出在像 framework、重用组件、和弹性化设计,这些东西本来就很复杂。你事先付出额外的成本去打造它们,希望稍后将这些花费都赚回来。这个事先弹性设计的想法被认为是软件设计有效率的关键部份。<br /><br />但XP的建议是,在处理第一个问题时不要因为可能需要某项功能,就建造出弹性的组件组及框架出来。让整体结构随着需要成长。假如我今天想要一个可以处理加法但是不用乘法的 Money 类别,我就只在 Money 类别中建造加法的功能。就算我确定下一个阶段也需要乘法的运算,而且我知道很简单,也花不了多少时间,我还是会留到下一阶段再去做它。<br /><br />其中一个理由是效益。如果我要花时间在明天才需要的功能,那就表示我没有将精神放在这个阶段应该完成的事情上。发表计画详列目前要完成的事项,现在做以后才需要的事情违背开发人员和顾客之间的协议。这种做法有让现阶段的目标无法达成的可能。而且这个阶段的 stroies[译注5] 是否具有风险,或是需不需要做额外的工作,都是由顾客来决定的 - 还是可能不包括乘法功能。<br /><br />这种经济效益上的限制是因为我们有可能出错。就算是我们已经确定这个功能应该如何运作,都有可能出错 - 尤其是这时候我们还没有取得详细需求。提前做一件错误的事情比提前做一件对的事情更浪费时间。而且XP专家们通常相信我们比较有可能会做错而不是做对(我心有戚戚)。<br /><br />第二个支持 simple design 的理由是复杂的设计违反光线行进的原理。复杂的设计比简单的设计还要令人难懂。所以随着渐增的系统复杂度,更加难以对系统做任何修改。如此,若系统必须加入更复杂的设计时,成本势必增加。<br /><br />现在很多人发现这样的建议是无意义的,其实他们那样想是对的。因为你所想象一般的研发并没有被 XP 有效的技巧所取代。然而,当规划式设计和渐进式设计之间的平衡点有了变化 (也只有当这样的变化发生时),YAGNI 就会变成好的技巧。<br /><br />所以结论是,除非到了往后的阶段有所需要,否则你不会浪费精神去增加新的功能。即使不会多花成本,你也不会这样做,因为就算现在加入这些功能并不增加成本,但是却会增加将来做修改时的成本。总之,你可以在套用 XP 时明智的遵守这样的方法,或是采取一种能降低成本的类似的方法。<br /><br /> <br /><br />What on Earth is Simplicity Anyway<br /><br /> <br /><br />因此,我们希望程序代码能够越简单越好,这听起来没什么好争论的,毕竟有谁想要复杂呢?但问题来了,究竟 &quot;什么才叫简单呢?&quot;<br /><br />在 XPE 一书中,Kent 对简单系统订了四个评量标准,依序是 (最重要排最前面):<br /><br />通过所有测试。<br /><br />呈现所有的意图。<br /><br />避免重复。<br /><br />最少数量的类别或方法。<br /><br /> 通过所有测试是一项很普通的评量标准,避免重复也很明确,尽管有些研发人员需要别人的指点才能做到。比较麻烦的是 &quot;呈现所有的意图&quot;这一项,这到底指的是什么呢?<br /><br /> 这句话的本意就是简单明了的程序代码。XP 对程序代码的易读性有很高的标准。虽然在 XP 当中,&quot;巧妙的程序代码 (clever code)&quot; 这个字眼经常被滥用,不过意图清楚的程序代码,对其他人来说真的是一种巧妙。Josh Kerievsky 在 XP 2000 论文中举了一个很好的例子,检视在 XP 领域可能是大家最熟知的 JUnit 的程序代码。JUnit 使用 decorators 在 test cases 中加入非必要的功能,像是同步机制及批次设定等,将这些程序代码抽出成为 decorator,的确让一般的程序代码看起来清楚许多。<br /><br /> 但是你必须扪心自问,这样做之后的程序代码够简单吗?我觉得是,因为我了解 Decorator 这个 patterns。但是对于不了解的人来说还是相当复杂的。类似的情况,JUnit 使用 pluggable method,一种大部分的人刚开始接触时都不会觉得简单的技巧。所以,也许我们可以说 JUnit 对有经验的人来说是比较简单的,新手反而会觉得它很复杂。<br /><br /> XP 的 &quot;Once and Only Once&quot; 以及 Pragmatic Programmer(书名) 的 DRY(Don&#39;t Repeat Yourself) 都专注在去除重复的程序代码。这些良好的建议都有很显著而且惊人的效果。只要依照这个方式,项目就可以一路顺利的运作。但是它也不能解决所有问题,简单化还是不容易达成。<br /><br /> 最近我参与一个可能是过度设计的项目,系统经过 refactor 之后去除部份弹性的设计。但是就像其中一位开发者所说的 &quot;重构过度设计的系统要比重构没有设计的要来的容易多了&quot; 做一个比你所需要简单一点的设计是最好的,但是,稍微复杂一点点也不是什么严重的事情。<br /><br />我听过最好的建议来自 Bob 大叔 (Robert Martin)。他的建议是不要太在意什么是最简单的设计。毕竟后来你可以,应该,也会再重构。愿意在最后重构,比知道如何做简单的设计重要得多。<br /><br /> <br /><br />Does Refactoring Violate YAGNI?<br /><br /> <br /><br />这个主题最近出现在 XP 讨论区上,当我们审视设计在 XP 扮演的角色时,我觉得很值得提出来讨论。<br /><br />基本上这个问题起因于重构需要耗费时间却没有增加新的功能。而 YAGNI 的观点是假设你为了眼前的需要做设计而不是未来,这样算是互相抵触吗?<br /><br />YAGNI 的观点是不要增加一些现阶段不需要的复杂功能,这也是简单设计这项技巧的部份精神。重构也是为了满足尽可能保持系统的简单性这个需要,所以当你觉得可以让系统变得更简单的时候,就进行重构。<br /><br />简单设计不但利用了 XP 的实务技巧,本身也是其中一项有用的实务技巧。唯有伴随着测试,持续整合,及重构的运用,才能有效地做出简单设计。同时,让研发异动曲线保持平缓的基础也就是保持设计的简单。任何不必要的复杂都会让系统变得难于调整,除非这个复杂性是你为了所预测的弹性而加入的。不过,人们的预测通常都不太准确,所以最好还是努力地保持简单性。<br /><br />不管怎样,人们不太可能第一次就能够获得最简单的东西,因此你需要重构来帮助你更接近这个目标。<br /><br /> <br /><br />Patterns and XP<br /><br /> <br /><br />JUnit 的例子让我不得不想到 patterns。XP 和 patterns 之间的关系很微妙,也常常被问起。Joshua Kerievsky 认为 patterns 在 XP 被过分轻视,而且他所提出的理由也相当令人信服,我不想再重提。不过值得一提的是,很多人都认为 patterns 似乎与 XP 是有冲突的。<br /><br /> 争论的本质在于 patterns 常被过度滥用。世上有太多传奇性的 programmer,第一次读到四人帮以 32 行程序代码阐述 16 种 patterns 这样的事情还记忆犹新[译注6]。我还记得有一晚与 Kent 喝着醇酒一起讨论一篇文章 &quot;Not Design patterns: 23 cheap tricks (不要用设计模式-23 个简单的诀窍)&quot;。我们认为那不过是以 if 条件式来取代 strategy 这个 pattern 罢了。这样的笑话有个重点,patterns 被滥用了。但并不表示 patterns 是不足取的,问题在于你要怎么运用它。<br /><br />其中一项论点是简单设计的力量自然会将项目导向 patterns。很多重构的例子明确地这么做,或者甚至不用重构,你只要遵从简单设计的规则就会发现 patterns,即使你还不知道 patterns 是什么。这样的说法也许是真的,不过它真的是最好的方式吗?当然如果你先对于 patterns 有个大略的了解,或者手边有一本书可以参考,会比自己发明新的 patterns 要好些。当我觉得一个 pattern 快浮现的时候,我必定会去翻翻 GOF 的书。对我来说,有效的设计告诉我们 pattern 值得付出代价去学习-那就是它特有的技术。同样地就像 Joshua 所建议的,我们需要更熟悉于如何逐步地运用 patterns。就这一点而言,XP 只是与一般使用 patterns 的方式不同而已,并没有抹煞它的价值。<br /><br />但是从讨论区一些文章看来,我觉得很多人明显地认为 XP 并不鼓励使用 patterns,尽管 XP 大部分的提倡者也都是之前 patterns 运动的领导者。因为他们看到了不同于 patterns 的观点吗?或是他们已经将 patterns 融入思考而不必再去理解它?我不知道其它人的答案是什么,但是对我来说,patterns 仍然是非常重要的。XP 也许是开发的一种流程,但 patterns 可是设计知识的骨干,不管是哪种流程这些知识都是很有用的。不同的流程使用 patterns 的方式也就不同,XP 强调等到需要时才使用 patterns 以及透过简单的实作逐步导入 patterns。所以 patterns 仍然是一种必须获得的关键知识。<br /><br />我对于采用 XP 的人使用 patterns 的建议:<br /><br />花点时间学习 patterns。<br /><br />留意使用 patterns 的时机 (但是别太早)。<br /><br />留意如何先以最简单的方式使用 patterns,然后再慢慢增加复杂度。<br /><br />如果用了一种 pattern 却觉得没有多大帮助-不用怕,再次把它去掉。<br /><br />我认为XP应该要更加强调学习 patterns。我不确定它要怎么和 XP 的实务技巧搭配,不过相信 Kent 会想出办法来的。<br /><br /> <br /><br />Growing an Architecture<br /><br /> <br /><br />软件架构是指什么呢?对我来说,架构这个字眼代表系统核心组件的概念,也就是难以改变的部份,剩下的都必须建造在这基础上。<br /><br /> 那么当你使用演进式设计时,架构又扮演着什么样的角色呢?XP 的批评者再一次地声称 XP 忽视架构,因为 XP 使用的方法是尽快地写程序,然后相信重构会解决所有设计的问题。很有趣地,他们说得没错,这有可能是 XP 的缺点。无疑地,最积极的 XP 专家-像 Kent Beck, Ron Jeffries, 及 Bob Martin-尽其所能地避免预先结构性的设计。在你知道真的要用到数据库之前,不要加入数据库,先用档案来代替,在之后的阶段再用重构加入数据库。<br /><br /> 我常被认为是一个胆小的 XP 专家,这点我不同意。我认为一个概括性的初始架构有它的用处在。像是一开始要怎么将应用分层,如何与数据库互动 (如果你需要的话),要使用哪种方式去处理网站服务器。<br /><br /> 基本上,我认为这些就是近年来我们所研究的 patterns。尤其当你对 patterns 的认识越深,你就会越熟悉要怎么去善用它们。不过,关键性的差异是在于这些初期架构的决定是可以更改的,只要团队认为他们早期的判断有误时,就应该要有勇气去修正它们。有人跟我讲了一个项目的故事,就在项目快要发表时,决定了不再需要 EJB,并且要将它们从系统中移除。这是一个相当大规模的重构,不过最后还是完成了。这些有效的实务技巧不仅让事情变得可能,而且很值得去做。<br /><br /> 如果以不同的方式来做这件事呢?如果你决定不采用 EJB,将来会难以加入吗?你是否要在试过各种方式却发现依然欠缺什么,然后才使用 EJB?这是一个牵涉很多因素的问题。不使用复杂的组件当然可以增加系统的简单度,而且可以让事情进展比较快,但有时候从系统中抽掉某个部份会比加入它要容易多了。<br /><br /> 所以我建议从评估架构可能的样子开始。假如你看到将会有多个使用者使用到大量的资料,一开始就直接使用数据库。若你看到很复杂的商业逻辑,就套用 domain model。你会怀疑是否偏离简单的特性,这当然不是 YAGNI 的精神。所以你要有所准备,在发现所使用的结构没有帮助时尽快简化你的结构。<br /><br /> <br /><br />UML and XP<br /><br /> <br /><br />在我投身于 XP 领域之后,由于我与 UML 的关系让我遇到一个挥之不去最大的问题:这两者不是不兼容吗?<br /><br /> 当然有些不兼容。XP 显然不重视 diagram。虽然台面上大家对 &quot;好用就用&quot; 有共识,但是实际上却是 &quot;实际上采用 XP 的人不画蓝图&quot;。这种印象因为如 Kent 这些人不习惯作图的现象而强化了。事实上我也从来没看过 Kent 主动使用固定的标记法画下软件蓝图。<br /><br /> 我觉得这种情形来自两个因素,其一是有人觉得软件蓝图有用,而有人不觉得有用。难就难在觉得蓝图有用的人不是真正必须动手做的人,而必须动手做的人却不觉得有其必要性。事实上我们应该接受有人喜欢用,而有人不喜欢用。<br /><br /> 另一种情形是软件蓝图常引人进入繁重的流程中,这些流程耗时费力却不见得有用,甚至还会产生坏处。我认为应该教导人们如何使用蓝图却不落入这样的陷阱,而不是像那些提倡者仅仅消极的说 &quot;必要时才用&quot;。<br /><br /> 所以,我对于有效使用蓝图的建议是:<br /><br /> 首先别忘了你画这些图的目的,主要的价值在于沟通。有效的沟通意味着选择重要的部份而忽略不重要的部份。这样的选择也是有效运用 UML 的关键。不必把全部的 class 都画出来,画出重要的就好。对于每个 class 也只显示关键的 attribute 和 operation,而不是全部显示出来。也不要为所有的 use case 和步骤画循序图... 除非你已经有完整的想象。有一个使用蓝图的通病就是人们通常希望详细完整的把图表现出来。其实程序代码就是提供完整信息的最佳来源,同时程序代码本身也是保持信息同步最简单的方式。因为图形的巨细靡遗就是一目了然的敌人。<br /><br /> 蓝图的用途是在开始撰写程序代码之前探讨设计内容。印象中总是觉得这样的动作在 XP 是不合法的,但并不是这样。很多人都说如果你遇到棘手的问题,就值得先做些设计。但是当你进行设计时:<br /><br />保持简短。<br /><br />不要做得太详细(只挑重要的做)。<br /><br />把结果当作是草图,而不是定案。<br /><br />最后一点值得深入探讨。当你做预先式设计,无可避免的会发现一些错误,而且是在撰写程序代码的时候才发现。如果你适时变更设计,它就不是问题。麻烦的是如果你认定设计已经定案,没有从 coding 过程学到经验而跟着先前的设计将错就错。<br /><br /> 变更设计不代表一定要更改蓝图。画这些蓝图来帮助你了解设计,然后就把图扔开,这么做是非常合理的。这些图能够帮上忙就有它的价值了。它们不必永远存在,最有用的 UML 图形也不会是收藏品。<br /><br /> 不少实行 XP 的人使用 CRC 卡,这与 UML 并不冲突。我常常交互运用 CRC 卡和 UML,我也总是依照手上的工作选择最有用的技巧。UML 图形的另一个用途是持续修订的文件。它一般的形式,就是在 case tool 中看到的模型。最初的想法是留着这样的资料有助于建构系统。事实上却常常没什么用。<br /><br />保持图形的更新太花时间,最后常无法与程序代码同步。<br /><br />它们隐含在 CASE tool 或 thick binder,让人忽略它。<br /><br />所以要希望这种持续修订的文件有用,就从这些看到的问题下手:<br /><br />只用一些改起来不至于让人觉得痛苦的图。<br /><br />把图放在显眼的地方。我喜欢画在墙上,鼓励大家一起动手修改。<br /><br />检讨这些图是不是有人在用,没用的就擦掉。<br /><br />使用 UML 的最后一个问题是文件的交接,像是不同团队的接手。XP 的想法是文件就像说故事,所以文件的价值由顾客来决定。于是 UML 又派上用场,所提供的图形可以帮助沟通。别忘了程序代码本身就蕴含了所有详细的信息,图形的作用只是提供概观以及标示重要的部份。<br /><br /> <br /><br />On Metaphor<br /><br /> <br /><br />好吧,我也许该坦承 - 我一直没有抓住 metaphor 的精神。它有用,而且在 C3 项目中运用得很好,但是并不表示我知道怎么用它,更不用说要解释怎么用了。<br /><br /> XP 实务技巧中的 Metaphor 是建立在 Ward Cunningham&#39;s 为系统命名的做法上。重点是想出一个众所周知的词汇,以这样一个字来比喻整个范畴。这个代表系统的名字会套用在 class 和 method 的命名上。<br /><br /> 我以不同领域的观念性模型,利用 UML 和它的前身与领域专家一起建立了一个命名系统。我发现你必须很小心,你要保持最精简的注释,而且要当心别让技术性的问题不知不觉的影响这个模型。但是一旦你完成这个工作,你就可以为各种领域建立一组词汇,这些词汇是大家都能了解并且可用来与研发人员沟通的。这种模型无法与 class 设计完美的吻合,但是足够给整个领域一个通用的代名词。<br /><br /> 目前我找不到任何理由说明为何这样的一个字汇无法成为一个比喻,就像 C3 这个成功的例子;我也不觉得以系统为主找到在该专业领域的一个词汇有什么坏处。同时我也不会放弃可以运作自如的为系统命名的技巧。<br /><br /> 人们常批评 XP 乃是基于觉得一个系统实在是至少需要一个大概的设计。XP 专家则以 &quot;就是 metaphor 啊!&quot; 来响应。但是我还是没有看到一个对于 metaphor 令人信服的解释。这是 XP 的缺憾,必须由 XP 专家来理出头绪。<br /><br /> <br /><br />Do you wanna be an Architect when you grow up?<br /><br /> <br /><br />近几年来 &quot;software architect (软件设计师)&quot; 越来越热门,这是一个就我个人而言难以接受的名词。我太太是结构工程师,工程师和建筑师之间的关系是... 有趣的。我最喜欢的一句话是:建筑师对三种 B 是好的,灯泡、灌木丛、和鸟。因为建筑师画出这些美丽的图画,但却要工程师保证能做出来。结论是我避免 software architect 一词,毕竟如果连我的太太都不能尊重我的专业,我又怎么能对其他人有所期望呢?<br /><br />对软件来说,architect 一词可以代表很多事情。(软件界很多词都可以代表很多事。) 这通常符合一句话:我不仅是一个程序员,我还是一个设计师[译注2]。还可以进一步解译成:我现在是一个设计师 - 我对于完成所有程序来说太重要了。然后这个问题就变成,当你要展现技术领导的时候,你是不是该把自己与烦琐的程序撰写分清楚?<br /><br />这个问题引起众多的不满。我看到人们对于再也无法担任设计角色这样的想法感到生气。我最常听到:在 XP 没有设计师的挥洒空间。<br /><br />就设计本身的角色来说,我不觉得 XP 不重视经验或好的设计。事实上多位 XP 的提倡者 - Kent Back、Bob Martin、当然还有 Ward Cunningham - 都是我从而学习设计的对象。然而这也代表着他们的角色从大家既有的印象中开始转变成为技术领导者。<br /><br />我将以一位 ThoughtWorks 的技术领导者 Dave Rice 为例。Dave 参与了很多个研发周期,并且非正式的指导一个 50 人的项目。他担任指导的角色意味着要花很长的时间与程序员为伍。当程序员需要帮助,他就介入,否则就留意着看谁需要协助。他的座位有一个明显的特征,担任一位长期的思考工作者,他可以在任何形式的办公环境适应良好。他曾经与发行部经理 Cara 共享办公室一段时间。而在最后几个月,他更是搬到工程师们工作的开放式空间 (就像 XP 小组喜欢的开放式 &quot;战斗空间&quot;)。这么做对他很重要,他可以知道事情的进展,并适时伸出援手。<br /><br />知道 XP 的人就能够了解我描述的是 XP &quot;教练&quot; 的清楚角色。的确,在 XP 玩的文字游戏中提到领导技术就是在描绘 &quot;教练&quot; 这个角色。其意义是很清楚的:在 XP 技术的领导特质是透过教导程序员和帮助他们做决定而呈现。这是一种需要良好人际管理和技术并重的技巧。Jack Bolles 在 XP2000 说:孤单的大师有点机会了,合作和教导是成功的关键。<br /><br />在研讨会的晚餐会上,我和 Dave 在谈话时对 XP 有了些对立的意见。当我们讨论到以前的经验,我们的方法有相当的类似。我们都偏好 adaptive,iterative development,也认为测试是重要的。所以我们都对他反对的立场感到疑惑。然而他提到 &quot;最后我要的是程序员照着设计忙于重构&quot;。事情一下子明朗起来。后来 Dave 又对我说 &quot;如果我不信任我的程序员,我何必要用他们呢?&quot;,观念上的隔阂就更加清楚了。在 XP 里头,有经验的研发人员所能做的最重要的一件事就是尽量将所有技术传继给新手。不同于一个决定所有重要事情的建筑师,你有一个能够教导研发人员如何做重大决定的教练。就像 Ward Cunningham 指出,这么做不只是增进了新手的能力,对项目的好处更大于一个孤立无援的超人所能做的。[ 译注7]<br /><br /> <br /><br />Things that are difficult to refactor in<br /><br /> <br /><br />我们能用 refactoring 来处理所有设计方面的决定吗?或者,有些问题太普遍而且难以在将来加入设计中?此时,XP 的正统做法是所有需求都可以轻易的在需要的时候增加,所以 YAGNI 总是能够适用。我猜是不是有例外?有一个不错的,被讨论到的例子是软件的国际化。这是不是一种现在应该立即进行,否则以后再加入时会觉得痛苦的事情?<br /><br />我能轻易的想象一些事情就是这种情形。事实上我们仍然掌握太少的信息。如果你必须陆续加入一些功能,如国际化,而你知道那需要多少工夫。你比较不容易意识到在你真正需要他之前,你要花多少时间加入它,并且要长时间的维护它。你也比较不容易察觉到也许你可能做错了,所以到头来还是需要做些 refactoring。<br /><br />有一部份能够为 YAGNI 辩护的理由是有些预先做的功能可能最后并不需要,或者它并不如预期的结果。不做这些所省下的力气比用 refactoring 来更改成为符合需要所用的力气要少。<br /><br />另外一个要想的问题是你是否真的知道怎么做。如果你有很多次做软件国际化的经验,你会知道该用什么模式来作。那样的情形下你应该会把它作好。这时你所加入的预留的结构可能会比你头一次处理这种问题要好。所以我的想法是,如果你知道怎么做,你就要考虑现在做和将来做,两种情形之间不同的成本。反过来说,如果你没有处理过那样的问题,不仅是你无法正确判断需要的成本,你也比较不可能把事情作好。这种情形,你就要选择将来再做。如果你还是执意做了,而且尝到苦果,可能会比不做的情况更糟。当你的组员更有经验,你对相关领域有更多认识,你对需求也会更了解。通常到这时你回头看才会发现事情有多简单。提早加入的设计比你想象中要难多了。<br /><br />这个问题也跟 stories 的顺序密切相关。在 Planning XP 一书中,Kent 和我公开的指出我们的歧见。Kent 偏向于只让商业价值这一个因素影响 stories 的顺序。在短暂的意见不合之后 Ron Jeffries 也同意这种想法。我仍保持怀疑。我相信在商业价值和技术风险之间能找到平衡点。基于这样的理由让我提早为软件国际化做准备以降低风险。但是这种做法也只有当第一阶段发行就需要将软件国际化才能成立。尽快达到一个阶段的发行是非常重要的。任何原来不需要而后来必须增加的复杂性都值得在第一阶段发行之后才开始。发行之后运作中的程序有强大的力量,它抓住顾客的注意,增加信任感并且是一个学习的好机会。就算是在初次发行之后会有更多的事情要做,还是要尽所有努力将第一阶段日期往前推。<br /><br /> <br /><br />So is Design Dead?<br /><br /> <br /><br />没什么原因,只是设计的本质已经改变。XP 的设计追求以下的技巧:<br /><br />持续保持清爽的程序代码,越简单越好。<br /><br />重构的技巧,所以当你觉得必要的时候都可以有信心的动手。<br /><br />具有 patterns 的知识:不只是照它的解法,更要感觉何时可以应用,或是如何导入 patterns。<br /><br />知道如何将设计说给必要的人了解[译注8],用程序代码、或是图形、或上述所有的工具:交谈。<br /><br />以上挑出来的技巧看来都挺吓人,但是要成为一个优秀的设计师本来就很难。XP 也不是要让它变得简单,至少我就不觉得。但是我想 XP 让我们对有效率的设计有全新的看法,因为它让渐进式设计听起来是可行的方式。而且我也很支持演进 - 否则谁知道我会变成什么呢?<br /><br /> <br /><br />Acknowledgements[译注9]<br /><br /> <br /><br />过去这些年我从很多好朋友身上偷学到不少好的想法,很多都已经记不起来。但是我记得从 Joshua Kerievski 那里偷到的好东西。我也记得 Fred George 和 Ron Jeffries 给我很好的建议。我当然也不能忘记 Ward 和 Kent 不断有好的想法。<br /><br />我也感谢曾经提出问题和指出打字错误的朋友。同时感谢 Craig Jones 提醒我好几个漏掉的 “a”。<br /><br /> <br /><br />Revision History<br /><br />以下是这篇文章重大的修改记录:<br /><br />&nbsp; &nbsp; &nbsp; 2001 年 2 月:对 growing an architecture、the role of an architect、和 where things that are difficult to add with refactoring 等段落做修改。<br /><br />&nbsp; &nbsp; &nbsp; 2000 年 7 月:原始文件在 XP 2000 发表,并刊载于 MartinFowler.com 网页。<br /><br />&nbsp; <br /><br />[译注1] 一种在着手进行程序代码的撰写之前,就先按照既定的程序分析、设计、制图、撰写文件等等耗时费力的工作方式。<br /><br />[译注2] 在台湾你觉得 “程序设计师”、“软件设计师” 和 “软件工程师” 有什么不同吗?相信大部分的人觉得都是同一种角色。但是从英文字意就比较容易区别 “programmer”、”designer”、”architect”等等不同的角色。这样的语言文化差异性,也是我在内文中留下不少原文的原因。在部份字句中,留下原文并不影响阅读的顺畅,但是可以避免文意因为翻译所造成的模糊或扭曲。<br /><br />[译注3] 在建筑业应该是称呼 “施工人员” 比较顺耳,而在软件业应该是 “programmer” 比较恰当。但是这两者都是 “builder”。<br /><br />[译注4] 关于这一点,译者也提供一个实际的经验,也就是翻译这篇文章的过程。我和一位朋友一起翻译这篇文章,而且因为都先看过 XP Distilled 一文,所以决定采用 XP 12 个有效的实务技巧其中的 Continuous Integration、Pair Programming、Small Releases、Refactoring、Coding Standards、Collective Code Ownership 等等技巧。因为 XP Distilled 一文的经验我们首先对于部份翻译名词提出彼此的统一版本,这就是一种 Coding Standards。我们同时都对这篇文章进行翻译,不同的人进行同一项工作进度就不会相同,每翻译几个段落就将进度寄给对方,这就是 Small Releases。当我收到朋友寄来的部份,我就对照两方的差异将文章针对译意的正确性和辞句的通畅做初步的整理和修正,这就是 Continuous Integration。我整理过的部份再寄回给朋友进行检查,如果发现不妥的部份,就进行讨论或修改,这就是 Refactoring。从头到尾的过程中,我们都收到彼此的翻译版本,也拥有整理过的版本,对于每个部份也都清楚了解,符合 Collective Code Ownership 的精神。最后,因为我们刚好是两个人,不巧又可以冠上另一个技巧Pair Programming。所以,我们使用了 XP 一半的方法,对于工作上有帮助的方法。但并不是非得每一项技巧都利用到。我想,更重要的一点是,XP 并不是只能用在软件研发,我们的翻译过程不也借来用了!<br /><br />[译注5] Story 是一种类似 use case 的描述。<br /><br />[译注6] 按照原文的意思就是以 32 行的程序代码而能够表现出 16 种 patterns!这样的传奇性功力实在不是经验及见识浅薄的译者所能想象,所以我们只能按照原文翻译,而无法对这句话提出左证。如果读者见过作者提到的例子,很感谢您提供相关资料给我。<br /><br />[译注7] 这一点也是译者对于台湾软件环境非常忧心的问题,大家都能体会中国人的一种不知道能不能说是重大缺点的民族习性 “藏私”。我在不同的机会从文章中以及朋友的口中听到一种想法,要提升团队的整理效率,一种最简单的方法就是将技术落后的成员教育提升到与技术领先的成员相同的水平。这样的想法实在是一种非常有用而且深刻的体认,更是一种感叹。在台湾能够在口头上同意这种做法,而实际上更能够进而实践这种精神的人有多少??有些人都担心自己的技术被人窥透之后,个人地位恐将遭到取代,更遭的是可能有老板真的会 “狡兔死走狗烹” 的在榨取经验的传承之后,将有贡献却成本高的成员以各种方式逼走,这实在是让人忧心又灰心的现象啊!译者相信,再困难的技术只要是你能了解,就已经存在了竞争对手,如果不能将身边成员的技术水平同时迅速提升,只有等着被快速超越,更可能被淘汰。译者也实践着 XP 这方面的精神,虽然译者所拥有的技术知识非常粗浅,但是只要同事朋友需要我的协助,我总是知无不言,言无不尽。译者要向流星许愿,希望能够找到越来越多的同类。<br /><br />[译注8] 有效的沟通也是译者常遭遇的问题之一,有些人无法以不同的方式为事情下批注,有些人对于门外汉还是满口专业术语,有些人不能观察顾虑到听者是不是已经了解所阐述的精髓。这些都不是有效的沟通。我们似乎还不够重视人际沟通这门学问,如何以对方能懂的方式说给对方听,真是不容易呢!译者只是发出感叹,却也亟需要培养沟通能力,才不会让共事的同事摇头。<br /><br />[译注9] 译者之一的我 (Daimler) 也要搭个顺风车,感谢朋友 (S.H.Chen) 在百忙之中抽空与我完成这篇文章的翻译,这位朋友在软件工程方面的知识给我的帮助非常关键。翻译本身就存在不少争议,应该按照句子逐字翻译,还是要考虑依据本国文字的用语习惯做适当的调整,以求字句的通顺,真的让人难以取舍抉择。我 (Daimler) 是比较倾向于在不扭曲原著作文意的原则下,对句子做适当的重组和调整。但是这个动作本身就存在着非常大的危险,我对于原文是否有足够的认识?我对于本国文字的造诣是否及格?希望这篇文章对于国内读者能有所帮助,至少是效率上的帮助。更期盼来自各方的指教。<br /><br /><!--QuoteEnd--></div><!--QuoteEEnd--><br /><a href='http://www.cnblogs.com/airforce1st/archive/2004/03/18/3514.aspx' target='_blank'>http://www.cnblogs.com/airforce1st/archive...03/18/3514.aspx</a>

2004-3-22 10:34 99大话王
Extreme Programming介绍<br /><!--QuoteBegin--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--QuoteEBegin-->计划<br /> User stories的编写<br /><br /> 开发计划的制定<br /><br /> 经常构造版本<br /><br /> Load Factor因子的确定<br /><br /> 将项目分解为各个迭代期<br /><br /> 每个迭代期开始时制定计划<br /><br /> 人员集中<br /><br /> 站着开每日晨会<br /><br /> 当实施遇到困难时及时修正XP<br /><br />设计<br /> 简单化.<br /><br /> 采用编程规范<br /><br /> 设计时使用CRC卡片<br /><br /> 使用Spike Solution 方法<br /><br /> 不要过早添加新功能<br /><br /> 尽可能保持程序的简洁性<br /><br />编码<br /> 始终获得用户的支持<br /><br /> 代码的书写必须按照规范<br /><br /> 所有代码均采用配对开发<br /><br /> 一次只能有一对开发人员进行Release<br /><br /> 代码经常集成<br /><br /> 代码共享<br /><br /> 将优化放在最后<br /><br /> 不要加班<br /><br />测试<br /> 所有代码均需进行单元测试<br /><br /> 在Release之前所有代码必须通过单元测试<br /><br /> Bug发现后应马上测试<br /><br /><br /><br />计 划<br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; User stories的编写<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 制定开发计划<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 经常构造版本<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; Load Factor因子的确定<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 将项目分解为各个迭代期<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 每个迭代期开始时制定计划<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 人员集中<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 站着开每日晨会<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 当实施遇到困难时及时修正XP <br /><br />User Stories<br />User stories与use case类似,它主要是在Plan Game过程中对时间以及开发风险进行评估。此外它还用于代替传统开发中所写得大量的需求文档。User stories是由用户来写的,在其中要写出所有需要系统完成的功能,在此也可以描述用户界面。User stories必须采用用户的术语来写,而不能采用任何技术术语。后期的功能测试也是信赖于此,并由此判定功能是否完成,是否正确。User stories必须足够的详细,这样才能对开发工作量有一个比较准确的评估。一个User stories应对应1至3周的工作量,如果超过3周就应当将其继续细分。一个典型的项目一般由80+/-20个User stories构成。User stories的另一个特点就是它是面对用户的,因此在其中不应包含任何有关技术、数据库以及算法在内的术语。我们应当将精力放在用户的需要以及GUI方面。<br /><br />Planning Game<br />通过Planning Game阶段,我们可以对整个项目制定一个开发计划表,并且以后还要依靠此计划表制定出每个迭代期的开发表。它应当是技术人员以及市场人员共同协商的结果。Planning Game的主要工作是评估每个User stories所需的工作量(以理想情况下的工作日为单位)、风险以及优先级。具体执行时,首先将所有的User Stories打印出来或者是写在卡片上,然后将其放在一起,由用户以及开发人员一起对它们进行优先级划分,确定实现的先后顺序,最终的结果是:尽早提供一个有用的、可测试的并且在商业上有意义的早期版本。此外最好能在前期就将高风险的功能加以实现。Load factor在此用于判断实现User stories需要多少时间,以及在指定的日期之前我们可以完成那些内容。Load Factor是基于理想的工作日而定的。<br /><br />经常构造版本<br />在Planning Game阶段,我们发现了那些从商为角度上看有意义的功能,在实现过程中应尽可能早地实现这些功能,也就是说要经常构造版本,并及时地将有关版本其交付给用户试用。采用这种方式的好处在于,我们可以及时从用户处获得有用的反馈信息,否则等到开发的后期才获得这些信息,此时留给我们进行改动的时间也不多了。<br /><br />Load Factor<br />Load Factor用于度量项目的开发速度。Load Factor相当于在理想状态下完成一个任务所需花费的工作时间。一开始时我们并不能确切地知道Load Factor是多少,通常可以设置为2或者3,但在以后的开发过程中可以不断对其进行修正。如果在开发中发现Load Factor与最初所设置的值有较大的差别,那我们就需要对Planning Game进行相应的调整了。在项目进入维护阶段以后,同样需要对Load Factor进行调整。<br /><br />迭代开发<br />迭代开发为开发过程增添了灵活性,一般来说,应将整个项目划分为若干个不超过两到三周的迭代期。注意:不要过早制定开发计划,而应在每个迭代期开始时通过计划会议制定本迭代期的开发计划。此外不要提前实现任何不在本迭代期计划中的功能!只有这样才能保证对变化的需求的及时响应。<br /><br />迭代期开发计划的制定<br />在每个迭代期开始时才制定相应的开发计划。一般迭代期的长度应控制在一到四周之内,计划的制定是依前期Planning Game中为每个迭代期所选择的User Stories而定的。 User Stories以及测试中出错的问题在此均转换为开发任务,并被写在卡片上。任务一定要填写的足够详细以便为本迭代期制定计划。每个任务应能在一至三个理想的工作日中加以完成。开发人员分配到任务后再根据自身的情况加以估计需要多长时间才能完成。Load Factor在此用于评估本迭代期的开发工作量是否过多或过少。最终的开发时间的估计等于理想开发时间再乘以Load Factor。如果工作量过大,则应减少此周期中所需完成的User Stories。如果User Stories的完成进度慢了下来,那就要注意了。通过是将难的任务放在前期,容易的放在后期,这样就可以保证开发速度越来越快。<br /><br />在此应注意以下几点:不要添加额外的灵活性,除非现在必须这样做;不要添加新功能,除非其已列在计划中,否则会减缓开发进度;注意Load Factories的变化,以便及时改进开发计划。<br /><br />人员集中<br />将开发人员集中起来,这样可以避免有关信息的丢失以及开发的瓶颈。配对开发一方面可以提高开发质量,另一方面可以防止由于人员流失造成开发进度受阻。<br /><br />站着开每日晨会<br />每天早上大家站在一起开个会,以便相互讨论所遇到的问题,解决方案,确定团队的工作重点。所有人均站着并围成一个圆圈以避免长时间的行讨论,而且可以增加大家对讨论内容的重视。<br /><br />通常开会时我们的大部分精力并没有放在会议主题上,大量的开发时间浪费在很多琐碎的小事上。同时由于项目成员参加了过多的此类会议,损失了大量的项目资源,从而造成了开发进度的失控。由于参加人员不多,大部分此类会议可以直接在计算机前开,所以可以在讨论中直接浏览代码并对新的想法加以验证。<br /><br />当实施遇到困难时及时修正XP <br />&nbsp; &nbsp; 当实施遇到困难时及时修正XP。在制定XP时不可能考虑到每个项目的特殊情况,所以在实施XP时也不要想象着它可以满足你的项目的所有需求,或者是它可以不加修改地直接在你所在的环境中执行。在实施过程中应及时开会讨论那些内容是有效的,那些是没有效果的,并不断对XP加以修正以提高项目组的开发水平。 <br /><br /><br /><br />设 计<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 简单化<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; Choose a system metaphor<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 在设计中使用CRC卡片<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; Create spike solutions to reduce risk<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 不要过早添加新功能<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 尽可能保持程序的简洁性<br /><br />简单化是关键<br />&nbsp; &nbsp; 通过将复杂的设计简单化将会节省大量的时间。因此如果你发现某些复杂的设计可以采用简单的方法加以实现时,采用简单的方式。记住:尽可能采用简单的方法,尽可能长时间的采用简单的方法,如果没有将其包含在计划中一定不要提早实现新功能。但同时应注意:保持设计的简单化是一个并不轻松的工作。<br /><br />采用编程规范 <br />系统中变量、类以及方法的命名均应采用约定的规则。统一的命名对了解他人的设计以及代码的重用均是十分重要的。<br /><br />CRC卡片<br />使用“类、职责、协作”(CRC)卡版进行系统设计。采用CRC的一个好处在于它可以使你自然地采用面向对象的方法加以思考问题,另外它还可以让更多的人加入到系统的设计过程中,从而使设计更加合理与健壮。<br /><br />&nbsp; &nbsp; 一个的CRC卡片代表一个独立对象的实例。在卡片的上边记录有类的名称,在卡的左边列出了此类所要实现的功能,在卡的右边列出了与此类相关的其它类的名称。通过将所有的CRC卡放在一起,不同的人负责一个或几个CRC卡,大家一起协同工作以模似当前所设计的软件最终动态的运行情况:哪个类发出一个消息,哪个类接收到这个消息并执行某一特定的动作…。采用上述“走读”方式,我们可以方便地发现设计中的问题。总得来看,此处的CRC方法与在ROSE中采用Class Diagram是相同的。如果发现有过多的人同时在移动/谈话,则可以限制一次站起并移动卡片的人的总数。只有当一个人坐下后才能允许其它人站起来。<br /><br />采用CRC卡的一个不利之处在于它缺乏设计文档。当然也可以将所有卡中的内容保存在一个文档之中。<br /><br />使用Spike Solution 方法<br />为了解决一个技术或者设计上的问题,我们可以采用“Spike Solution”方式(类似于我们常说的“技术原型”)。此方法只关心所要解决的问题本身,而不关心其它内容。大部分的“Spike Solution”是一个粗糙的不能再用的程序,一般试验完成后就不再用了。使用这种方法的目的是减少技术问题的风险,并且可以提高我们对User Stories评估的准确性。<br /><br />不要过早添加新功能<br />保持产品功能的单一性,不要添加你认为以后可能会用到的代码。只有10%的多余代码会在以后用到,因此过早加入多余的代码会导致你浪费90%的时间。多余的代码及功能还将降低开发速度并浪费开发资源。所以只做计划中要做的事情。<br /><br />保持程序的简洁性<br />很多时候,当程序的结构已被改的支离破碎,或者程序代码已被改的面目全非时,我们仍试图将其维持下去。但这一些均不会发生在XP中。在XP中,一旦发现上述情况就会将原有的结构/代码推翻重新进行设计/编码。虽然看起来这样的花费比维持原有状况代价更大,但从长远的角度来看将会节省更多的人力资源。不论在程序开发中哪一个阶段,如果发现程序中存在冗余的代码、无用的函数以及过时的设计,删掉它们!这在XP中被称为“Refactor”。<br /><br />通过Refactor可以避免程序的冗余以及复杂化,使之尽量简化。只有这样才能保证代码容易为他人理解、修改以及扩充。不要等到系统已混乱不堪时再花时间去解决问题。<br /><br /><br /><br />编 码<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 始终获得用户的支持<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 代码的编写必须符合规范<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 所有代码均应采用配对编程方式加以开发<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 一次只能有一对开发人员进行Release<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 经常集成<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 代码共享<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 将优化放在最后进行<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 不要加班<br /><br />始终获得用户的支持<br /><br />在XP开发中有一条原则是:始终保持与用户的联系。用户不但可以帮忙开发团队,而且是开发团队的一部分。在XP的各个阶段中均需要与用户的交流,最好是坐在一起面对面的交流。如果可能的话,最好在开发团队中分配一至多名用户。需要注意的一点是:在此我们需要的是用户中的专家,而不是新手。<br /><br />User Stories是由用户在开发人员的帮助下编写的,并且用户需要帮助确保系统所需的功能均已涵盖在User Stories中。<br /><br />计划阶段,用户帮助开发人员为每个迭代期选择需实现的User Stories,确定每个开发周期的长短。如果有商业目标的改动,应由用户做出最终的决定。迭代期确定的最终原则是让用户尽早拿到一个可用的早期版本。<br /><br />编程规范<br />&nbsp; &nbsp; 编码时一定要遵守编程规范,以使代码具有可读性,易于为项目组中其它人员所理解。<br /><br />配对编程<br />&nbsp; &nbsp; 所有的代码均应在采用配对编码方式下产生,即由两个开发人员共同编写。配对编程在不影响开发周期的前提下提高了软件的质量(多用15%的时间,但提高软件质量23%)。<br /><br />按顺序Release代码<br />&nbsp; &nbsp;&nbsp; 因为并行开发的原因,所以同一时刻可能有多对开发人员在对代码进行Release,由于大家均没有将自已的当前改动放到服务器中,所以在这种情效况下进行的Release并不能保证最终所有代码全部更新后再次Release的正确性。为此应当规定:同一时刻只能有一对开发人员在进行Release,当其保证有关代码正确并更新至服务器后才允许其它开发人员对其私有代码进行Release。<br /><br />经常集成<br />为了提早发现问题,尽可能地经常地进行代码集成,最好不要超过一天。通过代码集成可以发现不同部分之间的配合问题,如果集成的周期过长,将会导致修改成本的上升。并且通过经常集成代码,可以保证当前服务器上始终有一个可用的版本。另外,采用此方法,还可以更好地实现代码的重用。<br /><br />代码共享<br />&nbsp; &nbsp; 确保项目组中的每个人均能看到所有的代码,并且为了修改BUG可以对每个源代码文件进行修改。这样可以避免由于某个人的缺席造成开发中的瓶颈。此外应让所有开发人员对程序的整体结构有一个清晰的认识,而不要将有关知识只掌握在一两个人头脑中。<br /><br />最后做优化<br />只在开发的后期才进行优化。不要在开发的过程中想当然地认为何处是瓶颈,只有实际测试之后才能发现真正的瓶劲。首行保证代码能工作,然后保证工作正确,最后再想办法提高运行速度(Make it work, make it right, then make it fast)。<br /><br />不要加班<br />&nbsp; &nbsp; 不要加班,这样会榨干开发人员的精力并减弱开发积极性。如果是为了保证按时完成计划而加班的话,那么最终无论你怎么做,均无法实现这个目标。正确的做法是:减少软件所要实现的功能或者延长开发时间。在开发进度延后的情况下增加开发人员同样也是不可取的。<br /><br /><br /><br />测 试<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 所有的代码必面做单元测试<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 版本发放之前所有代码必须通过单元测试<br /><br />l&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 发现一个BUG后就要为其创建一个测试用例<br /><br />单元测试<br />单元测试是XP开发方法中的基石。与其它的单元测试方法有所不同,XP中的单元测试具有以下特点:首先你需要创建或者下载(从www.XProgramming.com中下载)一个单元测试框架以便实现自动化的单元测试;第二点,必须测试所有的类(可以利用VC中的Profile功能进行代码的覆盖性测试);最后,在编写代码之前就必须先考虑有关测试的内容。<br /><br />在编码之前就考虑测试可以使开发人员对需求具有更好的理解,对程序结构会有更好的把握,并且在代码开发完后马上就可以进行测试,及时获得有用的反馈信息。没有经过.测试的代码是不允许被包括在Release版本中。<br /><br />只有当所有的代码均进行并且通过了单元测试之后,才能Release一个新版本。<br /><br />针对每个User Stories应创建相应的功能测试。功能测试属于黑盒测试,由用户来判断测试结果是否正确,并且它的执行必须在Release之前。测试时最好有自动测试工具。<br /><br />一旦发现一个BUG,立即为其创建一个相应的测试用例,以防止以后再次出现此类问题。<br /><br /><br /><br />Extreme Programming总结<br /><br />XP的主要特点<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 是一个轻量级的软件开发过程<br /><br />最大限度地满足用户的需求<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 强调团队的协作<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 强调项目管理(基于评估以及制定计划)<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 将有限的时间投入到真正的开发中(抛弃不必要的会议、文档以及评审)<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 见效快<br /><br />XP适用对象<br /><br />&nbsp; &nbsp; 是一个轻量级的开发过程<br /><br />适用于2 – 10人,3个月 – 1年的小型项目<br /><br />适用于需求经常变更以及高风险的项目<br /><br />XP在实施中的四个主要特点<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 沟通、简单化、反馈、勇气 (Communication, Simplicity, Feedback, and Courage.)<br /><br />Communication takes place between people, documents are secondary.<br /><br />XP与RUP的关系<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 是RUP的最小实现集(A minimal RUP process)<br /><br />又被称之为dX (Object Oriented Analysis and Design with Application, 3th)<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; dX在表述上采用了RUP的表述形式<br /><br />XP实施中的注意事项<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 以体系结构为中心 (architecture-based)(has a very strong architecture focus)<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 以用户需求驱动 (requirement-driven)<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 强调软件的良好的内部结构<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 并不排斥分析及设计(包含在代码中,没有多余的外部文档)<br /><br />如何开发实施XP<br /><br />可以从一个全新的项目开始<br /><br />可以针对正在进行的项目开始<br /><br />可以全部采用XP的方法<br /><br />可以只采用部分XP的方法<br /><br />参考资料<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; www.extremeprogramming.org<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; www.XProgramming.com<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; www.objectmentor.com<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 《Design Patterns》<br /><br />&nbsp; &nbsp; &nbsp;&nbsp; 《Software Architecture》<br /><br /><br /><br />XP工作流程图<br /><img src='http://263.aka.org.cn/Magazine/Aka6/images/i21.gif' border='0' alt='user posted image' /><br /><img src='http://263.aka.org.cn/Magazine/Aka6/images/i22.gif' border='0' alt='user posted image' /><br /><img src='http://263.aka.org.cn/Magazine/Aka6/images/i23.gif' border='0' alt='user posted image' /><br /><!--QuoteEnd--></div><!--QuoteEEnd--><br /><a href='http://263.aka.org.cn/Magazine/Aka6/light/Extreme%20Programming%20intro.htm' target='_blank'>http://263.aka.org.cn/Magazine/Aka6/light/...ing%20intro.htm</a>

2004-4-3 08:25 hsia
建议加精。

页: [1]


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.