软件开发流程(转载)

软件开发流程
迭代化软件开发技术

1. 传统开发流程的问题
传统的 软件开发流程是一个文档驱动的流程,它将整个软件开发过程划分为顺序相接的几个阶段,每个阶段都必需完毕全部规定的任务(文档)后才能够进入下一个阶段。 如必须完毕全部的系统需求规格说明书以后才能够进入概要设计阶段,编码必需在系统设计完毕以后才能够进行。这就意味着仅仅有当全部的系统模块全部开发完毕之 后,咱们才进行系统集成,对于一个由上百个模块组的复杂系统来讲,这是一个很艰巨而漫长的工做。html


随着咱们所开发的软件项目愈来愈复杂,传统的瀑布型开发流程不断地暴露出下面问题:前端

  • 需求或设计中的错误每每仅仅有到了项目后期才能够被发现好比:系统交付客户以后才发现原先对于需求的理解是错误的,系统设计中的问题要到測试阶段才干被发现。
  • 对于项目风险的控制能力较弱项目风险在项目开发较晚的时候才能够真正减小,每每是通过系统測试以后,才干肯定该设计是否能够真正知足系统需求。
  • 软件项目常常延期完毕或开发费用超出预算项目开发进度每每会被意外发生的问题所打乱,需要进行返工或其它一些额外的开发周期,形成项目延期或费用超支。
  • 项目管理人员专一于文档的完毕和审核来预计项目的进展状况因此项目经理对于项目状态的预计每每是不许确的,当他回答系统已完毕了80%的开发任务时,剩下20%的开发任务实际上消耗的是整个项目80%的开发资源。

在传统的瀑布模型中,需求和设计中的问题是没法在项目开发的前期被检測出来的,仅仅有当第一次系统集成时,这些设计缺陷才会在測试中暴露出来,从而致使一系列的返工:又一次设计、编码、測试,进而致使项目的延期和开发成本的上升。linux


2. 採用迭代化开发控制项目风险
为 了解决传统软件开发流程中的问题,咱们建议採用迭代化的开发方法来代替瀑布模型。在瀑布模型中,咱们要完毕的是整个软件系统开发这个大目标。在迭代化的方 法中,咱们将整个项目的开发目标划分红为一些更易于完毕和达到的阶段性小目标,这些小目标都有一个定义明白的阶段性评估标准。迭代就是为了完毕必定的阶段 性目标而所从事的一系列开发活动,在每个迭代開始前都要依据项目当前的状态和所要达到的阶段性目标制定迭代计划,整个迭代过程包括了需求、设计、实施(编 码)、部署、測试等各类类型的开发活动,迭代完毕以后需要对迭代完毕的结果进行评估,并以此为根据来制定下一次迭代的目标。数据库


与传统的瀑布式开发模型相比較,迭代化开发具备下面特色:编程

  • 赞成变动需求
    需求老是会变化,这是事实。给项目带来麻烦的常常主要是需求变化和需求"蠕变",它们会致使延期交付、工期延误、客户不满 意、开发者受挫。经过向用户演示迭代所产生的部分系统功能,咱们可以尽早地收集用户对于系统的反馈,及时改正对于用户需求的理解误差,从而保证开发出来 的系统真正地解决客户的问题。
  • 逐步集成元素
    在传统的项目开发中,由于要求一会儿集成系统中所有的模块,集成阶段每每要占到整个项目很是大比例的工做量(最 高可达40%),这一阶段的工做经常是不肯定并且很棘手。在迭代式方法中,集成可以说是接二连三的,每一次迭代都会增量式集成一些新的系统功能,要集成 的元素都比过去少得多,因此工做量和难度都是比較低的。
  • 尽早减小风险
    迭代化开发的主要指导原则就是以架构为中心,在早期的迭代中所要解决的主要问题就是尽快肯定系统架构,经过几 次迭代来尽快地设计出能够知足核心需求的系统架构,这样能够迅速减小整个项目的风险。等到系统架构稳定以后,项目的风险就比較低了,这个时候再去实现系统 中还没有完毕的功能,进而完毕整个项目。
  • 有助于提升团队的士气
    开发者经过每次迭代都可以在短时间内看到本身的工做成果,从而有助于他们加强信心,更好地完毕开发任务。而在非迭代式开发中,开发者仅仅有在项目接近尾声时才干看到开发的结果,在此以前的至关长时间,你们仍是在不肯定性中摸索前近。
  • 生成更高质量的产品
    每次迭代都会产生一个可执行的系统,经过对这个可执行系统进行測试,咱们在早期的迭代中就可以及时发现缺陷并改正,性能上的瓶颈也可以尽早发现并处理。因为在每次迭代中老是不断地纠正错误,咱们可以获得更高质量的产品。
  • 保证项目开发进度
    每次迭代结束时都会进行评估,来推断该次迭代有没有达到预约的目标。项目经理可以很是清楚地知道有哪些需求已经实现了,并且比較准确地预计项目的状态,对项目的开发进度进行必要的调整,保证项目按时完毕。
  • 允许产品进行战术改变
    迭代化的开发具备更大的灵活性,在迭代过程当中可以随时依据业务状况或市场环境来对产品的开发进行调整。好比为了同现有的同类产品竞争,可以决定採用抢先竞争对手一步的方法,提早公布一个功能简化的产品。
  • 迭代流程自身可在进行过程当中获得改进和精炼
    一次迭代结束时的评估不只要从产品和进度的角度来考察项目的状况,而且还要分析组织和流程自己有什么待改进之处,以便在下次迭代中更好地完毕任务。


迭代化方法解决的主要是对于风险的控制问题,从下图能够看出,传统的开发流程中系统的风险要到项目开发的后期(主要是測试阶段)才能够被真正减小。 而迭代化开发中的风险,可以在项目开发的早期经过几回迭代来尽快地解决掉。在早期的迭代中一旦遇到问题,如某一个迭代没有完毕预约的目标,咱们还可以及时 调整开发进度以保证项目按时完毕。通常到了项目开发的后期(风险受控阶段),由于大部分高风险的因素(如需求、架构、性能等)都已经解决,这时候仅仅需要投 入不少其它的资源去实现剩余的需求就能够。这个阶段的项目开发具备很是强的可控性,从而保证咱们按时交付一个高质量的软件系统。promise


迭代化开发不是一种高深的软件project理论,它提供了一种控制项目风险的颇有效的机制。在平常的工做咱们也经常地应用到这一基本思想,如对于一个很 大型的project项目,咱们经常会把它分为几期来分步实施,从而把复杂的问题分解为相对easy解决的小问题,并且能够在较短周期内看到部分系统实现的效果,经过尽 早暴露问题来帮助咱们及早调整咱们的开发资源,增强项目进度的可控程度,保证项目的按时完毕。安全

3. 管理迭代化的软件项目
当我 们在实际工做中实践迭代化思想时,Rational统一开发流程RUP(Rational Unified Process)可以给予咱们实践的指导。RUP是一个通用的软件流程框架,它是一个以架构为中心、用例驱动的迭代化软件开发流程。RUP是从几千个软件 项目的实践经验中总结出来的,对于实际的项目具备很是强的指导意义,是软件开发行业其实的行业标准。架构

3.1 软件开发的四个阶段
在RUP中,咱们把软件开发生命周期划分为四个阶段,每个阶段的结束标志就是一个基本的里程碑(例如如下图所看到的)。框架


这四个阶段主要是为了达到下面阶段性的目标里程碑:jsp

  • 先启(Inception):肯定项目开发的目标和范围
  • 精化(Elaboration):肯定系统架构和明白需求
  • 构建(Construction):实现剩余的系统功能
  • 产品化(Transition):完毕软件的产品化工做,将系统移交给客户

每一个目标里程碑都是一个商业上的决策点,如先启阶段结束以后,咱们就要决定这个项目是否可行、是否要继续作这个项目。每一个阶段都是由里程碑来决定的,推断一个阶段是否结束的标志就是看项目当前的状态是否知足里碑中所规定的条件。

从这样的阶段划分模式中可以看出,项目的主要风险集中在前两个阶段。在精化阶段中通过几回迭代后,咱们要为系统创建一个稳定的架构,在此以后再实现更 多的系统需求时,再也不需要对该架构进行改动。同一时候,在精化阶段中,咱们经过迭代来不断地收集用户的需求反馈,便得系统的需求逐步地明白和完整。

3.2 关于开发资源的分配
基于 RUP风险驱动的迭代化开发模式,咱们仅仅需要在项目的先启阶段投入少许的资源,对项目的开发前景和商业可行性进行一些探索性的研究。在精化阶段再投入多一 些的研发力量来实现一些与架构相关的核心需求,逐步地把系统架构搭建起来。等到这两个阶段结束以后,项目的一些主要风险和问题也获得了解决,这时候再投入 整个团队进行全面的系统开发。等到产品化阶段,基本的开发任务已经全部完毕,项目再也不需要维持一个大规模的开发团队,开发资源也可以随之而下降。在项目开 发周期中,开发资源的分配可以例如如下图所看到的。


这样安排可以最充分有效地利用公司的开发资源,缓解软件公司对于人力资源不断增加的需求,从而减小成本。另一方面,由于前两个阶段(先启和精化) 的风险较高,咱们仅仅是投入部分的资源,一旦发生返工或是项目目标的改变,咱们也可以将资源浪费降到最低点。在传统的软件开发流程中,对于开发资源的分配基 本上是贯穿整个项目周期而不变的,资源每每没有获得充分有效地利用。

基于这样的资源分配模式,一个典型的项目在项目进度和所完毕的工做量之间的关系可能例如如下表中的数据所看到的。

先启 精化 构建 产品化
工做量 ~5% 20% 65% 10%
进度 10% 30% 50% 10%

3.3 迭代策略
关于迭代计划的安排,一般有下面四种典型的策略模式:

  • 增量式(Incremental)
    这样的模式的特色是项目架构的风险较小(每每是开发一些反复性的项目),因此精化阶段仅仅需要一个迭代。但项目的开发工做量较大,构建阶段需要有屡次迭代来实现,每次迭代都在上一次迭代的基础上添加�实现一部分的系统功能,经过迭代的进行而逐步实现整个系统的功能。
  • 演进式(Evolutionary)
    当项目架构的风险较大时(从未开发过类似项目),需要在精化阶段经过屡次迭代来创建系统的架构,架构是经过屡次迭代的探索,逐步演化而来的。当架构创建时,每每系统的功能也已经基本实现,因此构建阶段仅仅需要一次迭代。
  • 增量提交(Incremental Delivery)
    这样的模式的特色产品化阶段的迭代较多,比較常见的样例是项目的难度并不 大,但业务需求在不断地发生变化,因此需要经过迭代来不断地部署完毕的系统;但同一时候又要不断地收集用户的反馈来无缺系统需求,并经过兴许的迭代来补充实现 这些需求。应用这样的策略时要求系统架构很稳定,能够适应知足兴许需求变化的要求。
  • 单次迭代(Grand Design)
    传统的瀑布模型可以看做是迭代化开发的一个特例,整个开发流程仅仅有一次迭代。但这样的模式有一个固有的弱点,由于它对风险的控制能力较差,每每会在产品化阶段产生一些额外的迭代,形成项目的延误。

这几种迭代策略仅仅是一些典型模式的表明,实际应用中应依据实际状况灵活应用,最多见的迭代计划每每是这几种模式的组合。

3.4 制定项目开发计划
在迭代 化的开发模式中,项目开发计划也是随着项目的进展而不断细化、调整并无缺的。传统的项目开发计划是在项目早期制定的,项目经理老是试图在项目的一開始就制 定一个很具体无缺的开发计划。与之相反,迭代开发模式以为在项目早期仅仅需要制定一个比較粗略的开发计划,因为随着项目的进展,项目的状态在不断地发生变 化,项目经理需要随时依据迭代的结果来对项目计划进行调整,并制定下一次迭代的具体计划。

在RUP中,咱们把项目开发计划分为下面三部分:

  • 项目计划
    肯定整个项目的开发目标和进度安排,包含每一个阶段的起止时间段。
  • 阶段计划
    当前阶段中包括有几个迭代,每一次迭代要达到的目标以及进度安排。
  • 迭代计划
    针对当前迭代的具体开发计划,包含开发活动以及相关资源的分配。

项目开发计划也是全然体现迭代化的思想,每次迭代中项目经理都会依据项目状况来不断地调整和细化项目开发计划。迭代计划是在对上一次迭代结果进行评 估的基础上制定的,假设上一次迭代达到了预约的目标,那么当前迭代仅仅需要解决剩下的问题;假设上一次迭代中留有一些问题尚未解决,则当前迭代还需要继续 去解决这些问题。因此必须注意,迭代是不能重叠的,即你尚未完毕当前迭代时,你决不能进入下一迭代,因为下一次迭代的计划是依据当前迭代的结果而制定 的。


 

Rational开发过程
 

1. 引言
本文对 Rational 软件开发过程(Rational Software Development Process)的原理和结构给出了高度的描写叙述,它是:

  • 迭代的、增量的开发过程
  • 面向对象的开发过程
  • 管理和控制的开发过程

它具备足够的广泛性,可以在规模与应用领域方面,为各个软件产品和项目量身订作。

2.总体软件生命周期

2.1 两种视角
Rational 过程可以从两种不一样而又密不可分的视角来观察:

  • 从管理的视角来看,涉及財务、战略、商业和人文方面
  • 从技术的视角来看,涉及质量、project和设计方法方面

2.2 周期和阶段


从管理的角度,即从业务和经济的角度来看,相应项目的进展,软件的生命周期包括四个主要阶段:

  • 起始阶段(Inception)-- 有一个好的想法:具体构想出终于产品的设想和它的业务案例,肯定项目的范围 。
  • 细化阶段(Elaboration)--计划必要的活动和所需资源,具体肯定功能并设计构架 。
  • 构建阶段(Construction)-- 构建产品, 发展最初的设想、构架和计划,直到一个可以交付给用户的产品(完毕后的设想)完毕。
  • 移交阶段(Transition)-- 将产品移交用户使用,包含:制造、交付、培训、支持、维护,直到用户惬意。

完毕这4个阶段称为一个开发周期, 它产生的软件称做第一代(generation)。 除非产品的生命结束, 一个现有产品可以经过反复下一个一样的起始、细化、构建和移交四阶段,各个阶段的側重点与第一次不一样,从而演进为下一代产品。 这个时期咱们称之为演进(evolution)。最后伴随着产品通过几个周期的演进,新一代产品也不断被制造出来。

好比,演进周期的启动可能由下面这几项触发:用户建议加强功能、用户环境的改变、重要技术的变动,以及应对竞争的需要。


实际中,周期之间会有轻微重叠:起始阶段和细化阶段可能会在上一个周期的移交阶段未结束时就開始了。

2.3. 迭代
从技术的角度来 看,软件开发可以视为一连串的迭代过程,经过这些迭代被开发的软件得以增量演进。 每次迭代都以一个可运行的产品的公布而结束, 该产品多是完整版本号的一个子集,但从project的或用户的角度来看是实用的。 每次公布都伴随一些支持性工件:版本号描写叙述、用户文档和计划等。


一次迭代包含下面活动: 计划、分析、设计、实施和測试。 依据迭代在开发周期中所处位置的不一样,这些活动分别占不一样的比例。

管理角度和技术角度之间是协调的, 而且各个阶段的结束还和各次迭代的结束保持同步。

换句话说,每个阶段可以分为一次或屡次迭代过程。

(注意:本图中每阶段的迭代数目仅为示意)
(注意:本图中每阶段的迭代数目仅为示意)

但是,这两个角度(管理角度和技术角度),不仅不过保持同步,它们还具备一些全然一样的里程碑,它们共同贡献出一些随时间演进的产品和工件。 一些工件不少其它地处于技术方面控制之下,还有一些工件不少其它地处于管理方面的控制之下。见第五节。

这些工件的可用性、工件是否知足所创建的评估标准,是构成里程碑的主要详细元素,比日历牌上的日期提供了多得多的内容。

像周期同样,迭代之间也会有轻微重叠。即第N次迭代的计划和构架在第N-1次迭代还未结束时就開始了。有时候,迭代也会平行进行:一个工做于系统某一部分的小组,可能在某个迭代内没有可交付的工件。

2.4.差异
对于不一样的项目而言,每个阶段的側重点,入口和出口准则,一个开发周期的各个工件,以及各次迭代的数目和长度都会不一样。这主要取决于做为过程判别式的的四个主要项目特征。依照影响程度降序排列,它们是:

  • 业务环境
    • 契约性工做,开发人员基于给定的客户规格说明仅仅为该客户开发软件。
    • 猜測性开发或商业开发,开发人员开发软件以推向市场。
    • 内部项目, 开发人员和客户在同一个机构中。
  • 软件开发工做量的规模:
    依照一些度量标准来肯定,比方 Delivered Source Instructions,或功能点、人-月数,或者仅仅依照成本。
  • 新颖程度:
    对于软件开发组织,这个软件新颖程度怎样有多新,尤为是该软件是否为第二次或更后面的周期。这项差异包含了组织和过程的成熟度、资产、技术水平,当前的技情况,以及诸如组建并培训团队、获取工具及其它资源这种问题。
  • 应用类型,目标领域:
    MIS,命令和控制系统, 嵌入式实时系统, 软件开发环境工具等等, 尤为时详细的应用领域会给开发提出特殊的约束条件:安全性、性能、国际化、内存限制等。
    本文首先描写叙述适用所有类型软件开发的通用过程,而后描写叙述了一些有差异价值的特定过程实例,并列举了几个样例。

2.5工做量和日程安排
各阶段在工做量和时间安排上是不一样的。虽然由于不一样项目类型之间相差会很是大,一个典型的中等规模项目的最初开发周期可以估计为如下的比率:

起始阶段 细化阶段 构建阶段 移交阶段
工做量 5% 20% 65% 10%
日程安排 10% 30% 50% 10%

可以用下图表示:


但是对于一个演进周期来讲,起始阶段和细化阶段可能大大缩减。使用特定工具和技术(如应用程序构建器),构建阶段可以远远小于起始阶段和细化阶段的总和。

3. Rational 过程的各个阶段

3.1. 起始阶段
这个阶段产生一个预測产品的最初设想,并将其转换为一个实际的项目。本阶段的目的是创建一个新产品或一次大的更新的业务案例,并且指定项目的范围。

对于一个新产品的开发,本阶段的主要结果是获得一个"作仍是不作"的决定以进入下一阶段,并投入必定的时间和资金来具体分析构建什么、是否能构建,以及怎样构建。

对于一个现有产品的演进,这会是一个简短的阶段, 主要看用户或客户的要求、问题报告,或是新的技术动态。

对于一个契约性的开发,是否进行项目的决定取决于在特定领域的经验、以及组织在此领域的竞争力和市场状况。这里起始阶段可以归结为一个參加投标的决定,或投标活动自己。该决定多是基于一个现有的研究原型,其结构对终于软件可能合适,也可能不合适。

入口准则:

对于一项需要的描写叙述,可以採用下面形式:

  • 一份最初的设想
  • 一个遗留系统
  • 一份建议请求(An RFP --request for proposal)
  • 先前一代的产品和一个加强要求清单
  • 一些资产(软件, 专门技能, 財务资产)
  • 一个概念原型或实物模型

出口准则:

  • 一个初始的业务案例至少要包括下面内容:
    • 对产品设想的明白表达即核心需求,表述为功能、范围、性能、容量和技术等。
    • 成功标准 (如收入的数目)
    • 最初的风险评估
    • 完毕细化阶段所需的资源估算

一般在初试阶段结束时,咱们将获得:

  • 一个最初的域分析模型(完毕大约10%-20%), 肯定最关键的用例, 并且足以进行进构架工做。
  • 一个最初的构架原型,在这个阶段可以是一个一次性原型

3.2. 细化阶段
本阶段的主要目的是更完全地分析问题域,定义构架并使之稳定,肯定项目的最大风险。这样在本阶段结束时,咱们可以获得一个关于下2个阶段怎样工做的综合计划:

  • 一个基于分析模型的基线产品设想(即最初的需求集合)。
  • 至少对第一次构建迭代的评价准则。
  • 一个基线软件构架。
  • 开发和部署产品的必需资源,尤为是人员和工具。
  • 一份日程安排。
  • 足以对构建阶段的成本、日程安排和质量作出"精确"的评估的一份风险决议。

在这个阶段,创建了一个可运行的构架原型;它至少实现了初始阶段识别出的最关键的用例 ,攻克了项目的最大技术风险;依据范围、规模、风险和项目新颖程度的不一样构架原型需要一次或屡次迭代。这是一个生成高质量代码(这些代码成为架构基线)的 演进原型,但是也不排除开发出一个或几个试探性的、一次性原型,以减小开发的风险:对需求、可行性、人机界面研究、向投资者演示等的精化。在本阶段的结束 时,仍然会产生一个"作仍是不作"的决定, 以肯定是否要真正投资构建这个产品(或參与合同项目的竞标)。

此时产生的计划必定要足够具体,风险也必须充分减小,可以对开发工做的完毕进行精确的成本和日程估算。

入口准则:

  • 前一阶段出口准则所描写叙述的产品和工件
  • 被项目管理者和投资者承认的计划,和细化阶段所需的资源

出口准则:

  • 一份具体的软件开发计划,包括:
    • 更新后的风险评估
    • 一份管理计划
    • 一份人员配置计划
    • 一份显示迭代内容和次数的阶段计划
    • 一份迭代计划,具体计划下次迭代
    • 开发环境和所需的其它工具
    • 一份測试计划
  • 一个基线设想,以对终于产品的一个评估准则的集合的形式
  • 用于评估构建阶段最初的迭代结果的客观、可測量的演进标准
  • 一个域分析模型(80%完毕),对应的构架可以称之为是"完整的"
  • 一个软件构架描写叙述(说明约束和限制)
  • 一个可运行的构架基线

3.3. 构建阶段
本阶段可以划 分为数次迭代,不断充实构架基线,向终于产品逐步演进或增量演进。在每次迭代过程当中,上个阶段(细化阶段)的工件获得扩充和修正, 但它们终于将随着系统向正确和完整的方向的演进而稳定下来。在这个阶段,除了软件自己,还生成一些新的工件:文档(既有内部使用的文档,也有面向终于用户 的文档)、測试床及測试套件、部署附件,以及用于支持下一阶段的部署辅助(好比销售辅助)。

对每次迭代,都具备:

入口准则:

  • 上次迭代的产品和工件。 迭代计划必须阐明迭代的特定目标:
    • 将要开发的新添加�能,覆盖了哪些用例或场景
    • 本次迭代过程当中下降的风险
    • 本次迭代过程当中改动的缺陷

出口准则:

更新后的产品和工件,另外还有:

  • 一个版本号描写叙述文档,记录了迭代的结果
  • 測试用例和依据产品得出的測试结果
  • 一个具体描写叙述下一次迭代的计划
  • 对下一次迭代的客观度量标准

到构建阶段的后期,必须完毕下面工件,及本阶段最后一次迭代额外的出口准则:

  • 一个部署计划,指定必需的事项:
    • 打包
    • 订价
    • 演示
    • 支持
    • 培训
    • 移交策略 (好比一个现有系统的更新计划)
    • 产品 (软盘和手冊)
  • 用户文档

3.4. 移交阶段
移交阶段是将产品交付给终于用户的阶段。 它涉及销售、打包、安装、配置、支持用户社区和作出修正等.

从技术角度来看,伴随本阶段迭代的是一次或屡次公布:`beta' 版公布、正式版公布、修补bug , 或加强版公布。

当用户对产品惬意时,本阶段即告结束。 好比,契约性开发时正式验收, 或者产品有关的所有活动都已结束。 此时,某些积累的资产可以加以整理,觉得下一个周期或其它项目重用。

入口准则:

  • 上一次迭代的产品和工件, 尤为是足够成熟可以交付给用户的软件产品

出口准则:

  • 前一阶段某些文档的更新,以及必要时依据原始及修订后的成功标准,进行"过后"项目性能分析,从而替换原有计划。
  • 一个简短的清单,列出本次开发周期给组织带来的新的资产

3.5. 演进周期
对于重要的演进,咱们应用整个过程递归,仍从起始阶段開始一个新的周期。因为咱们已经有了一个产品,因此比起一个初次开发的产品,起始阶段可能大大缩短。细化阶段也可能缩小范围,而在计划方面的关注程度要大于分析或构架的演进方面。需要指出:周期之间可以略有重叠。

较小的演进可以经过延长移交阶段或添加�一两次迭代来完毕。

移交阶段可以以一个终结过程而结束,即产品再也不演进了,但是为了终结它,需要採取一些特定的动做。

4. Rational过程当中的活动
Rational 过程当中各个阶段的名称(如起始、细化、构建、移交)与描写叙述高级活动的术语(如分析、设计、測试等)相差甚远。 所以咱们easy理解某种活动的进行并不局限于某个特定阶段,也与其它做者、标准及特定领域的所使用的术语无关。这些活动确实发生,但它们在每个阶段和每次迭 代中的程度有所不一样。下图代表了活动重点怎样随时间的推动而发生演进。


图中活动重点的变化也说明虽然每次迭代在形式上都是"相似"的,但它们的性质和内容倒是随时间而改变的。

这还代表,一项活动的结束并不总意味着还有一项活动的開始,即并不是分析完毕了才開始设计,而是这些活动相关的各类"工件"在随着开发人员对问题或需求的理解的加深也不断获得更新。

最后,在一个迭代过程当中,计划、測试和集成这些活动不是集中堆积在开发活动的開始和结束阶段,而是增量地分布在整个开发周期的各个阶段、每次迭代之中。 它们并不表现为开发过程的某个独立的阶段或步骤。

虽然详细的项目有详细的差异,但对于一个中等规模、初次开发的典型项目来讲,其开发周期中各类活动的比比例如如下:

计划与管理 15%
分析/需求 10%
设计/集成 15%
实施/功能測试 30%
度量/评估/验收測试 15%
工具/环境/变动管理 10%
维护(开发过程当中的修补) 5%

5. 生命周期工件
开发过程不是文档驱动的:它的工件中必须一直包含软件产品自身。文档应该十分精简,数目不能太多,应仅仅保留那些确实从管理或技术的角度有真正价值的文档。 Rational 建议保留下面典型的文档集。

5.1管理工件
管理工件不是产品,而是用来驱动或监控项目进展、预计项目风险、调整项目资源,以及使客户或投资者对项目保持必定的"可见性" 的。

  • 一份机构策略文档,是机构开发过程的明文规定。 它包括一个此类项目的实例。
  • 一份远景文档, 描写叙述系统级需求,质量要求和优先级。
  • 一份业务案例文档, 描写叙述財务环境、合同,以及项目的投资回报等等。
  • 一份开发计划文档, 包含总体的迭代计划和当前及最近迭代的具体规划。
  • 一份评估标准文档,包括需求、验收标准及其它特定的技术目标,它们由各个阶段演进的主要"里程碑"组成。包括迭代的目标和验收水平。
  • 每次公布的版本号描写叙述文档。
  • 部署文档, 包括对交付、培训、安装、销售、制造和交割相关的实用信息。
  • 状态评估文档: 项目状态的阶段性"快照", 具备进展、人力、开销、结果、关键风险、活动等的度量标准。

5.2技术工件
它们或者是交付的产品,可运行的软件及手冊,或者是一些用于制造产品的蓝图,这些产品包含软件模型、源码和其它有助于理解和演进产品的project信息。

  • 用户手冊, 在生命周期早期开发。
  • 软件文档, 最好以源码自建文档和模型的形式,当中模型是用合适的CASE工具捕获并维护的这些模型包含用例、类图和过程图等。
  • 一个软件构架文档, 描写叙述软件的整体构架,及它的主要组成元素的分讲解明: 类的分组、类、过程、子系统、关键接口的定义和关键设计决策的根据。

本文第3部分中列举的入口准则和出口准则可以映射到这11类文档之中。

上面介绍的这套文档可以按照详细项目的类型进行扩充和删减,一些文档可以合并。 文档没必要必定是纸张形式---也可以是电子表格、文本文件、数据库、源码的凝视、超文本文档等等---但对应的信息资源必须被清楚地识别,易于訪问,也要保存一些历史记录。

5.3需求
Rational 软件开发过程也不是需求驱动的。 在产品演进的周期中,需求表现为不一样的形式:

  • 业务案例给出了主要约束,可能是些可用的资源。
  • 远景文档从用户角度仅描写叙述了系统的关键需求,它在开发过程当中将缓慢演进。
  • 更具体的需求在第二阶段(细化阶段)以用例和场景的形式进行阐明,并在第三阶段(构建阶段)随着对产品和用户需求了解的加深进一步精化。这些更具体的需求记录在评估标准文档中,它们驱动了构建阶段和移交阶段迭代内容的定义, 并在迭代计划中引用。

6. Rational过程的样例
依照2.4节中所述的差异,Rational 过程採用不一样的形式。 这里有两个极端的样例。

6.1大型契约性软件开发的Rational过程
对这个软件开发项目,Rational 过程分为3个阶段创建招标, 相应3个不一样类型的合同。

  • 一个研究与设计阶段, 包括了生命周期的起始阶段和细化阶段, 一般以风险分担方式投标,举例来讲,成本加奖金合同( cost plus award fee contract ,CPAF)。
  • 一个生产阶段,包括了生命周期的构建和移交阶段, 一般做为一个公司、固定的价格合同(a firm, fixed price contract ,FFP)来投标。
  • 一个维护阶段,相应生命周期的演进阶段,一般做来工做量水平合同( a level of effort contract ,LOE)来投标。

因为用户需要更高的可视性来评估项目,还因为项目涉及大量人员和组织,开发过程应更加正规化,要比小型、内部的项目更加剧视书面工件。第5部分列出的11类文档都以某种形式或名称存在。


6.2小型商业软件产品的Rational过程
在按规模分类的过程家族的还有一端,是小型的商业软件开发。它的流动性更强一些,仅仅有有限的正规性, 表现为一些基本的里程碑和有限的文档集:

  • 一个产品远景 (A product vision)。
  • 一份开发计划,显示资源和日程安排
  • 版本号描写叙述文档,在每次迭代的開始指明本次迭代的目标,在迭代结束时 做为版本号说明(release notes)进行更新。
  • 必要的用户手冊

软件结构、软件设计、开发过程可以经过代码自己或软件开发环境来进行文档化。

 

在项目中集成RUP和XP
概述

咱们集中讨论怎样经过使用两个流行的方法获得过程的恰当级别:Rational Unified Process 或简称 RUP 以及极限编程(XP)。咱们展现怎样在小型项目中使用 RUP 以及 RUP 怎样处理 XP 没有涉及到的领域。两者融合为项目团队提供了所需的指南--下降风险同一时候完毕交付软件产品的目标。

RUP 是由 IBM Rational 开发的过程框架。它是一种迭代的开发方法,基于六个通过行业验证的最佳实践(參见 RUP 附录)。随着时间的推动,一个基于 RUP 的项目将经历四个阶段:起始阶段(Inception)、细化阶段(Elaboration)、构造阶段(Construction)、交付阶段 (Transition)。每个阶段都包含一次或者屡次的迭代。在每次迭代中,您依据不一样的要求或工做流(如需求、分析和设计等)投入不一样的工做量。 RUP 的关键驱动因素就是减小风险。RUP 经过数千个项目中数千名 IBM Rational 客户和合做伙伴使用而获得精化。下图展现了一个典型迭代过程的工做流:

典型迭代流
典型迭代流

做为风险怎样影响过程的一个样例,咱们应该考虑是否需要为业务建模。假设由于对业务的理解中没有考虑到一些重大风险,将致使咱们所构建的系统是错误 的,那么咱们就应该运行一些业务建模工做。咱们需要正式进行建模工做吗?这取决于咱们的涉众--假设一个小团队将非正式地使用结果,那么咱们或许仅仅进行非 正式的记录就可以。假设组织中的其它人也将使用结果或者查看结果,那么咱们可能就要投入更大的努力,并且确保该结果的正确性和可理解性。

您可以定制 RUP 使其知足差点儿不论什么项目的需要。假设没有知足您特定需要的即装即用的过程或路线图,您可以轻松地建立您本身的路线图。路线图描写叙述了该项目怎样计划使用过程, 所以表明了该项目的特定过程实例。这就意味着,RUP 可以按需要变得简单或复杂,咱们将在本文中详解。

XP 是一个用于小型项目中的以代码为中心的轻量级过程(參见 XP 附录)。它来自 Kent Beck 的创意,在大概 1997 年 Chrysler 公司的 C 3 工资单项目中获得软件界的关注。如同 RUP 同样,XP 也是基于迭代的,并且体现了诸如小规模公布、简单设计、測试以及持续迭代几项实践,。XP 为恰当的项目和环境引入了一些有效的技术;只是,当中也存在隐藏的若是、活动和角色。

RUP 和 XP 具备不一样的基本原理。RUP 是过程组件、方法以及技术的框架,您可以将其应用于不论什么特定的软件项目,咱们但愿用户限定 RUP 的使用范围。XP,从还有一方面来讲,是一个具备不少其它限制的过程,需要附加内容以使其适合完整的开发项目。这些不一样点解释了软件开发界的一个观点:开发大型 系统的人员使用 RUP 解决这个问题,而开发小型系统的人员使用 XP 做为解决方式。咱们的经验代表大部分的软件项目都处于二者之间--尽力找寻适用于各自状况的过程的恰当级别。单纯地使用二者之中的一个是不充分的。

当您在 RUP 中融合了 XP 技术时,您会获得过程的正确量,既知足了项目所有成员的需要,又攻克了所有基本的项目风险问题。对于一个工做于高信任环境中的小型项目团队,当中用户是团 队的一部分,那么 XP 全然可以胜任。对于团队愈来愈分散,代码量愈来愈大,或者构架没有很是好定义的状况,您需要作一些其它工做。在用户交互具备"契约"风格的项目中,仅有 XP 是不够的。RUP 是一个框架,您可以从 RUP 出发,在必要时以一组更健壮的技术来扩展 XP。

本文的下面部分描写叙述了一个基于 RUP 四个阶段的小型项目。在每个阶段中,咱们都肯定了所产生的活动和工件 。尽管 RUP 和 XP 具备不一样的角色和职责,但是咱们在这里不会处理这些差别。对于不论什么组织或项目,实际项目成员必须在过程当中与正确的角色关联起来。

项目启动-起始阶段
对于新的开发项目来讲,起始阶段是很是重要的,在项目继续进行前,您必须处理重要的业务与需求风险。对于那些加强现有系统的项目,起始阶段是比較短暂的,但是其目的还是肯定该项目的实施价值及可行性。

在起始阶段中,为了构建软件您可以建立业务案例。视图是起始过程当中的关键工件。它是系统的高级描写叙述。它为每个人解释该系统是什么、可能使用系统的用 户、使用系统的缘由、必须具有的功能,以及存在的约束。视图可能很是短,或许仅仅有一两段。视图每每包含软件必须为客户提供的关键功能。

如下的样例展现了一个项目的很是短视图,该项目对 Rational 的外部站点进行了改造。

为使 Rational 的地位达到电子开发(包含工具、服务和最佳实践)的世界率先程度,可以经过动态的、个性化的站点增强客户关系,为訪问者提供自助服务、支持和目标内容。新的过程和技术启用可以使内容供应商经过一种简化的、本身主动的解决方式加速公布并提升内容的质量。

RUP 起始阶段中 4 个重要活动为:

制定项目的范围。假设咱们打算构建一个系统,咱们需要知道其内容以及它怎样知足涉众的需要。在这个活动中,咱们捕获内容和最重要的需求的足够具体的信息,从而得出产品可接受的标准。

计划并准备业务案例。咱们使用视图做为指导,定义风险缓和策略,开发起始的项目计划,并肯定已知成本、日程计划,以及盈利率平衡。

综合得出备选构架。假设正在计划中的系统没什么新颖性,而且使用的框架广为人之,那么您可以跳过这一步。咱们一旦知道客户的需求,就要開始分配时间 研究可行的备选构架。新技术能够带来解决软件问题的新的并且通过改进的解决方式。在过程的早期花些时间评估购买仍是建立系统,并选择技术,也能够开发出一 个起始原型,这些都可以下降项目的一些主要风险。

准备项目环境。不论什么项目都需要项目环境。不论您使用 XP 技术(好比结对编程),仍是较传统的技术,您都需要肯定团队将要使用的物理资源、软件工具以及步骤。

进行小型项目开发时,并不需要太多的"过程时间"来运行起始过程。您每每可以在几天中或者更少的时间里完毕,如下的内容说明了本阶段除了视图以外的预期工件。

一个经批准的业务案例
涉众有机会 从业务的角度认定项目是值得进行的。RUP 和 XP 都认可最好在早期就得出项目是否值得进行的结论,以避免在一个注定将要失败的项目中花费宝贵的资源。如同在"Planning Extreme Programming" 一书描写叙述的那样,XP 对于项目是怎样造成的以及涉及哪些角色这两个问题的回答是比較模糊的(彷佛在现有项目或系统的环境中是最清晰的),但是在研究阶段,XP 处理的工件与 RUP 起始过程当中的是一样的。

不论您在 XP 中非正式地考虑业务问题,仍是在 RUP 中将业务案例作成一流的项目工件,您都需要考虑这些问题。风险清单您应该在整个项目开发过程当中都保持记录 Risk List(风险清单)。使用有风险清单可以是一个具备通过计划的风险缓和策略的简单清单。为各个风险设定优先级。不论什么与项目有关的人员都可以随时看到风险 的内容以及怎样处理风险,但是没有提供解决风险的通常方式 。

初步项目计划
本计划包含资源估算、规模以及阶段计划。对于不论什么项目,这些估算都是不断变化的,您必须监控它们。

项目验收计划
您的计划正式与否依 赖于项目的类型。您必须推断客户会怎样才干以为您的项目取得了成功。对于一个 XP 项目,客户会採取验收測试的形式。在更广泛的过程当中,客户可能不会真正地进行測试,但是接受的标准必须直接由客户做出,或者由还有一个角色做出,好比与客户 直接接触的系统分析员。也可能存在其它的验收标准,好比建立终于用户文档和帮助,但是XP并不涉及此内容。

起始细化迭代计划
在基于 RUP 的项目中,在上次迭代的最后,您将具体计划下次迭代。在迭代的最后,您可以评估迭代開始时设立的标准。XP 提供了探监控与衡量迭代成功的一些优秀技巧。衡量标准是简单的,您可以轻松地将它们合并到迭代计划和评估标准中。

起始用例模型
尽管这听起来比較正 式而让人望之却步,但是它却至关简单。用例与客户在XP中编写的"故事"相相应。其间的差别就是一个用例就是一套完整的动做,由參与者或系统外部的人员或 事物发起,这正是用例的价值所在。用例可能包含若干个XP"故事"。RUP 为了定义项目的边界,推荐在起始过程当中肯定用户与角色。从用户的观点关注整套操做有助于将系统分为有价值的部分。这有助于断定恰当的实施特性,所以咱们能 够在每次迭代的最后向客户交付一些成果(可能在起始迭代与细化迭代早期除外)。

RUP 与 XP 都可以帮助咱们确保避免一种状况,即整个项目已完毕 80%,但都不是可交付的形式。咱们一直但愿公布的系统对用户都是有价值的。

在这一点上,用例模型在识别用例和參与者方面差点儿没有或仅仅有很是少提供支持的细节。它可以是手工或使用工具绘制的简单的文本或者 UML(统一建模语言)图。该模型帮助咱们确保已经包括了涉众所关心的正确的功能,并且没用忘记不论什么功能,并赞成咱们轻松地查看整个系统。用例依据若干因 素设定优先级,这些因素包含风险、对客户的重要程度以及技术难点。起始阶段中不需要过于正式的或过大的工件。依照您的需求让它们保持简单或者正式就可以。 XP 包含对计划与系统验收的指南,但是 RUP 需要在项目的早期加入�不少其它的一些内容。这些少许加入�可能经过处理一套更完整的风险而为项目提供很是大的价值。

细化阶段
细化阶段的目标是为系统构架设立基线,为在构建阶段大量的设计与实施工做打下坚实的基础。构架经过考虑最重要的需求(那些对系统构架影响最大的需求)与评估风险演进而来。构架的稳定性是经过一个或多个构架原型进行评估的。

在 RUP 中,设计活动主要关注系统构架的概念,对于软件密集型的系统来讲,就是软件构架的概念。使用组件构架是在 RUP 中体现的软件开发 6 项最佳实践当中之中的一个,该实践推荐在开发与所做所为构架上要投入一些时间。在这项工做花费的时间可以减缓与脆弱的、僵化日系统有关的风险。

XP 使用"隐喻"替换了构架的概念。隐喻仅仅捕获构架的一部分,而其他构架部分则随着代码开发的天然结果而演进。XP假定构架的造成是从生成简单的代码開始,而后进行持续的代码重构。

在 RUP 中,构架不只仅是"隐喻"。在细化阶段中,您构建可运行的构架,从中可能减小与是否知足非功能性需求相关的不少风险,好比性能、可靠性以及健壮性。经过阅读 XP文献,很是可能判断出一些 RUP 为细化阶段所描写叙述的内容,尤为是过于 XP 所称的基础设施的过度关注,都是徒劳无功的。XP 以为在没有必要的状况下建立基础设施所作的工做致使了解决方式过于复杂,并且所建立的结果对客户没有价值。在 RUP 中,构架与基础设施不是等同的。

在 RUP 与 XP 中建立构架的方法是大相径庭。RUP 建议您关注构架,避免随时间变化而产生的范围蔓延、添加�项目规模以及採用新技术带来的风险。XP 採用足够简单或是很是好理解的现有构架,该构架能够随着代码而演进。XP 建议您不要为明天而设计,而要为今天而实施。XP 相信假设您尽量地保持设计简单,那么未来管理起来也垂手可得。RUP 但愿您考虑该主张带来的风险。假设系统或者部分系统在将来不得不重写,那么 XP 以为这样的举措比方今就计划这样的可能性更明智而且花费更少。对于一些系统,这是千真万确的,而且使用 RUP 时,在您细化阶段考虑风险也会得出同一结论。RUP 并不以为对于所有系统这都是正确的,而且经验代表对于那些较大型、较复杂和没有先例的系统来讲,这多是灾难性的。

尽管为将来的可能性(可能永远不会生生)花费太多的精力多是一种浪费但是对将来进行足够的关注不失为一件精明之举。多少公司能花得起代价不断重写或者甚至是重构代码呢?

对于不论什么项目,在细化阶段您应该至少完毕这三项活动:

定义、验证并且设定构架的基线。 使 用风险清单从起始阶段开发备选构架。咱们关注是否能够保证构想中的软件具备可行性。假设选定技术对于系统没什么新颖性或者复杂性,这项任务不会花费太长时 间。假设您正在向现有系统中加入�内容,那么假设现有构架不需要进行变动,这项任务就不是必要的。但是当真正出现构架风险时,您并不想让您的架构来"碰运 气"。

做为这项活动的一部分,您可能运行一些组件选择,并且作出决定进行购买/建立/重用组件。假设这需要大量工做,您可以将其分为单独的活动。

精化视图。 在起始 阶段,您开发了一个视图。因为你要肯定项目的可行性,并且涉众有时间检查和评价系统,所以可能要对视图文档及需求做出一些变动。对视图与需求的改动通常在 细化阶段进行。在细化阶段的最后,您已经深入理解了用来构建和计划的最关键的用例。涉众需要获得承认,在当前构架的环境中,仅仅要依照当前的计划开发整个系 统,就能实现当前的设想。在随后的迭代过程当中,变动的数量应该有所下降,但是您可能会在每次迭代中花一些时间进行需求管理。

为构建阶段建立迭代计划并且设定基线 。 现在,可以为您的计划填充细节了。在每次构建迭代的最后,您可以按需要又一次考虑计划并且进行调整。调整过程经常是必需的,因为需要进行的工做每每被错误地 估算,业务环境也会常常变化,有时需求也会发生变动。为用例、场景以及技术工做设定优先级,而后将它们分配到迭代过程当中。在每次迭代过程的最后,您计划产 生一个能够为涉众提供价值的工做产品。

您可以在细化阶段运行其它活动。咱们推荐您创建測试环境并且開始开发測试。尽管具体的代码尚未完毕,但是您仍然可以设计測试,或许可以实施集成測 试。程序猿应该随时准备进行单元測试,并且了解怎样使用项目选定的測试工具。XP 推荐您在编写代码前先设计測试内容。这是个独到的看法,尤为是当您向现有代码主体中加入�内容时。只是,无论您选择怎样进行測试,都应该在细化阶段创建常规 測试体制。

RUP 描写叙述的细化阶段包含 XP 中的研究阶段和投入阶段。XP 处理技术风险(好比新颖性和复杂性)的方式为使用"spike"解决方式,好比花费一些时间进行试验以对工做量进行估算。这样的技术在不少案例中都是有效 的,当较大风险没有体现在单个用例或"故事"中时,您就需要花些工夫确保系统的成功而且对工做量进行精确的估算。

在细化阶段,您会经常更新工件,好比起始阶段的需求与风险清单。在细化阶段可能出现的工件包含:

软件构架文档(SAD)。 SAD 是一个复合型的工件,它提供了整个项目的技术信息的单一来源。在细化阶段的最后,该文档可能会包括具体的介绍,描写叙述在结构上很是重要的用例,并且肯定关键的 机制和设计元素。对于加强现有系统的项目,您可以使用曾经的 SAD,或者假设你认为不会带来什么风险,那么就决定不使用该文档。在所有的状况下,您都应该深思熟虑并且记录于文档中。

构建过程的迭代计划。 您 可以在细化阶段计划构建迭代的次数。每次迭代都有特定的用例、场景以及其它分配的工做项目。这些信息都在迭代计划中有所体现并且设定基线。评审与核准计划 可以做为细化阶段的出口标准的一部分。对于很小的短时间项目来讲,您可以将细化阶段的迭代与起始过程和构建过程合并。关键性的活动仍然可以进行,但是迭代 计划和评审所需的资源都会有所下降。

构建阶段
构建的目标是完毕系统开发。构建阶段从某种意义上来看是一个制造过程,当中重点工做就是管理资源、控制操做以优化成本、日程和质量。从这个意义上来说,管理理念应该进行一个转换,从起始阶段和细化阶段的知识产权开发转换到构建和交付阶段的部署产品的开发。

XP 側重构建阶段。构建阶段是编写产品代码的阶段。XP所有阶段的目的都是为了进行计划,但是 XP 的关注焦点是构建代码。

构建阶段的每次迭代都具备三个关键活动:

管理资源与控制过程。 每个人都需要了解本身的工做内容和时间。您必须保证工做负荷不会超过您的能力,而且工做可以按计划进行。

开发与測试组件。 您构建组件以知足迭代中用例、场景以及其它功能的需要。您对其进行单元測试和集成測试。

对迭代进行评估。 在迭代完毕时,您需要推断是否已经达到了迭代的目标。假设没有,您必须又一次划分优先级并管理范围以确保能够按时交付系统。

不一样类型的系统需要使用不一样的技术。RUP 为软件project师提供了不一样的指导,以帮助他们建立恰当的组件。以用例和补充(非功能)需求的形式提出的需求是足够具体的,可以使project师开展工做。RUP 中的若干活动为设计、实施和測试不一样种类的组件提供了指南。一名有经验的软件project师不需要具体查看这些活动。经验稍欠缺一些的project师可以经过最佳实践得到 很是大的帮助。每个团队成员都可以按需要深刻研究过程或者仅仅是略微了解一下。只是,他们都參照一个单独的过程知识基础。

在 XP 中,"故事"驱动实施过程。在 Extreme Programming Installed 一书中,Jeffries等人以为"故事"是程序猿的"会话承诺"(promises for conversation)。 持续有效的交流大有裨益。尽管老是需要澄清一些细节,假设"故事"不够具体,而使程序猿不能完毕他们大部分工做,那么可以说"故事"尚未就绪。用例必须 足够具体以方便程序猿实施。在不少状况下,程序猿会帮助编写用例的技术细节。Jeffries 等人以为,会话应该记录在文档中并且附加到"故事"中。RUP 也容许这个观点,除了以用例规格说明的形式,可以按需要使用非正式的形式。捕获并管理会话的结果是您必须管理的任务。

XP 的好处在于构建阶段。对于大多数团队来讲,都存在适用于他们的"智慧与指南的结晶"。XP 中最显著的实践包含:

測试--程序猿不断地随着代码的开发编写測试。測试反映了"故事"。XP提倡您首先编写測试,这是一项优秀的实践,因为它可以迫使您深入地理解"故 事",并且在必要的地方提出不少其它的问题。不论在编写代码以前仍是以后,必定要编写測试。将它们添�到您的測试包中,并且保证每次代码变动时都执行測试。

重构--不断重构系统的结构而不改变其行为,可以使其更加简单或灵活。您需要推断对您的团队来讲是否存在一个较好的实践。简单与复杂的判别否因人而 异。有这样一个样例,一个项目中的两个很是聪明的project师每晚都要重写对方的代码,因为他们以为对方的代码过于复杂。这产生了一个反作用,也就是他们老是干扰 次日其它成员的工做。測试是有帮助的,但是假设他们之间不陷入代码之争的话,那么团队的处境就会更好一些。

结对编程--XP 以为结对编程可以在更短的时间内建立出更好的代码。有证据代表这是正确的 。假设您遵守这项实践,就需要考虑不少人文与环境的因素。程序猿愿意对此进行尝试吗?您的物理环境可以知足这样的状况吗,即有足够的空间使两个程序猿在一个 单独工做站中有效地工做?您怎样对待远程工做或者在其它地点工做的程序猿?

持续集成--集成与构建工做需要持续进行,可能天天不止一次。这是一种确保代码结构完整的很是好的方式,它还赞成在集成測试过程当中进行持续的质量监控。

集体代码所有权--不论什么人都可以随时改动不论什么代码。XP 依赖这样一个事实,即一组好的单元測试将会下降这项实践的风险。让你们将每一件事都搞清楚的优势不能局限在必定的尺度上--是 1 万行代码、2 万行代码仍是必定要少于 5 万行?

简单设计--随着重构过程的进行,需要不断地改动系统设计使其变动简单。再一次重申,您需要推断这项工做进行到何种程度才刚好合适。假设您在细化阶段中花费了必要霎时间来设计构架,咱们相信简单的设计将会很是快完毕并且很是快变得稳定。

代码标准--这一直都是一项良好实践。标准是什么都不要紧,仅仅要您使用它们而且每个人都承认就可以。

RUP 与 XP 都以为您必须管理(和控制)迭代过程。衡量标准可以提供较好的计划信息,因为它们可以帮助您选择对于您的团队来讲什么是最适合的。需要衡量三件事:时间、 规模和缺陷。这样您就可以得到所有类型您所感兴趣的统计数字。XP 为您提供简单的衡量标准来推断进展并且预測成果。这些衡量标准环绕着完毕的"故事"数量、经过測试的数量以及统计中的趋势这些问题。XP 为使用最少许的衡量标准作出了一个优秀的表率,因为查看太多并不必定会添加�项目成功的机会。RUP 为您提供了对于您可以衡量的内容以及怎样衡量的指导,并且举了有关衡量标准的样例。在所有的状况中,衡量标准必须简单、客观、易于搜集、易于表达,并且不 易产生误解。

在构建阶段的迭代过程当中将会产生哪些工件呢?这取决于迭代是处于构建阶段的早期仍是后期,您可以建立下面工件:

组件--组件表明了软件代码中的一部分(源码、二进制代码或者可运行程序),或者包括信息的文件,好比,一个启动文件或者一个 ReadMe 文件。组件还可以是其它组件的聚合,好比由几个可运行程序组成的应用程序。

培训资料--假设系统的用户界面比較复杂,那么请在用例的基础上尽早编写用户手冊和其它培训资料的初稿。

部署计划--客户需要一个系统。部署计划描写叙述了一组安装、測试并且有效地向用户交付产品所需的任务。对于 以Web 为中心的系统来讲,咱们已经发现,部署计划的重要性又提升了。

交付阶段迭代计划--临近交付时,您需要完毕并且评审交付阶段迭代计划。

代码完整吗?
以为代码就是设计并且设计也就是代码。代码与自身老是一致的,这一点是千真万确的。咱们以为花费精力进行设计并且沟通设计是很是值得的,而不不过建立代码。如下的小故事会说明这一点。

RUP 与 XP 间的差别除了创建构架的方法之外,还包含其它方面的不一样。当中一点就是关于设计概念的沟通方式。XP

一名project师曾有两次这种软件项目经历,设计体现在代码中,并且仅仅能在代码中找到设计信息。这两个项目都是关于编译器的:一个是改进与维护用于 Ada 编译器的优化程序,还有一个项目是将一个编译器的前端移植到一个新的平台上,并且链接一个第三方的代码生成器。

编译器技术是比較复杂的,但也是广为人知的。在这两个项目中,该project师想要概览编译器(或者优化程序)的设计和实施。在每个案例中,他都接到一堆源 代码清单,大概有几英尺厚,而且被告知"查看这些信息"。他本应被提供一些带有支持性文字的构建很是好的图。优化程序的项目没有完毕。但是编译器项目确实取 得了成功,由于在代码开发过程当中进行了普遍的測试,因此代码质量很是高。这位project师花费了数天时间研究调试器中的代码以弄明确其做用。我的的损失尚在其次, 团队的损失代价就更不值得。咱们并无按 XP 所看到的的那样在 40 小时后完毕开发,咱们反而花费了大量我的努力来完毕工做。

仅仅开发代码带来的主要问题就是无论代码文档编写得多么好,它都没有告诉您它自己要解决的问题,它仅仅提供了问题的解决方式。一些需求文档在最初用户和 开发者继续工做很是长时间之后,仍然可以很是好地解释项目的原始目标。为了维护系统,您每每需要了解最初项目团队的设计目标。一些高级设计文档都是相似的 --代码经常没有通过高度的抽象,因此没法提供不论什么信息以代表整体的系统能够实现什么功能。在面向对象的系统中,这一点尤为是正确的,因为只查看里面的 类文件是很是难甚至没法得出运行线程。设计文档指导您在后期出现故障时该查看的内容--在后期经常会出现故障。

这个故事说明花费时间建立与维护设计文档确实会有所帮助。这可以减小误解的风险,并且加速开发过程。XP 的方式就是花费几分钟勾画出设计的大概内容或者使用 CRC 卡片。 但是团队不主张这样,而仅仅是进行代码开发。他们有一个隐含的若是,那就是任务很是easy,咱们已经知道该怎样进行了。即便咱们成功地完毕了任务,那么下一个新 来的人可能就不会如此幸运。RUP建议您多花费一些时间建立并维护这些设计工件。

交付阶段
交付阶段的焦点就是确保软件对于终于用户是可用的。交付阶段包含为公布进行产品的測试,在用户反馈的基础上作微小的调整等几方面内容。在生命周期的这个时刻,用户反馈主要集中在精确调整产品、配置、安装,以及可用性等问题上。

较早公布、经常性公布都是很是好的办法。但是,咱们经过公布要达到的目的是什么呢?XP 没有清楚地解释这个问题,也没有处理公布商业软件所必须制造问题。在内部项目中,您可以为解决这些问题找到捷径,但是即便这样,您仍然需要编辑文档、员工 培训等工做。那么技术支持与变动管理又怎样呢?但愿现场客户控制这些内容,这是可行的吗?Bruce Conrad 在他的 XP 的 InfoWorld 评论 中指出用户并不但愿获得的软件老是在持续变动。您必须对高速变动软件的利益和变动的劣势及可能带来的不稳定性进行权衡。

当您决定公布的时候,您必须为终于用户提供比代码多得多的东西。交付阶段的活动和工件会指导您完毕本部分软件开发过程。这些活动主要是为了向您的客户提供可用的产品。交付阶段的关键活动例如如下:

肯定终于用户支持资料。该活动比較简单,您仅仅需提供一个清单就能够。但是务必要确保您的组织已准备好对客户进行技术支持。

在用户的环境中測试可交付的产品。假设您能够在公司内部模拟用户环境,那是最好只是的。不然,就到客户的公司去,安装软件并且保证其能够执行。您必定不想尴尬地回答客户:"但是在咱们的系统上工做很是正常。"

基于用户反馈精确调整产品。假设可能的话,在您向有限数量客户交付软件时计划一次或者屡次 Beta 測试周期。假设进行该測试,那么就需要对 Beta 測试周期进行管理,并且考虑您"收尾工做"中的客户反馈。

向终于用户交付终于产品。对于不一样类型的软件产品和公布版本号,需要处理不少有关打包、制造和其它产品问题。您确定不会只将软件拷贝到一个目录中,而后向客户发一封邮件告诉他们软件已经到位了。

与其它阶段同样,过程的格式与复杂度都有所不一样。只是,假设您没有注意部署细节,那么可能致使数周或数月的良好开发工做前功尽弃,从而在进入目标市场时以失败了结。

在交付阶段中您可以生成若干工件。假设您的项目涉及到未来的公布(有多少项目没有涉及到呢?),那么您就应该開始为下次公布肯定功能和缺陷。对于不论什么项目,下列工件都相当重要:

部署计划--完毕您始于构建阶段的部署计划并且将其做为交付的路线图。

版本号凝视--它是一个比較少见的软件产品,不包括对终于用户相当重要的指令。可以对其作出计划,对于凝视要有一个可用的、一致的格式。

交付阶段资料与文档--这类资料可以採取很是多形式。您可以在线提供所有内容吗?您会进行指导吗?您的产品帮助完整并且可用吗?不要以为您所了解的,客户也相同了解。您的成功就在于帮助您的客户取得成功。

结束语
构建软件的工做远远多于编 写代码所工做。一个软件开发过程必须集中处理向用户公布高质量软件的所有必需活动。一个完整的过程没必要是庞大的。咱们经过集中论述项目中的主要活动和工 件,已经向您展现了怎样进行一个小型但是完整的过程。假设运行某项活动或者建立某个工件对于缓解项目中的风险是有帮助的,那么就请进行。您可以按需要为您 的项目团队和组织使用或多或少的过程和格式。

RUP 和 XP 并没必要是互相排斥的。经过结合使用这两种方法,您全然可以获得一个过程,帮助您比方今更快地交付更高质量的软件。Robert Martin 描写叙述了一个叫作 dX 的过程,他将其做为 RUP 的附属品 。它就是一个从 RUP 框架中构建的过程的实例。

一个优秀的软件过程可以使用经业界验证的最佳实践。最佳实践已经在真实的软件开发组织中使用,并且经历了时间的考验。XP 是眼下广为关注的方法。它以代码为中心,并提供了一项承诺:花费最少的过程开销获得最大的生产力。XP 中的不少技术值得在恰当的状况中考虑和採用。

XP 关注"故事"、測试和代码--它以必定的深度讨论了计划,但没有具体阐述怎样获取计划。XP 意味着您可以完毕其它一些工做,好比"使用一些卡片进行 CRC 设计或者草拟某种 UML……"或者"请不要生成并不使用的文档或者其它工件",但仅仅是一带而过。RUP 但愿您在定制和更新开发计划时,只考虑建立实用和必须的东西,并且指出了这些东西该是什么。

RUP 是一个可以处理整个软件开发周期的过程。它关注最佳实践,并且通过了数千个项目的洗礼。咱们鼓舞研究和发明新的技术以产生最佳实践。随着新的最佳实践崭露头脚,咱们但愿将它们归入 RUP 中。

附录:Rational Unified Process
Rational Unified Process,或者简称 RUP,提供了软件开发的规律性方法。它是由IBM Rational开发并维护的过程产品。它为来同类型的项目提供了几种即装即用的路线图。RUP 还提供了一些信息,帮助您在软件开发过程当中使用其它 Rational 工具,但是它不要求将 Rational 工具备效地应用于整个组织,您也可以将 Rational 工具与其它供应商的产品进行集成。

RUP 为软件项目所有方面提供了指导。并不需要您运行不论什么特定的活动或者建立不论什么特定的工件。它仅仅为您提供信息和指南,您可以决定将哪些应用于您的组织。假设没有特定的路线图适合您的项目或者组织,RUP 还提供了一些指南来帮助您量身定作你的过程。

RUP 强调採用现代软件开发的一些最佳实践,做为一种减小开发新软件所带来的内在风险的方式。这些最佳实践包含:

1. 迭代开发
2. 管理需求
3. 使用基于组件的构架
4. 可视建模
5. 持续的质量验证
6. 控制变动

这些最佳经验融合到 Rational Unified Process 的下面定义中:

角色--运行的系列活动和拥有的工件。
学科--软件project中的关键领域,好比需求、分析与设计、实施与測试。
活动--工件生成与评估方式的定义。
工件--在运行活动中所使用的、生成的或改动的工做产品。

RUP 是一个迭代过程,肯定了不论什么软件开发项目的四个阶段。随着时间的推动,每个项目都要经历起始阶段、细化阶段、构建阶段和交付阶段。每个阶段包含一次或屡次 迭代,当中您可以生成可运行文件,但是系统可能不完整(可能起始阶段除外)。在每次迭代过程当中,您以不一样的细节级别运行几个学科中的活动。下文是 RUP 的概述图。

RUP 概览图
RUP 概览图

The Rational Unified Process, An Introduction, Second Edition 一书是 RUP 的好的概述。您可以在 Rational 的 Web 网站 www.rational.com 上找到更进一步的信息和对于 RUP 的评价。

附录:极限编程
极限编程(XP) 是由 Kent Beck 在 1996 年开发的一种软件开发学科。它基于四个价值:沟通、简单、反馈和勇气。它强调客户与开发团队成员的持续沟通,在开发进程中设立一名现场客户。该现场客户决 定建立的内容和顺序。经过持续重构代码并建立最小的非代码工件集合而体现简单。不少短时间公布和持续单元測试创建了反馈机制。勇气意味着完毕正确的事情,即 使并不是最流行的事情。它还意味着诚实面对您能作的和不能作的事情。

12 个 XP 实践为这四个价值提供支持。它们是:

有计划的开发:经过结合使用优先级"故事"和技术估算,肯定下一版本号的功能。

小版本号:以小的增量版本号经常向客户公布软件。

隐喻:隐喻是一个简单、共享的"故事"或描写叙述,说明系统怎样工做。

简单设计:经过保持代码简单从而保证设计简单。不断的在代码中寻找复杂点并且立马进行移除。

測试:用户编写測试内容以对"故事"进行測试。程序猿编写測试内容来发现代码中的不论什么问题。在编写代码前先编写測试内容。

重构:这是一项简化技术,用来移除代码中的反复内容和复杂之处。

结对编程:团队中的两个成员使用同一台计算机开发所有的代码。一我的编写代码或者驱动,还有一我的同一时候审查代码的正确性和可理解性。

集体代码所有权:不论什么人都拥有所有的代码。这就意味这每个人都可以在不论何时变动不论什么代码。

持续集成:天天屡次建立和集成系统,仅仅要不论什么实现任务完毕就要进行。

每周 40 个小时:程序猿在疲劳时没法保证最高效率。连续两周加班是绝对不一样意的。

现场客户:一名真实的客户全时工做于开发环境中,帮助定义系统、编写測试内容并回答问题。

编码标准:程序猿採用一致的编码标准。

浅谈測试驱动开发(TDD)
 

測试驱动开发(TDD)是极限编程的重要特色,它以不断的測试推进代码的开发,既简化了代码,又保证了软件质量。本文从开发者使用的角度,介绍了 TDD 优点、原理、过程、原则、測试技术、Tips 等方面。

背景
一个高效的软件开发过程 对软件开发者来讲是相当重要的,决定着开发是痛苦的挣扎,仍是不断进步的喜悦。国人对软件蓝领的不屑,对繁琐冗长的传统开发过程的不耐,使大多数开发人 员无所适从。近期兴起的一些软件开发过程相关的技术,提供一些比較高效、有用的软件过程开发方法。当中比較基础、关键的一个技术就是測试驱动开发 (Test-Driven Development)。尽管TDD光大于极限编程,但測试驱动开发全然可以单独应用。如下就从开发者使用的角度进行介绍,使开发者用最少的代价尽 快理解、掌握、应用这样的技术。如下分优点,原理,过程,原则,測试技术,Tips等方面进行讨论。

1. 优点
TDD的基本思路就是经过測试来推进整个开发的进行。而測试驱动开发技术并不只仅是单纯的測试工做。

需求向来就是软件开发过程当中感受最很差明白描写叙述、易变的东西。这里说的需求不只仅是指用户的需求,还包含对代码的使用需求。很是多开发者最惧怕的就是 后期还要改动某个类或者函数的接口进行改动或者扩展,为何会发生这种事情就是因为这部分代码的使用需求没有很是好的描写叙述。測试驱动开发就是经过编写測试 用例,先考虑代码的使用需求(包含功能、过程、接口等),而且这个描写叙述是无二义的,可运行验证的。

经过编写这部分代码的測试用例,对其功能的分解、使用过程、接口都进行了设计。而且这样的从使用角度对代码的设计一般更符合后期开发的需求。可測试的要求,对代码的内聚性的提升和复用都很故意。所以測试驱动开发也是一种代码设计的过程。

开发者一般对编写文档很厌烦,但要使用、理解别人的代码时一般又但愿能有文档进行指导。而測试驱动开发过程当中产生的測试用例代码就是对代码的最好的解释。

快乐工做的基础就是对本身有信心,对本身的工做成果有信心。当前很是多开发者却经常在操心:“代码是否正确?”“辛苦编写的代码还有没有严重 bug?”“改动的新代码对其它部分有没有影响?”。这样的操心甚至致使某些代码应该改动却不敢改动的地步。測试驱动开发提供的測试集就可以做为你信心的来 源。

固然測试驱动开发最重要的功能还在于保障代码的正确性,能够迅速发现、定位bug。而迅速发现、定位bug是很是多开发者的梦想。针对关键代码的測试集,以及不断无缺的測试用例,为迅速发现、定位bug提供了条件。

个人一段功能很是复杂的代码使用TDD开发完毕,真实环境应用中仅仅发现几个bug,而且很是快被定位解决。您在应用后,也必定会为那种自信的开发过程,功能不断添加�、无缺的感受,迅速发现、定位bug的能力所感染,喜欢这个技术的。

那么是什么样的原理、方法提供上面说的这些优势哪?如下咱们就看看TDD的原理。

2. 原理
測试驱动开发的基本思想就是在开发功能代码以前,先编写測试代码。也就是说在明白要开发某个功能后,首先思考怎样对这个功能进行測试,并完毕測试代码的编写,而后编写相关的代码知足这些測试用例。而后循环进行加入�其它功能,直到完全部功能的开发。

咱们这里把这个技术的应用领域从代码编写扩展到整个开发过程。应该对整个开发过程的各个阶段进行測试驱动,首先思考怎样对这个阶段进行測试、验证、考核,并编写相关的測试文档,而后開始下一步工做,最后再验证相关的工做。下图是一个比較流行的測试模型:V測试模型。

【图 V測试模型】

在开发的各个阶段,包含需求分析、概要设计、具体设计、编码过程当中都应该考虑相相应的測试工做,完毕相关的測试用例的设计、測试方案、測试计划的编 写。这里提到的开发阶段仅仅是举例,依据实际的开发活动进行调整。相关的測试文档也不必定是很具体复杂的文档,或者什么形式,但应该养成測试驱动的习惯。

关于測试模型,还有X測试模型。这个測试模型,我以为,是对具体阶段和编码阶段进行建模,应该说更具体的描写叙述了具体设计和编码阶段的开发行为。及针对某个功能进行相应的測试驱动开发。

【图 X測试模型】

基本原理应该说很easy,那么怎样进行实际操做哪,如下对开发过程进行具体的介绍。

3. 过程
软件开发其它阶段的測试驱动开发,依据測试驱动开发的思想完毕相应的測试文档就能够。如下针对具体设计和编码阶段进行介绍。

測试驱动开发的基本步骤例如如下:

1) 明白当前要完毕的功能。可以记录成一个 TODO 列表。

2) 高速完毕针对此功能的測试用例编写。

3) 測试代码编译不经过。

4) 编写相应的功能代码。

5) 測试经过。

6) 对代码进行重构,并保证測试经过。

7) 循环完毕所有功能的开发。

为了保证整个測试过程比較快捷、方便,一般可以使用測试框架组织所有的測试用例。一个免费的、优秀的測试框架是 Xunit 系列,差点儿所有的语言都有相应的測试框架。

开发过程当中,一般把測试代码和功能代码分开存放,这里提供一个简单的測试框架使用样例,您可以经过它了解測试框架的使用。如下是文件列表。

	project/				项目主文件夹
project/test 測试项目主文件夹
project/test/testSeq.cpp 測试seq_t 的測试文件,对其它功能文件的測试文件复制后改动就能够
project/test/testSeq.h
project/test/Makefile 測试项目的 Makefile
project/test/main.cpp 測试项目的主文件,不需要改动
project/main.cpp 项目的主文件
project/seq_t.h 功能代码,被測试文件
project/Makefile 项目的 Makefile

主要流程基本如此,但要让你的代码很是easy的进行測试,全面又不繁琐的进行測试,仍是有很是多測试原则和技术需要考虑。

4. 原则
測试隔离。不一样代码的測试应该相互隔离。对一块代码的測试仅仅考虑此代码的測试,不要考虑事实上现细节(比方它使用了其它类的边界条件)。

一顶帽子。开发者开发过程当中要作不一样的工做,比方:编写測试代码、开发功能代码、对代码重构等。作不一样的事,承担不一样的角色。开发者完毕相应的 工做时应该保持注意力集中在当前工做上,而不要过多的考虑其它方面的细节,保证头上仅仅有一顶帽子。避免考虑无关细节过多,无谓地添加�复杂度。

測试列表。需要測试的功能点很是多。应该在不论什么阶段想加入�功能需求问题时,把相关功能点加到測试列表中,而后继续手头工做。而后不断的完毕相应的測试用例、功能代码、重构。一是避免疏漏,也避免干扰当前进行的工做。

測试驱动。这个比較核心。完毕某个功能,某个类,首先编写測试代码,考虑其怎样使用、怎样測试。而后在对其进行设计、编码。

先写断言。測试代码编写时,应该首先编写对功能代码的推断用的断言语句,而后编写对应的辅助语句。

可測试性。功能代码设计、开发时应该具备较强的可測试性。事实上遵循比較好的设计原则的代码都具有较好的測试性。比方比較高的内聚性,尽可能依赖于接口等。

及时重构。无论是功能代码仍是測试代码,对结构不合理,反复的代码等状况,在測试经过后,及时进行重构。关于重构,我会另撰文具体分析。

小步前进。软件开发是个复杂性很是高的工做,开发过程当中要考虑很是多东西,包含代码的正确性、可扩展性、性能等等,很是多问题都是因为复杂性太大致使 的。极限编程提出了一个很好的思路就是小步前进。把所有的规模大、复杂性高的工做,分解成小的任务来完毕。对于一个类来讲,一个功能一个功能的完毕,如 果太困难就再分解。每个功能的完毕就走測试代码-功能代码-測试-重构的循环。经过分解减小整个系统开发的复杂性。这种效果很明显。几个小的功能代码 完毕后,大的功能代码差点儿是不用调试就可以经过。一个个类方法的实现,很是快就看到整个类很是快就完毕啦。原本感受很是多特性需要添加�,很是快就会看到没有几个 啦。你甚至会为这个速度感到震惊。(我理解,是大幅度下降调试、出错的时间产生的这样的速度感)

5. 測试技术

5.1. 測试范围、粒度
对 哪些功能进行測试?会不会太繁琐?何时可以中止測试?这些问题比較常见。按大师 Kent Benk 的话,对那些你以为应该測试的代码进行測试。就是说,要相信本身的感受,本身的经验。那些重要的功能、核心的代码就应该重点測试。感到疲劳就应该停下来休 息一下。感受没有必要更具体的測试,就中止本轮測试。

測试驱动开发强调測试并不该该是负担,而应该是帮助咱们减轻工做量的方法。而对于什么时候中止编写測试用例,也是应该依据你的经验,功能复杂、核心功能的代码就应该编写更全面、仔细的測试用例,不然測试流程就能够。

測试范围没有静态的标准,同一时候也应该可以随着时间改变。对于開始没有编写足够的測试的功能代码,随着bug的出现,依据bug补齐相关的測试用例就能够。

小步前进的原则,要求咱们对大的功能块測试时,应该先分拆成更小的功能块进行測试,比方一个类A使用了类B、C,就应该编写到A使用B、C功能的測 试代码前,完毕对B、C的測试和开发。那么是否是每个小类或者小函数都应该測试哪?我以为没有必要。你应该运用你的经验,对那些可能出问题的地方重点測 试,感受不可能出问题的地方就等它真正出问题的时候再补測试吧。

5.2. 怎么编写測试用例
測试用例的编写就用上了传统的測试技术。

  • 操做过程尽可能模拟正常使用的过程。
  • 全面的測试用例应该尽可能作到分支覆盖,核心代码尽可能作到路径覆盖。
  • 測试数据尽可能包含:真实数据、边界数据。
  • 測试语句和測试数据应该尽可能简单,easy理解。
  • 为了不对其它代码过多的依赖,可以实现简单的桩函数或桩类(Mock Object)。
  • 假设内部状态很复杂或者应该推断流程而不是状态,可以经过记录日志字符串的方式进行验证。

6. Tips
很是多朋友有疑 问,“測试代码的正确性怎样保障?是写測试代码仍是写測试文档?”这样是否是会陷入“鸡生蛋,蛋生鸡”的循环。事实上是不会的。一般測试代码通常是很easy 的,一般环绕着某个状况的正确性推断的几个语句,假设太复杂,就应该继续分解啦。而传统的开发过程一般强调測试文档。但随着开发节奏的加快,用户需求的不 断变化,维护高层(需求、概要设计)的測试文档可以,更低层的測试文档的成本的确太大了。而且可实时验证功能正确性的測试代码就是对代码最好的文档。

软件开发过程当中,除了遵照上面提到的測试驱动开发的几个原则外,一个需要注意的问题就是,谨防过分设计。编写功能代码时应该关注于完毕当前功能点, 经过測试,使用最简单、直接的方式来编码。过多的考虑后期的扩展,其它功能的加入�,无疑添加�了过多的复杂性,easy产生问题。应该等到要加入�这些特性时在进 行具体的測试驱动开发。到时候,有整套測试用例作基础,经过不断重构很是easy加入�相关特性。

公布时间:2005-8-17
相关文章
相关标签/搜索