2008年6月15日

1、项目经理必须关注项目成功的三个标准

简单地说,一是准时;二是预算控制在既定的范围内;三是质量得到经理和用户们的赞许。项目经理必须保证项目小组的每一位成员都能对照上面三个标准来进行工作。

2、任何事都应当先规划再执行

就项目管理而言,很多专家和实践人员都同意这样一个观点:需要项目经理投入的最重要的一件事就是规划。只有详细而系统的由项目小组成员参与的规划才是项目成功的唯一基础。当现实的世界出现了一种不适于计划生存的环境时,项目经理应制定一个新的计划来反映环境的变化。规划、规划、再规划就是项目经理的一种生活方式。

3、项目经理必须以自己的实际行动向项目小组成员传递一种紧迫感

由于项目在时间、资源和经费上都是有限的,项目最终必须完成。但项目小组成员大多有自己的爱好,项目经理应让项目小组成员始终关注项目的目标和截止期限。例如,可以定期检查,可以召开例会,可以制作一些提醒的标志置于项目的场所。

4、成功的项目应使用一种可以度量且被证实的项目生命周期

标准的信息系统开发模型可以保证专业标准和成功的经验能够融入项目计划。这类模型不仅可以保证质量,还可以使重复劳动降到最低程度。因此,当遇到时间和预算压力需要削减项目时,项目经理应确定一种最佳的项目生命周期。

5、所有项目目标和项目活动必须生动形象地得以交流和沟通

项目经理和项目小组在项目开始时就应当形象化地描述项目的最终目标,以确保与项目有关的每一个人都能记住。项目成本的各个细节都应当清楚、明确、毫不含糊,并确保每个人对此都达成了一致的意见。

6、采用渐进的方式逐步实现目标

如果试图同时完成所有的项目目标,只会造成重复劳动,既浪费时间又浪费钱。俗话说,一口吃不成个胖子。项目目标只能一点一点地去实现,并且每实现一个目标就进行一次评估,确保整个项目能得以控制。

7、项目应得到明确的许可,并由投资方签字实施

在实现项目目标的过程中获得明确的许可是非常重要的。应将投资方的签字批准视为项目的一个出发点。道理很简单:任何有权拒绝或有权修改项目目标的人都应当在项目启动时审查和批准这些项目目标。

8、要想获得项目成功必须对项目目标进行透彻的分析

研究表明,如果按照众所周知记录在案的业务需求来设计项目的目标,则该项目多半会成功。所以,项目经理应当坚持这样一个原则,即在组织机构启动项目之前,就应当为该项目在业务需求中找到充分的依据。

9、项目经理应当责权对等

项目经理应当对项目的结果负责,这一点并不过分。但与此相对应,项目经理也应被授予足够的权利以承担相应的责任。在某些时候,权利显得特别重要,如获取或协调资源,要求得到有关的中小企业的配合,做相应的对项目成功有价值的决策等等。

10、项目投资方和用户应当主动介入,不能被动地坐享其成

多数项目投资方和用户都能正确地要求和行使批准(全部或部分)项目目标的权力。但伴随这个权力的是相应的责任——主动地介入项目的各个阶段。例如,在项目早期要帮助确定项目目标;在项目进行中,要对完成的阶段性目标进行评估,以确保项目能顺利进行。项目投资方应帮助项目经理去访问有关的中小企业和目标顾客的成员,并帮助项目经理获得必要的文件资料。

11、项目的实施应当采用市场运作机制

在多数情况下,项目经理应将自己看成是卖主,以督促自己完成投资方和用户交付的任务。项目计划一旦批准项目经理应当定期提醒项目小组成员该项目必须满足的业务需求是什么,以及该怎样工作才能满足这些业务需求。

12、项目经理应当获得项目小组成员的最佳人选

最佳人选是指受过相应的技能培训,有经验,素质高。对于项目来说,获得最佳人选往往能弥补时间、经费或其它方面的不足。项目经理应当为这些最佳的项目成员创造良好的工作环境,如帮助他们免受外部干扰,帮助他们获得必要的工具和条件以发挥他们的才能。

posted @ 2008-06-15 15:43 JavaSuns 阅读(62) | 评论 (0)编辑 收藏

在开始正文之前,我想先讲两个故事——关于软件项目的故事。


故事一

有两个软件项目(姑且称之为“项目 A”和“项目 B”),它们在开始时的预算都是 50 个人月,时间是 5 个月。

项目 A 在 5 个月后完工,耗费成本 50 人月
项目 B 在 6 个月后完工,耗费成本 70 人月
在软件圈子里摸爬滚打多年的读者们对这个故事一定有自己的判断——而且我可以大致猜出是什么样的判断。不过先别着急,我们还有另一个故事。

故事二

有两个软件项目(仍然姑且称之为“项目 A”和“项目 B”),它们在开始时的计划都是交付 200 项功能。

项目 A 在项目结束时一次性交付了最初计划的 200 项功能,但客户发现其中大约 30 项功能没有太大用处,而另外 30 项有用的功能要等到下一个项目才能实现。
项目 B 在第一个月结束时交付了第一个版本,此后每两周交付一个新的版本。在项目进行的过程中,客户进行了一次业务调整,加入了 90 项新的功能,并搁置了 50 项用处不大的功能。最终该项目交付了 240 项功能。
聪明的读者大概注意到了,前后两个故事讲的是同一回事,同样的两个项目。现在我的问题来了:请问哪个项目是更成功的项目?

这个问题并不容易回答——实际上它没有标准答案。站在很多软件企业的立场上,项目 A 是一个理想的成功项目:按时间、按成本完成预先约定的任务。请注意,我用了“理想的”这个词,稍后我还会解释这个有趣的词,因为实际上的软件项目往往没有那么理想。

而如果换一个角度,站在客户的立场上呢?也许付钱购买软件的客户会有一些不同的想法。项目 B 从开始之后一个月便交付了第一个可工作的版本,从那时起客户就开始使用这个软件的部分功能,并且不断地把自己使用的感受反馈给开发团队。在真实的业务运营过程中,客户甚至发现了一种新的盈利模式,并进行了一次大规模的业务调整,这次调整的结果也直观地体现在软件项目中。虽然项目B的整体交付速率低于项目 A,但它提供的所有功能都是客户真正需要的,它们为客户提供实实在在的价值——更不用说,客户提前好几个月就开始使用这个软件。

实际上,这是一篇关于软件价值的文章。和“成功项目”一样,对于“软件的价值”,不同的人也会有不同的定义。不过作为付钱购买软件的客户,他对于软件价值的定义是一目了然的:他能够从使用软件中创造多少价值,软件能够为他的业务提供多少价值,这就是软件的价值。或者说得更简明一点:

软件价值源自使用
这正是为什么很多客户青睐“项目 B”的原因——我并不打算声称所有客户都有同样的观点,稍后我也会举出反例,但至少支持这一观点的客户不在少数。因为他们处在一个残酷而快速变化的商业环境中:他们的供应商在变化,他们的客户在变化,他们所处的经济环境和政策环境也在变化。这一切的变化迫使他们的业务也要随之变化。更要命的是,今天这个经济全球化的时代是一个“快鱼吃慢鱼”的时代,客户迫切希望新的软件系统为他们带来竞争优势——哪怕这个软件系统尚未完成,只要能够投入使用。最后,客户对于新的软件系统究竟应该是什么样子并没有百分之百的把握,他们的想法往往要在真正使用软件之后才会浮现成型。几方面的因素加在一起,使得这些客户更愿意尽快开始使用软件、提出反馈、并不断完善软件,而不是提出一组需求、然后坐等几个月之后原封不动地拿到这些功能。

一个真实的案例

在 ThoughtWorks 的一个项目中,开发者们在项目开始之后一个月内就发布了第一个版本——只有一些简单的数据采集功能。在发布展示会上,发生了这样的对话……

开发者:这是我们的第一个功能。我们从文本文件、Excel 数据表和遗留数据库采集数据,现在我们的数据库中有这些数据……(展示数据库结构)
客户:唔……有意思。要是你能做这样一个查询(写出查询要求),得到的结果可能会有用。
开发者:可是我们的界面上没有地方做这样的查询操作。
客户:啊,我不需要操作界面,只要每天深夜做一次查询,把报表发到我的信箱就可以了。
开发者:这样吗……另一个问题是,这需要花我们几天时间。
客户:不要紧,把别的任务往后放几天好了,我很想看到这份报表。
开发者:那好吧,下周我们就会开始提供这个报表。
猜猜结果怎么样?一周之后客户就开始每天接收这份报表,并根据报表内容做一些分析和决策。仅仅几个月之后,这份报表给客户带来的收益就已经超过了整个项目的投资——这时项目其他部分的开发甚至还没有完成。

想想这个客户会怎么定义一个“成功的软件项目”?好吧,也许这个项目超过了预期的时间,也许投入了更多的人力,但这些并不意味着“项目失败”——只是付出更高的成本。关键在于,他投入的这些成本能够带来多大的收益,他的投资回报率是否划算。对于这个客户而言,如果项目能够随时给他提供可用的、能够创造最大价值的软件,能够随时让——就像故事中提到的——这种有价值的想法得以实现,这就是一个成功的项目。

所以,亲爱的读者,请你忘记本文标题上出现的“敏捷”二字,我们在这里所说的不是别的,就是一种为客户创造最大化价值的软件开发方法。这样的方法有很多种,但它们有一个共同的特点:尽快、尽可能频繁地交付可以工作的软件,让客户尽快开始使用软件,从使用中创造价值、厘清思路、提出反馈。仍然以 ThoughtWorks 的项目为例,这些项目通常在启动开发阶段之后一个月内就会发布第一个版本,随后每一周或每两周发布一个新版本——每个版本都是一个可以工作的软件,每个版本都比前一个版本具有更丰富的功能,并且每个版本都包含客户认为迄今为止最有价值的那些功能。用软件开发的“黑话”,“开发下一个版本”的过程叫做“迭代”,这些开发方法最大的共同点就是“迭代式开发”——不是一股脑地交付全部功能,而是每次增加一点、渐进地交付最有价值的功能。

软件开发的梦想与真实

回到文章开始处的两个故事。我曾经说过,对于很多软件企业而言,项目 A 是一个“理想的”成功项目。那么,是什么让情况变得不那么理想?

答案是一个所有软件开发者耳熟能详的词:需求变更。在真实的项目中,客户通常不会等到最后一天再照单全收整个项目,因为他知道自己的业务正在发生变化。这时需求变更就出现了,伴随着来回的扯皮和讨价还价。更糟的是,大量的需求变更发生在项目晚期——因为直到这时客户才真正看到、使用到这个软件,他的很多想法才真正浮现成型。随着这种“最后一分钟的需求变更”,项目超期、超出预算也就成了家常便饭。能够像项目A这样完工交付的,实在是凤毛麟角的幸运儿。

为了对付需求变更这个噩梦,软件开发者们还发明了另一个词:变更控制。这个有趣的词暗示着:需求变更是一种“不好”的东西,是需要“控制”的东西。然而站在客户的角度上想想,他在亲身使用了软件之后提出的要求,难道不是最有价值的东西吗?把这种真正创造业务价值的要求“控制”起来,难道是合理的吗?

在前面我也暗示过,并非所有的客户都一定青睐迭代式开发。那么,哪些软件项目不一定需要迭代式开发呢?从整篇文章的内容不难看出,如果客户的业务绝对不会变化,如果客户的需求巨细靡遗非常明确,如果客户不需要尽快开始使用软件以便收回成本,那么迭代式开发对他的帮助就会小得多。不过,如果读者认真思考的话,这样的例子也许并不多——也许比你最初认为的要少得多。一个很好的例子是“神州六号”火箭使用的计算机控制系统。还有多少这样的例子?读者不妨试着自己想想。

如果我足够幸运的话,也许一些读者已经被这篇文章吊起了胃口:既然有这么好的软件开发方法,既然它能够为我们创造更大的价值,那还等什么呢,我们马上就动手吧。事情不会那么简单。为了让迭代式开发能够成为现实,为了确保尽快、尽可能频繁地交付,为了确保每次交付的都是最有价值的功能,我们——包括软件开发者、软件企业和客户——需要很多的改变。这里既有职责与权利的划分,也有开发过程和团队的重组,还有技术层面的实践指导。这些正是敏捷方法学所涵盖的内容。缺少了这些东西,“为客户创造最大价值”就只能成为一句空话。在后续的文章里,我们将结合 ThoughtWorks 的实践经验,逐步介绍敏捷方法的方方面面。

 

posted @ 2008-06-15 15:35 JavaSuns 阅读(51) | 评论 (0)编辑 收藏

最开始时微软公司将Java当做一种能解决C和C++中存在的问题的语言,并不在意,并继续维持和培训着其C和C++技术和编程人员。接下来不幸的是,正当微软尽力在Visual J++基础上拓展Java功能,并使之与Windows操作系统紧密结合在一起的时候,Sun公司对微软提出法律诉讼说其违反了许可证协议中的条款,最终的结果是微软公司不得不停止其Visual J++产品的开发。(微软公司仍然销售Visual J++,但是从1998年10月以来就没有新的版本发布,并且在.Net平台上也没有Visual J++的位置了)接下来的事情就很清楚了,微软公司开发了C#语言。接下来的一部分将讨论C#与Java的相似性。
  C#与Java的区别
  C#最引人的地方是它与Java的区别而不是其相似性。下面主要来介绍C#区别于Java的不同的运行特点及Java完全没有的特点。
  中间语言
  当MSIL被编译成最终的机器码时,微软公司在如何选择上是非常灵活的。微软公司很谨慎的对外宣称说MSIL不是解释型的,而是被编译成机器码。因为开发人员都有这样一个观念:Java程序天生就比C程序运行慢,所以这暗示着基于MSIL的程序优于解释型的Java字节码。当然,既然C#和其它MSIL产品编译器还未发布,那么这一点就还未证明,但是Java无处不在的即时编译器使得C#和Java在效能上是一样的。象“C#是编译型的,Java是解释型的”这样话只是销售中的技巧。Java的字节码和MSIL码都是的类似汇编的中间语言,在运行时执行这些中间码。
  与COM的整合
  对于基于Windows的C#开发人员来说,最大的收获是对COM的无损整合,COM是微软Win32的组件技术。实际上,任何一种.Net体系结构上的语言最终都可能去写COM的客户端和服务器端程序。用C#编写的类也会作为COM组件的子类;结果类(resulting class)也能作为COM组件使用,并作为COM组件的子类。
  微软公司的目标是使越来越多的语言都能访问组件,并使这些组件能整合到.Net体系结构中。已有几个厂商开始着手开发支持.Net功能的编程语言,如COBOL和Haskell。开发人员能选择不同的语言解决不同问题,更重要的是,开发人员不必为采用.Net体系结构而必须学习新语言,可以选择一种他们熟悉的语言。

  总结
  本文的第一、二部分对C#做了一肤浅的总体介绍,主要是其产生动机及与Java的相似性。第三部分则涵概了C#的语言特点。用范例说明了C#与Java两者在相似性外,它们又是非常不同的,有许多细微的语义和设计区别,适合不同的技术和市场环境,又谈到了微软公司对C#进行标准化方面的尝试,及其对Java的影响。
c#与java的区别

1.属性:
java中定义和访问均要用get和set方法,可以不成对出现。
c#中是真正的属性,定义时get和set必须同时出现,房问时用.号即可。不用get,set

2.对象索引
就是对象数组
public Story this [int index] {

3.C#中,不用任何范围修饰符时,默认的是protect,因而不能在类外被访问.

4.因为JAVA规定,在一个文件中只能有一个public类,而且这个类的名称必须与文件名一模一样,这是一个区别

5.在C#中,它是以Main方法来定位入口的.如果一个程序中没有一个名为Main的方法,就会出"找不到入口的错误".不要把Main写成main哟

6.C#预定义的简单数据类型比Java多。例如,C#有unit,即无符号整数

7.忘掉Java中的static final修饰符。在C#中,常量可以用const关键词声明
C#的设计者还增加了readonly关键词,readonly域只能通过初始化器或类的构造函数设置
8.公用类的入口点:c#是可以对Main进行重载(java中是main),允许有int返回值和空参数的Main

9.在Java中,switch语句只能处理整数。但C#中的switch语句不同,它还能够处理字符变量。请考虑下面用switch语句处理字符串变量的C#代码

10.C#没有>>>移位操作符

11.goto关键词:
Java不用goto关键词。在C#中,goto允许你转到指定的标签。不过,C#以特别谨慎的态度对待goto,比如它不允许goto转入到语句块的内部。在Java中,你可以用带标签的语句加上break或continue取代C#中的goto。

12.int[] x = { 0, 1, 2, 3 };
int x[] = { 0, 1, 2, 3 };
但在C#中,只有第一行代码合法,[]不能放到变量名字之后。

13.与Java不同的是,C#允许为名称空间或者名称空间中的类指定别名:
using TheConsole = System.Console;

14.在Java中,包的名字同时也是实际存在的实体,它决定了放置.java文件的目录结构。在C#中,物理的包和逻辑的名称之间是完全分离的
.NET中包的实体称为程序集(Assembly)。每一个程序集包含一个manifest结构。manifest列举程序集所包含的文件,控制哪些类型和资源被显露到程序集之外,并把对这些类型和资源的引用映射到包含这些类型与资源的文件。程序集是自包含的,一个程序集可以放置到单一的文件之内,也可以分割成多个文件。.NET的这种封装机制解决了DLL文件所面临的问题,即臭名昭著的DLL Hell问题。

15.在Java中,java.lang包是默认的包,C#中不存在默认的包

16.C#中的访问修饰符与Java中的基本对应,但多出了一个internal。简而言之,C#有5种类型的可访问性,如下所示:

public:成员可以从任何代码访问。
protected:成员只能从派生类访问。
internal:成员只能从同一程序集的内部访问。
protected internal:成员只能从同一程序集内的派生类访问。
private:成员只能在当前类的内部访问。

17.由于C#中不存在final关键词,如果想要某个类不再被派生,你可以使用sealed关键词

18.与Java不同,C#中的接口不能包含域(Field)。
另外还要注意,在C#中,接口内的所有方法默认都是公用方法。在Java中,方法声明可以带有public修饰符(即使这并非必要),但在C#中,显式为接口的方法指定public修饰符是非法的。例如,下面的C#接口将产生一个编译错误。

19.C#中的is操作符与Java中的instanceof操作符一样,两者都可以用来测试某个对象的实例是否属于特定的类型。在Java中没有与C#中的as操作符等价的操作符。as操作符与is操作符非常相似,但它更富有“进取心”:如果类型正确的话,as操作符会尝试把被测试的对象引用转换成目标类型;否则,它把变量引用设置成null。

20.C#仍旧保留了C++的内存手工管理方法,它适合在速度极端重要的场合使用,而在Java中这是不允许的

21.在C#中,所有的异常都从一个名为Exception的类派生

22.枚举器即enum类型(java无),把它作为一个变量值的类型使用,从而把变量可能的取值范围限制为枚举器中出现的值。

23.结构(Struct)与类很相似,而结构是一种值类型,它存储在栈中或者是嵌入式的,结构可以实现接口,可以象类一样拥有成员,但结构不支持继承

24.属性声明语法的第一部分与域声明很相似,第二部分包括一个set过程和/或一个get过程

25.传值方式:
在java中简单数据类型的值传参时,都以传值方式;
在c#中如果加ref则会以引用的方式传值(方法内部改变该参数,则外部变量一起跟着变);
加out与ref基本相同,但out不要求参数一定要初始化.

26.c#保留了指针。unsafe

27.代理:代理(delegate)可以看作C++或者其他语言中的函数指针
代理用来封装可调用方法。你可以在类里面编写方法并在该方法上创建代理,此后这个代理就可以被传递到第二个方法。这样,第二个方法就可以调用第一个方法。
代理是从公共基类System.Delegate派生的引用类型。定义和使用代理包括三个步骤:声明,创建实例,调用。代理用delegate声明语法声明。

posted @ 2008-06-15 14:37 JavaSuns 阅读(103) | 评论 (0)编辑 收藏