【IT168 技术文章】
随着信息技术的迅猛发展,今天的IT从业人员正处于这样一种进退两难的境地:一方面,根据以往的痛苦开发经历,他们知道如果采用杂凑的作坊模式来开发复杂的、高质量的信息系统具有太大的风险;另一方面,他们也同样知道,形式化的、戒律森严的软件工程方法(典型情况下是与ISO9000和SEI-CMM相关的)又常常是官僚主义和耗费时间的,不可能满足目前高度竞争的“Internet时代”环境下对于进度方面不断增长的挑战性要求。显然,如何使得企业在保证软件质量的前提下,同时又能够适应快速变化的市场需求,无疑是业内人士关注的焦点。为此,本文从市场驱动的IT开发特点分析入手,对目前国际上正日趋成熟的“轻”方法和满意质量的内涵和操作加以讨论,同时以快速应用开发为实例介绍了具体操作及注意事项,为读者进一步深入理解现代软件工程实践工作提供帮助。
一、市场驱动的IT开发工作
当今的IT企业正处于一种前所未有的竞争环境之中,无论是作为独立软件供应商还是增殖服务商,也无论是开发直接面向市场的软件产品如游戏、工具、多媒体等等,还是为用户定制软件如电子商务应用、MIS等等,市场竞争都无处不在,IT开发工作被迫在市场驱动的状态进行,具有以下典型特征:
快速演变升级的基础技术,必须及时跟踪基础技术的革新并调整策略。
持续的竞争,必须不断推陈出新来满足用户需求。
时间就是金钱——需要在时间、质量、费用之间达成折衷。
从业人员聪明且教育程度高,能够在一定范围内进行自我管理。
以往流行于IT行业的设计—评审—构造模型已过时。IT业最新的技术和工具改变了以前项目运行所必须遵循的逻辑顺序。比如:现在一些工具允许“即时”创建屏幕,使得冗长的设计—评审—构造模型不再适用,而要求一种更难于计划的原型—审核—构造—再审核—再构造的过程。
角色重叠:现代技术和工具使原来专门的设计、分析、编码人员之间严格的区分界限变的模糊。
以往的IT开发人员相对于当前市场驱动下的开发人员而言,至少拥有以下优势:控制他们的应用开发技术。在传统的企业应用开发中,机器配置和其他系统元素在实现阶段就被指定。现在,这种优势不复存在,很少有哪个系统被实现为在专用机器上的孤立应用。相反,他们经常是企业用户机器上的另一种应用,必须与其他商业应用程序联合使用,这使得IT开发人员不得不为保持与CORBA、Internet、或数据库标准的变化相一致而疲于奔命。同时,持续的竞争、紧迫的进度和严格的预算让IT开发经理不得不经常根据销售人员或客户的要求而调整开发工作。
显然,市场驱动的新环境给IT开发带来新的挑战,如果照搬套用以往的成功经验和开发模式并非明智之举,必须适应新形势的要求,重新思考和定位。
二、“轻”方法浮出水面
随着软件工业不断发展,各种各样的模型不断涌现或退出历史舞台。早期从不同角度提出的各种设计表示方法(常常以发明者的名字来命名)目前似乎已经聚合成为UML这种被广泛接受的标准,结构化设计方法也正在让位于面向对象设计等更受欢迎的方法学,这种变化在更高层次的全局性开发方法学方面同样进行着。
传统意义上的软件方法学描述通常“能够”处理任何大小的项目,而实际上真正的困难就来自于如何对这些方法加以裁剪以适合较小的项目。针对这种理论与实际的脱节现象,国际上一些著名的软件工程专家提出所谓“重(heavy)”方法和“轻(light)” 方法之分,试图为快速发展的软件工业探寻更切合实际的解决方法。
所谓“重”方法,就是指形式化的、戒律森严的软件工程方法学——不仅指这些方法所生成纸文档重量,还意指管理资源投入、QA评审的程度和开发人员被要求遵守的严格流程。相对的,诸如快速应用开发(Rapid Application Development,简记为RAD)和原型方法等则可以被称为“轻”方法——不仅是因为这些方法倾向于产生最小数量的纸文档,还因为其将管理资源投入最小化。不幸的是,1990年代的许多RAD项目在方法学上采取了过“轻”的处理以至于几乎不存在什么方法,这些项目常常退化为杂凑式作坊开发,实质上根本没有任何文档。 显然,需要在两种极端方法之间找到平衡点。
轻方法代表了一种有意识的风险防护方法,依据不同风险在与开发相关的各种活动中投入相应时间、资金和资源。例如,进行多少需求分析工作才算是过多,拟或过少?针对一个几百个需求的开发项目而言,一个需求分析“轻”方法(requirements-light approach)可能是由将每一个需求通过一个简洁的句子加以文档化的行为所组成,一个需求分析“中”方法(requirements-medium approach)可能要求对每个需求通过一段描述性文本来文档化,而一个需求分析“重”方法(requirements-heavy approach)则可能要求详细的UML模型、数据元素定义和每个对象方法的形式化描述。
究竟选择需求分析的“轻”方法还是“重”方法很大程度上受到公司产品上市时间或合同期限压力的影响。同时,公司雇员的流动率也是一种影响因素:作为形式化开发过程的理由之一认为,如果有一份详细的文档来记录需求、设计和编码,那么一旦在项目进行中关键开发成员离职所造成的混乱将会被尽量减小。然而,尽管1970年代和1980年代的系统生命周期预期为十年或二十年,也许Interbet时代的网络公司更愿意正式承诺其电子商务应用仅持续一年,然后被废弃或完全重写。如果正是这种情况,并且如果下一代应用预期与当前应用存在质的差异,那么仅仅为了达到SCM-CMM三级就遵循需求分析“重”方法还真的有意义吗?
同样地,针对设计和测试工作采用什么样的形式化和严格程度才是合适的呢?与项目管理有关的时间汇报、进展汇报、状态会议及其他常见活动又如何呢——尤其针对那些仅持续一周或两周的项目?这些问题总是相互关联的,但是一些传统上被接受的答案却需要至少每隔几年重新审视一下,因为成本-收益参数正在随着商业环境、技术和软件开发人员的变化而不断变化。
轻方法还重新审视了历史上有关投入资源在需求分析的假定,以及投入资源在过程改进的假定。1981年Barry Boehm在他的经典著作“软件工程经济学”(Software Engineering Economics)中指出了一项惊人发现,即如果我们在项目的系统分析阶段引入一个缺陷的话,那么在项目的分析阶段发现这个缺陷会比允许这个错误直至进入设计阶段才被发现节省约10倍资源。但是Boehm在此做了一个在新千年的头十年中未必依然正确的基本假定:仅当该缺陷在生命周期某阶段发生时可通过某种方式加以鉴别,那么这种数量级增长关系图才是相关的。在今天的环境中,这个前提假定在许多商业条件下都是不成立的。比如,当Bill Gates阐明对于浏览器IE的需求时,可能他会说“就象Netscape Navigator那样,但要更好”,可能Netscape的Marc Andreesen也会这样想:“我希望使Navigator就象Mosaic一样,但要更好。”但是当Tim Berners-Lee在构建WWW的初始版本和浏览器的第一个草样时又该如何考虑呢?让他写出详细需求的意义何在呢?
与此同时,重方法的倡导者争辩说,如果一个缺陷在开发阶段就被发现,那么就不应当责备引入该缺陷的个人,而应重新检查允许该缺陷发生的过程本身。但此处又有一个基本假设,也就是说,我们值得投入资源在鉴别一个过程中潜在缺陷的唯一理由是我们希望再次使用同样的过程——因为我们的下一个项目将会与上一个项目足够相似,很自然就应使用同样的过程。但是现在事物变化是如此之快,以至于完全不能保证第N+1个项目会与第N个项目有任何相似之处。因此,昨天的过程可能不得不为了明天的需求而发生实质性变化,换言之,也许只有投资于过程中的重要缺陷才是值得的,因为一些细节仅针对某个特定项目才有意义。
当然,仍然有一些环境需要我们继续依赖于旧的、基本的软件工程原理,在这些环境中重方法被证实依然正确。但是我们应当扪心自问,隐藏在这些原理背后的前提假定是否依然合理。对于许多今天的项目而言,一些根本性的前提假定需要加以改变,而轻方法将是具有最优性能价格比的方法。
可以看出,轻方法的基本思路是试图在项目范围、成本、时间和质量之间达成一种平衡,其关键是在足够的管理可见度、足够的灵活性和足够快的开发速度以完成工作之间找到这种平衡,必须严格审查你想要对项目加入或删除的控制手段的价值何在。尽管我们可以将某个公布于众的开发方法作为基础进行裁剪,但必须深入理解你要执行的每个步骤的理由,尤其在项目的初始规划阶段,就应明确定义开发方法,确保项目团队成员的参与和认可,并以满足项目的商业需求为目标。
三、满意质量框架
满意质量(Good Enough Quality,简记为GEQ)是与“轻”方法相呼应的新思路,同时也是一个存在很大争议和误解较深的概念,近年来受到越来越多的关注,其理论基础正在不断走向成熟,本节对其进行深入探讨。
满意质量的提法最初主要源自软件项目的直接参与人员,而不是那些制定软件过程或提供咨询的人士,在软件工程学术界则更是缺乏相关研究。这种情况导致了相关概念的滥用,满意质量常被用来为软件中明显存在的缺陷做辩解,甚至有人认为软件供应商在软件产品中保留错虫是一种蓄意行为甚至是聪明的策略,这无疑造成了很大误解。
为此,著名的软件工程专家James Bach根据自己多年的实践经验和理论基础对满意质量的原则进行了系统化定义,提出了满意质量框架,澄清了许多模糊认识。满意质量框架基于以下假定:
1) 软件开发被迫面对一个充满复2) 杂性、未知、限制、错误和不3) 完美的世界;
4) 截止目前人员是软件项目中最易变和最重要的元素;
5) 任何事情都带来成本,6) 而7) 我们所想要的总是超过我们能够支付的;
8) 质量在本质上是有条件的和主观的;
9) 为了在软件方面达到完美,10) 我们不11) 得不12) 解决许多困难问题、达成许多折衷和解决相互冲突的价值,13) 完美不14) 会很容易或机械性地实现;
15) 软件工程方法仅在其设计范围和假定前提下有用。
基于上述假定,满意质量定义如下:(1)可带来足够的利益;(2)不存在致命性问题;(3)所带来的利益超过问题所造成的损失;(4)在当前条件下综合考虑所有因素后,进一步的改进所带来的损害大于其带来的帮助。同时,提供了一个用于评估GEQ的框架,该框架包括四个GEQ元素和六个GEQ视角,它们构成了一个提示问题集,可用来帮助相互沟通,或者帮助进行产品开发、产品改进、实现更好的实践活动等。例如,当某人说“满意未必是满意”时,就可以利用受益人和关键目的两个视角来理解该悖论的真实含义并予以讨论,可以应对“对你而言的满意对我却未必”,或者“相对生存目的而言的满意在以成功为目标时却未必”,这样问题就转换成谁的价值起作用或哪个目标是真正要实现的,进而探讨可行解决方法。以下是GEQ框架的概要描述:
GEQ元素(factor)
这里给出的四个元素是以GEQ定义为基础扩展而得到,并非严格的公式。这些元素被设计用来提醒那些忙碌的、超负荷工作的软件人士在评估软件产品质量时应思考的问题。
1. 评估产品的利益
鉴别——对于产品的受益人而 言具有什么已知利益或潜在利益?
可能性——假设产品正如所设计的那样工作, 受益人有多大可能性会认识到每个利益?
影响——对受益人而 言, 每个利益的期望程度如何?
个体重要程度——从个体考虑, 哪些利益是完全不 可替代的?
整体利益——作为一个整体且假设没有问题, 是否具有足够的利益以满足受益人?
2. 评估产品的问题
鉴别——对于产品的受益人而 言具有什么已知问题或潜在问题?
可能性——受益人有多大可能性会发现每个问题?
影响——对受益人而 言, 每个问题的破坏程度如何?是否可以继续工作?
个体重要程度——从个体考虑, 哪些问题是完全不 可接受的?
整体问题——所有问题叠加在一起会怎样?是否有太多的非关键问题?
3. 评估产品质量
整体质量——根据GEQ视角, 利益是否看来超值于问题?
安全/完美边际值——如果需要或想要使利益超值于问题, 那么至少需要投入多少?
4. 评估改进产品的后勤问题
策略——有哪些策略可用于改进产品?
能力——具备 实现这些策略的能力吗?知道如何做吗?
成本——改进工作需要多少成本或存在什么麻烦?是否充分利用了资源?
进度——能否立即开始或稍 后再改进?能否在可接受的时间范围内实现改进工作?
利益——改进效果明确吗?有附加利益吗(如更好的士气)?
问题——改进工作会有多大可能带来负面影响(例如, 引入错虫、损伤士气、占用其他项目资源)?
GEQ视角(perspective)
上述GEQ元素是必要条件而不是充分条件。为了执行可靠的评估,还必须同时从六个关键视角来检查每个元素:
1. 受益人——哪些人关于质量的意见起作用?(例如,2. 项目团队、客户、商会、法院等)
3. 关键目的——什么是必须达到的?(例如,4. 即时生存、利润、市场份额、客户满意度等)
5. 时间尺度——质量改进成果的时间敏感性如何?(例如,6. 立即、近期、长期、某个关键事件之后等)
7. 替代物——本产品与替代物相比如何?(例如,8. 竞争对手的产品、服9. 务或解决方案)
10. 失败结果——如果质量比GEQ稍11. 差一些会怎样?是否需要对突发事件进行规划?
12. 评估质量——评估本身的可信度如何?是否令人满意?
显然,满意质量决不等同于平庸,它强调的是理性的选择,而不是强制性行为。如果按照GEQ框架分析后认为某个软件已经达到满意质量,那么进一步的改进将意味着资源投入得不到足够的回报。如果我们发现自己正处于这样一种境地时,就应当认真找寻一下其背后的强制性理由何在。对于GEQ方法的强大推动来自于市场驱动型软件的爆炸性增长,软件公司对于巨额股票市值的憧憬导致公司致力于寻找最短途径以更快地推出更好、更便宜的软件,他们愿意承担风险,而且很难容忍传统意义上的所谓良好实践,许多传统的软件管理观点在应用到市场驱动软件项目时常常不适用或显得过于呆板。可以看出,GEQ方法与“轻”方法殊途同归,无论是高可靠性要求的软件开发还是高娱乐性要求的软件开发,都可以利用其指导开发工作。无论称其为GEQ,或其他什么称谓如经济性、实用主义、功利主义等,基本思想都是一致的,即我们的行为应受理性指导,而不是强制。
随着GEQ思想的持续发展,我们思考的质量,而不是遵循形式方法的质量,将成为问题所在,而形式方法及其背后的权威将被重新审视,这也正是许多权威将GEQ视为危险思想的原因。
四、快速应用开发
以上从基本原理入手对于新兴的“轻”方法和满意质量框架进行了讨论,本节则以近年来被广泛应用的快速应用开发(RAD)方法作为具体实例加以探讨,为加深对于这些新思想的理解提供帮助。
RAD方法与原型方法有很多相似之处。原型开发可以使用户看到系统的不同设计方案,尤其当用户需求不确定时。一般情况下,原型仅用于提供演示。不过,一旦最终版本原型功能正确,文档齐全,且被正确构造,则可以将其用作最终产品。当原型被用作产品时,所有的遗留问题都必须已经解决,软件应符合需求说明书、设计文档和测试文档。与原型法不同的是,RAD每次交付的是用户在实际业务中应用的系统,而不仅仅是一个演示模型。
在接受项目定单以后,通过在产品开发时间、费用和质量三者间达成折衷从而快速地移交产品。RAD方法采用递增式产品交付,通过用户在每一开发循环周期中的反馈信息来确定下次循环的方向。由于市场需求很难预计,因此RAD循环将无限持续下去直至系统被淘汰。一个典型的RAD开发循环周期是每月推出一个系统的新版本,有时会缩短到每星期甚至每天。不过开发周期越短则开发过程就会越不稳定,也越容易失控。RAD方法通常建立在以下基础上:
所有目标 的明确定义(需要做什么)和解决方案的指 导说明(怎样去做)。
将解决具体问题的任务(怎样去做)交给个人。
项目领导者以教练方式代替细节管理, 从一开始就让各员工担负较大责任(仅当有迹象表明员工不 能按时交付时领导再出面解决)。
团队中的各角色都应预先明确, 这样每一项任务的完成交付都至少和一位员工的责任对应。但在项目开发的中途, 当实际工作量高于或低于预期的工作量时, 可以改变员工角色或任务。
领导者本身具备 编程能力但可以不 进行编码工作。
顾客积极参与:顾客是否支持该项目的结果、设计等?你需要确定谁是顾客:谁影响和作出决定?
开发团队积极参与:团队各成员认可各项需求和时间期限吗?
范围控制:保证当前和以后各阶段的估计值不 会过于脱离实际。
实际应用中,RAD方法一般以进度和费用作为独立参数来调整策略,步骤如下:
1. 客户确定他们所能承受的最长开发时间和费用。
2. 开发人员估计满足所有功能所需的开发时间和费用。
3. 如果开发人员估计的开发时间和费用同4. 客户所能承受的时间和费用相差无几,5. 那么就可以进行项目开发了。否则:
6. 客户划分项目所需功能的优先级。
7. 如果开发时间超出或费用不8. 够时,9. 项目开发者会在系统开发中摒弃那些低优先级的功能特性。
10. 项目开发者先建立起系统的核心功能,11. 然后按照优先级由高到低的顺序实现新的功能,12. 直到开发超时或费用超支。
在使用RAD方法时,可利用以下技巧来提高开发效率和质量:
在每次开发之前,确定一个明确的开发计划,包括初始需求的建立,总体目标,项目范围,成功标准,采用的RAD工具和开发方法。
在每次开发之前,简要描述出每个开发周期中所需实现的功能模块。制定出在前一两个开发周期中所需实现的功能特性是非常重要的,这包括确定实现具有高优先级的基础功能或关键功能,预测实现目标和潜在风险。
在每次开发之前,回顾需要在此阶段实现或修改的每个功能,判断它们是否同项目所要实现的目标一致。区分哪些功能是在这个阶段中必须要实现的,哪些仅仅是希望实现的。
使用那些经验丰富的、受人敬重的测试人员。
保证设计者和开发者密切联系,并使测试人员尽可能参与到开发过程中。
要求设计者和开发者完成各自的单元测试和适当的集成测试。
确定开发过程的安全警戒点,例如,当开发过程中未解决的问题超过了预计值时,应安排额外的时间进行产品修正,直到错误数量大大减少。
尽可能利用和调整已有测试工具,如回归测试平台、已有测试用例等。
使用成熟的调试工具和自动化的测试工具以加速开发进程。
使客户和最终用户最大程度地参与容量测试,请用户在日常工作中尽可能地并行使用该系统,并与上次开发周期交付的版本进行前后对比。
对需求和产品范围的任何改变应慎重分析,测试人员应对所提出的改变可能产生的影响做出评价,并在证明是正当的情况下有权予以否决。
提醒用户可能存在错误,培训他们怎样认识和报告错误,怎样在这些错误下工作。
应用程序的每一次循环开发都应在版本控制下进行。
不允许未经过最小测试的新版本发布。根据用户反映、操作风险、故障等级、与上一版本相比最新改动的地方等因素来确定最小测试需求。
必要时,如果为了满足有时间期限的下一次升级,可以考虑在准备发布之前删掉漏洞多的功能部分。
如果最新功能证明包含一个漏洞,则要提供给用户一个返回原版本的机制。
应用软件通过反复的修正,会变得更稳定。或者至少特定功能或子系统会比其他部分更早些趋向稳定,作为系统稳定的部分,可使用自动测试工具进行更完全的测试。
发布升级版本后不必对用户所发现的小漏洞感到不安。这对于首次运行是很自然的问题,而且通常还将会有使用户抱怨的地方。用户应当理解软件升级的原因完全是因为新生事物很少有完全正确的。应强调团队合作。
通过探测或预测程序中可能发生错误的地方而避免关键点任务的失败。
通过原型、标准、一致性检查等减少走回头路,利用风险预测技术来避免各种缺陷和风险。