Danny's profile季节的水滴PhotosBlogListsMore Tools Help

Blog


    4/2/2007

    软件开发项目的最佳实践

    大多数软件项目都是失败的。事实上,Standish group 的报告显示 80% 多的项目是不成功的,原因是超出了预算、未能按时完成、遗漏功能或者因为一个项目中同时出现了这些问题中的其中几个。此外,30% 的软件项目执行得很糟糕以至于半途而废。根据我们的经验,使用现代技术(例如 Java、J2EE、XML 以及 Web 服务)的软件项目都逃不出这个规则。

    本文概述了软件开发项目的最佳实践。一些业界泰斗,如 Scott Ambler、Martin Fowler、Steve McConnell 和 Karl Wiegers,已经在因特网上写了许多这样的最佳实践,本文也引用了这些最佳实践。另请参阅本文末尾的相关信息部分。附带的文章软件开发项目实施指南描述了有助于提高项目成功率的十条最重要的因素。

    最佳实践

    1. 开发流程(Development process)- 为手头的项目选择适当的开发生命周期流程很重要,因为其他的所有活动都是从这个流程派生出来的。现代的软件开发项目多数都是在瀑布式流程的基础上采用某种螺旋式方法。有几种方法可供选择,包括 Rational 统一流程(Rational Unified Process,RUP)、IBM® Global Services 方法(IBM® Global Services Method)以及极端编程(eXtreme Programming,XP)。有个流程当然比根本没有要好,但在多数情况下流程的执行情况要比使用的是什么流程更重要。以上列举的常用方法都包含关于如何执行流程的指南和构件模板。此外,RUP 还有一系列描述使用 RUP 的最佳实践的书 [1][2][3][4],即便不选用 RUP,这些书也是获得最佳实践的极好来源。给 RUP 加插件也是可以的。请为基于 WebSphere® J2EE 的项目下载 WebSphere 插件。

    2.需求 - 收集需求并就需求达成一致是项目成功的基础。这并不一定意味着需要在建立好体系结构、完成设计和编码工作之前确定所有的需求,但对于开发小组来说明白需要构建什么是很重要的。质量需求分两种:功能性的和非功能性的。一种记录功能性需求的好方法是使用用例(Use Case)。注意:用例被用于非面向对象的项目。Armour 和 Miller 著有一本关于用例主题的权威著作 [5]。非功能性需求描述应用程序的性能和系统特性。收集非功能性需求很重要,因为他们对应用程序体系结构、设计以及性能都会产生重要影响。请参阅 Construx Web 站点上的非功能性需求清单。

    3.体系结构 - 为您的应用程序选择合适的体系结构是关键。有好几次 IBM 被要求复查出问题的项目,结果发现开发小组没有应用知名的业界体系结构最佳实践。与 IBM 联系是避免这类问题的好方法。我们的顾问可以与您的开发小组并肩工作以确保项目沿正确的轨道开始。经过实验证明可靠的实践称为模式,有经典的 Gang of Four [6] 模式、Java 模式 [7],也有 EJB 设计模式 [8]。Sun 公司与此相应的是核心 J2EE 模式(Core J2EE Pattern)目录 [9]。IBM 也发布过一些最佳实践和参考应用程序体系结构 [10]。引言中说过许多项目都是失败的。通过对这些失败的项目的研究提出了反模式这个概念。这些反模式是很有价值的,因为它们针对哪里出了问题以及为什么会出问题提供了有用的信息。

    4. 设计 - 即使有了好的体系结构,也可能设计不好。许多应用程序不是设计得过于复杂就是设计得过于简单。这有两个基本原则“尽量简单”和信息隐藏。对于许多项目来说,使用 UML 进行面向对象的分析与设计(Object-Oriented Analysis and Design)很重要。有关 UML 的书有很多,但我们推荐 UML User Guide [11] 和 Applying UML and Patterns [12]。重用是面向对象的很有前途的一个方面,重用经常会因为需要额外的工作来创建可重用资产而变得无法实现。代码重用是重用的一种形式,当然也有其他一些能够提高效率的重用种类。

    5. WebSphere 应用程序设计 - IBM 拥有关于 WebSphere 系列产品的最佳实践和设计模式的广泛知识。每个项目都是不同的,我们的顾问有丰富的经验来帮助您。即使您只聘请我们的顾问很短一段时间,这种投资回报(ROI)也是很大的,因为您可以在以后的项目中节省开销。我们的专家也发表过大量有关这类知识的文章,包括高性能 Web 站点注意事项和自主计算指南。

    6. 代码的构建 - 代码的构建虽然只是整个项目工作的一小部分,但往往是最明显的部分。其他同样重要的工作还包括需求、体系结构、分析、设计以及测试。在没有开发流程(所谓的“编码加修正”)的项目中,也会有这些任务,只不过被统称为“编程”而已。构建代码的最佳实践包括每日构建和冒烟测试。Martin Fowler 进一步提出了连续集成(continuous integration),这个概念还集成了单元测试和自测试代码概念。注意,即使连续集成和单元测试是通过 XP 流行起来的,您也可以在所有类型的项目中使用这些最佳实践。我建议使用标准框架(比如 Ant 和 JUnit)使构建和测试自动进行。

    7. 对等审查 - 审查别人的工作很重要。经验证明这种方法可以及早消除问题,审查和测试一样有效,甚至比测试还有效。开发流程中任何构件都需要审查,包括:规划、需求、体系结构、设计、代码以及测试案例(test case)。Karl Wiegers 的文章 Seven Deadly Sins of Software Reviews 说明了执行对等审查的正确方法。对等审查有助于以最快的速度提高软件质量。

    8. 测试 - 即使日程安排再紧也不可以推迟或省去测试。测试是需要计划的软件开发的一个必不可少的部分。提前测试也很重要;这意味着要在开始编码前就安排好测试案例,测试案例的开发与应用程序的设计和编码同时进行。同样也有许多现成的测试模式。

    9. 性能测试 - 测试通常是用于检查应用程序缺陷的最后一招。它是劳动密集型工作,通常只检查编码缺陷。体系结构和设计上的缺陷可能会漏掉。一种检查体系结构缺陷的方法是在部署应用程序之前对其进行模拟负载测试,并在性能问题真正成为问题前就处理它们。

    10. 配置管理 - 进行配置管理涉及到了解组成您的系统或项目的所有构件的状态,管理这些构件的状态并发布系统的不同版本。配置管理比单独的源代码控制系统(比如 Rational Clearcase)管理的内容更多。同样也有针对配置管理的最佳实践和模式 [13]。

    11. 质量和缺陷管理 - 为项目建立质量优先级和发布标准很重要,这样就可以制定一个计划来帮助开发小组开发出高质量的软件。当对项目进行编码和测试时,缺陷的出现和修正比率有助于测量代码的成熟程度。使用链接到源代码控制管理系统的缺陷跟踪系统也很重要。例如,使用 Rational ClearCase 的项目还可以使用 Rational ClearQuest。使用缺陷跟踪,就可以在准备发布项目时对项目进行测量(gauge)。

    12. 部署(Deployment)- 部署是向用户发布应用程序的最后阶段。如果您的项目进行到了这一步 - 那就恭喜您啦!但仍然会有可能出错的地方。您要制定部署计划,并且您可以使用 Construx Web 站点上的部署清单。

    13. 系统操作与支持(System operations and support)- 没有操作部门就不能部署和支持新应用程序。支持范围对于回答和解决用户问题至关重要。为缓解问题流,应用程序缺陷跟踪系统中引入了支持问题数据库。

    14. 数据迁移(Data migration)- 多数应用程序都不是全新的,而是改善或者重写的现有应用程序。从现有的数据源迁移数据这本身通常就是一个比较大的项目。这不是初级程序员能做的。它与新应用程序一样重要。通常新应用程序的业务规则更好,数据质量有可能更高。提高数据质量是一个复杂的主题,已经超出了本文讨论的范围。

    15. 项目管理(Project management)- 项目管理是项目取得成功的关键。本文描述的许多其他的最佳实践都和项目管理有关,出色的项目经理已经知道了这些现有的最佳实践。我们推荐的项目管理权威著作是 Steve McConnell 编写的 Rapid Development [14]。如果把项目管理的其他清单和技巧的数目考虑进去,您会感到大吃一惊,居然有那么多的项目经理不知道这些技巧,并且也没有从以前的项目中吸取教训,比如:“如果没有计划好,就等于计划着要失败。”一种管理困难项目的方法是通过使用时间定量(timeboxing)。

    16. 衡量是否成功 - 您可以根据卡内基梅隆大学软件工程学院(Software Engineering Institute at Carnegie Mellon University)的业界标准软件能力成熟度模型(Capability Maturity Model,CMM)来衡量您的开发流程。多数项目处于 1 级(初级)。如果按照上面描述的最佳实践和附带的文章,软件开发项目实施指南,中的执行,就可以开发出更加成熟的软件,使项目取得成功。

    结束语

    本文提供了一系列有助于提高软件开发项目成功率的最佳实践。遵循这些最佳实践,您的项目成功的机会会更大。

    软件高手是这样练成的

    中国人大都喜欢用武侠小说来比较软件开发,但是在实战武功中,只有葵花宝典才是最厉害的,也只有掌握了葵花宝典,才能称为“不败”。
           但什么才是软件开发的葵花宝典?
           让我们先从一些现象出发。我们的前提是,软件开发是一项智力密集型劳动。对于智力密集型劳动,我们观察到的现象是,个体的表现差异很大,团队的表现差异很大,组织的表现差异很大,国家的表现差异很大。这不象体力占主要的劳动,象百米王跑百米的速度也仅比我快50%。但在棋类运动中,一个高手可以车轮战数位低手,而且毫无例外地将他们一一击败!
          这些智力运动员表现出的特点是,计算精确而且速度快。其行为很象东方不败。虽然关于葵花宝典的传说很多,但最准确的描述只有一个字“快”。东方不败已经快到了吓人的地步。就象卡斯帕罗夫已快到了深蓝的地步。

      有一则关于物理学家玻尔的轶事,有一次玻尔在普林斯顿大学听两个年青教授演讲他们的工作成果。期间玻尔突然发言说,如果照你们的研究算下去,会得到一个很有意思的推论。结果两个年青教授回去计算了两天,果然得出了同样的结论。玻尔是如何做到这样快的?

      在软件开发中,我们同样注意到这样一种高手,他们可以每天写出一千行左右的高品质代码。他们可以运用已有的一些软件包,迅速完成一个新的产品。他们可以在很短的时间内,学会一项新的程序语言或是新技术。他们表现出一种神奇的速度。
      在武侠小说中,所有的高手都有一些凡人不能企及的表现。象张无忌学太极,用龙爪手击败龙爪手名家;乔峰用太祖长拳击败天下英雄;姑苏慕容以其人之道还治其人之身,令狐冲一剑剌瞎十几双眼睛等等。我认为,之所以他们能做到这样,关键是在于他们快。

      快并不意味着不准或品质差。快与品质并不矛盾。
      高手的快,其实包含着很高的品质在其中。如果你因为高手的快,就质疑其品质,那就相当于在问:东方不败出手那么快,会不会刺不准?东方不败并不满足于刺死对手,他会在对手身上刺朵花。他把杀人变成了艺术。准确来说,他真正的兴趣不在杀人,而在于艺术。
      退一步说,就算东方不败第一击有点偏差,他稍作修正后,马上跟上的第二第三击,也会击中他想击中的地方。在武功差的对手剑还没拨出来的时候,他已杀死对方并刺上了一朵花。

      所以真正的软件高手,他并不满足于他的代码能有效地工作了,他认为编程是艺术,并醉心于其中。在低手能写出一个版本的时间里,他已经写出了第十版。其品质当然不可同日而语。就象一个九段棋手,在给定的时间里,他能计算十种可能,并将每种可能计算到100手之后,从中选择一种最有利的下法。低手岂有苟全的机会?
      高手写软件总是不停地在重构(refactoring)。高手喜欢迭代式开发。高手说,增量就是打补丁,迭代就是推倒重来。对于软件这种东西,写一遍它可能ok(做到这一点也不容易),写十遍就是一个伟大的产品,再多写一遍它就更伟大些。
      高手快的诀窍在于他很熟悉各种东西。高手看书很快,因为每一本新书里,值得他好好看的新技术只有一两章的内容。他能迅速看完,并准确领会这本书的中心思想和价值。而对于一个新手,每句话都是新的,他都需要去理解,每一段例子,他都需要去试。

      很少看到一种100%全新的技术或理论。就象java language specification里说的,java没有使用任何新技术,用的都是业界久经考验的技术。对于高手来说,那些技术都是他所熟悉的。自然,很快他就从一个c++高手变成了java高手。如果一个编程新手学java,学两年也不如一个高手学两个月的。高手学新东西快。

      高手写代码速度快。统计结果说,人均每人月的有效代码速度大概是300至400行。但那是业界平均生产效率。对于高手来说,这个数字太低了。每天写300至400行是完全有可能的。因为在写代码时,所有知识都已具备,已经没有任何需要他多花时间的事情了。他甚至很少需要debug。
      高手重用代码的能力很强,熟悉新的api的速度很快。这也是因为,他曾经使用过很多的api,重用过很多的代码。他知道哪些是可用的,哪些有缺陷。他既过用qt,也用过gtk+,也用过windows api & mfc,也用过awt & swing。新的api对他来说,也是老熟人。 
        高手喜欢用轻量级的工具,象vi,notepad,最多到ultraedit这样复杂的。高手用这种工具写出很多的东西。这些工具就象东方不败的针。那根针已具有神奇的魔力,有时候它可以当激光枪来用。
      对于一些重量级的工具,高手虽不常用,但一经使出也威力大于常人。如果让东方不败用剑,最厉害的剑术名家也会败得很难看。高手其实用过很多的重量级工具,而且深知其优缺点。所以使出来,就会把威力发挥到最大,而把缺陷减少到最小。而低手则不然,总是把缺陷加以大大的发扬而浑不知其精髓何在。就象很多人学用uml、rup、xp、design pattern那样。
      高手所学博杂且融会贯通。高手做什么都快,当低手还在一愁莫展的时候,高手已经圆满解决问题,去干别的事去了。

      相信你有一点点想成为高手了。但是有一个问题亟等解决,那就是“欲练神功,必先自宫”的问题。这一点其实是有比喻意义的。就是说,你必需抛弃一些世俗的人们很看重的东西。有诗为证:
      世人都晓高手好,只是寂寞受不了
      世人都晓高手好, 只有名利忘不了
      世人都晓高手好, 只有金钱一定要
      世人都晓高手好, 天下美女都要抱
         世人都晓高手好, 不写代码最最好
     
      高手的武功不是一朝一夕练成的。还记得玻尔那件轶事吗,玻尔回答说,他年青时也计算过很多的问题。在很多计算的基础上,高手能培养起一种感觉。高手不写代码就能做设计是因为他以前写了很多的代码。而且他们会保持写代码,以保证自已的水平不下降。想一想九段高手是如何练成的。最难做到的是能忍受十年磨一剑的寂寞。别人在父母那里撒娇时,他们在一旁用功。十年磨一剑,剑就成了东方不败的针。
      在你下定决心要做高手之后,也就是下定决心抛弃那些世俗的追求之后,也就是你下决心忍受那些来自于庸俗的人的白眼、攻击和谩骂之后,你就具备了练成神功的必要条件。
      事实上其实你不必一开始就练神功,一开始大家可能是为了钱,房子,汽车,美女才编程序的,然而后来艺术就从中产生了。那时高手就不再关注那些东西了。卓别林曾说过,他开始进入那个圈子也是为了钱,后来艺术就从中产生了。当然,也有人一开始是为了艺术,后来变成为了钱。

      所谓三十而立,就是说到了三十,你找到了你的真爱,值得用一生去追求的那种。比如说有的人到了三十认为这一辈子应该赚尽可能多的钱,这也没什么不好,也可以把赚钱本身变成一种艺术,所谓资本运作是也。所以在三十以前,有些私心杂念没什么。三十以后还这样是可耻的。而我,想做一个程序员。

      每个人做自己最喜欢的事。这个世界需要程序员,也需要资本运作。所有真正的程序员,他最喜欢的事是编程和他自已。如果他后来去做ceo去了,不再编程,只说明他本来不是一个真正的程序员。

      在成为高手的路上,要有热情,要循序渐进,要持之以恒。
      要靠自己,书要快快地看。要试图迅速理解其主旨。其实你快快看所接受的信息量,与慢慢看接受的差不多。能明白多少很大程度上取决于你的功底。以后用到再回过头来看。一本对你来说新东西太多的书,不要指望看一次就全理解吸收。就象很多功力不够的人看design patterns那本书一样。慢慢看还不如找到多种 信息来源,都快快看一遍。对于一个完全陌生的领域,只看一本书很远远不够的。
        要靠自已,事要快快做。有一个朋友,几年前我介绍他去玩玩linux,他也表示想玩,但他现在还没碰过。他失去了很多机会。
        平时要有意识提高自己写代码的速度,其实你一天写15行有效代码,与你写50行有效代码,其品质是差不多的。你应该把那些业界平均水平抛诸脑后,把超越自己做为唯一目标。等到你写了很多各式各样的代码,你的水平就不一般了。一个老师曾向我介绍他的学英语的决窍,他说你去啃原版小说,啃到50本,就和一般人有很大距离了。就是这个理。如果你写得太慢,怎么能写得多?水平怎么能提高?
      要靠自己,学很多别人怕学的东西。低手总会说:这么多东西怎么学得过来啊。于是就少学或不学。这样就成不了高手了。高手有非常广的知识面,有很丰富的经验。知道很多低手不知道的事。玩过很多低手听都没听过的东西。
      要靠自己,努力满足客户的各种需求。个人技能是在满足客户的各种需求的过程中提高的。比如你喜欢用delphi,客户说一定要用vb,那你就答应他,然后把自己培养成为vb的高手。用户的需求看似**,但对你是一个机会。

      怎样才能做到看书快,写代码快,学新东西快,一个显而易见的途径就是将工作并行化。你在一台机器上make时,同时可以在看别的文档和聊天。对于计算机是这样,对人也是这样。如果你只能串行地处理问题,你的速度将提高有限。你的大脑有很大潜力可挖,它应该是一个多任务分时系统。努力减少它idle的时间。搞经济的samuelson被人称为human brain main frame,可见他的大脑有多快。
      让你的思维快起来,你就会区别于那些反应迟钝的人。如果你不能让人生的道路变长,就让它变宽。这世界变化快,需要你变得比它快才行。
      这样加快并不会让你短命,相反,你有更多的时间来享受生活和锻炼身体。你的生活将更有品质,更丰富,更有意义。面对变化,你将立于不败之地。我们都是和自己赛跑的人,需要跑得比昨天的自己更快。