2009年3月31日星期二

PM实战心得(转)

本人做项目经理工作多年,感到做这个工作最要紧的就是要明白,什么叫因地制宜、因势利导,就是说只有最合适的,没有什么叫对的,什么叫错的,项目经理的工作就是利用有限的资源把事情做到客户期望的水平,企业的根本目的就是赚钱,不是研究机构,所以,项目经理最忌讳的就是完美主义倾向,尤其是做技术人员出身的,喜欢寻找标准答案,耽误了工作进度,也迷茫了自己。

以下是本人一些做项目经理的个人体会,写出来供大家指点,在讨论过程中共同提高水平。由于本人的经历主要是做和软件开发相关项目的管理工作,所以,这些经验可能不适合用在工程项目管理领域。

项目开始阶段是一个最重要的阶段。项目经理在接手一个新项目的时候,首先要尽可能地多从各个方面了解项目的情况,如:

1. 这个项目是什么项目,具体大概做什么事情,是谁提出来的,目的是解决什么问题。在国内很多客户都很不成熟的情况下,千万不要根据项目的名称望文生义地去想象项目的目标。一个名为"办公自动化"的项目很有可能在你进场以后一个月才发现客户其实需要的是一个计算机生产管理辅助信息系统。你前期了解情况的工作越详细,后面的惊讶就越少,项目的风险就越小。

2. 这个项目里牵涉哪些方面的人,如投资方、具体业务干系方、项目建成后的运营方、技术监督方等等,很多项目里除了业主单位的结构很复杂以外,还有一些其他单位也会牵涉进来,如项目监理公司、业主的行业主管机构等。项目经理需要了解每个方面的人对这个项目的看法和期望是什么。事先了解各个方面的看法和期望,可以让你在做项目碰到问题的时候,就每件事情分析哪些人会在什么方面支持你,哪些人会出于什么目的反对你,从而提前准备联合朋友去对抗敌人,让事情向你所希望的方向发展。没有永远的朋友,也没有永远的敌人,只有一致的利益,这句话作为项目经理是一定要记住的。
就像二战时候的英国首相邱吉尔,他是个典型的反苏反共分子,但是在苏联进行几大保卫战的时候,他冒着德国潜艇的炮火,忍受路途运输损失一半的代价,把大量的坦克、飞机、军用卡车送到了苏联军队的手中,因为他那时候最主要的任务就是打击纳粹德国。所以,在项目的最初阶段,根据各个方面的情况,经过平衡后得出一个项目大致目标并获得其他人的认可,这个是一个成功项目的第一步。

3. 基本了解了客户的情况后,下面的事情就是了解自己公司各方面对这个项目的看法。首先是高层领导是否重视,这个决定了你在需要资源的时候,公司是否会根据你的要求提供最有力的支持。一般说来,领导口头肯定是说支持的,你需要做的是了解公司对这个项目的实际期望,是想把项目越做越大还是想赚钱?是想做样板工程还是干脆想敷衍了事,公司领导对项目的态度决定了你做这个项目的战略,而这个战略方针将对你做项目计划产生直接的影响;

4. 在做整体项目计划前,还要大致计算一下你手上的资源。首先是时间,现在市场竞争激烈,往往很多项目要求在几乎不可能的时间范围里完成。对于这一点,你在做项目的风险控制计划的时候要充分考虑。其次是人员,根据项目预算和已往经验,大致计算一下未来的项目小组有多少种角色,每个角色目前公司是否有人,是否能完全归这个项目使用,是否需要另外招聘一些人员,招聘的准备工作要尽早启动。最后就是一些设备的准备,项目所需大件关键设备要尽早预定,以后不管发生设备等人还是人等设备的情况,浪费的都是你的时间。所以,项目经理不仅要和客户有很好的沟通,熟悉自己公司内部的各种办事流程,知道如何和人事、财务部门打交道,也是一个很重要的方面;

5. 现在是做项目说明书的时候了。一份好的项目说明书不仅将要做的事情描述得很清楚(主要是讲做什么,而不是说怎么做),而且把如何检查也说明得很透彻。也就是说它不仅说明白了要做哪些事情,也让客户的业务人员(一般不懂技术)知道项目做成什么样就算完成了。简单地说,项目说明书描述项目做哪些事情和每件事情做到什么程度以及如何检查每一个结果。

6. 是到做总体计划的时间了吗?不,你现在已经知道了客户的目标和你手上的资源,那么做计划以前,你还需要和你的经理和客户充分沟通资源的问题。因为很多资源是还不明确的,你需要写一份报告,详细分析这个项目的风险以及对资源的需求情况。如果一些问题不能得到解决的话,将发生什么样的后果。如果资源不够,就要高层改变策略,增加对这个项目的投入。甚至在条件许可的情况下,有些公司会放弃这个项目。总之,没有人能完成一个不可能完成的任务,如果项目经理不能尽早发现风险,做出对策,那么就只能去当烈士了。

7. 明白了要做哪些事情和你手上的筹码以及你做这个项目的总体策略,现在是成立项目小组的时候了。很多项目经理都没有自己选择组员的权利,那么,就尽量发挥你的影响力去寻找那些你想要的人吧。成员的组成根据项目不同,相差较大,很难有什么具体要求,但是,一定要有精通客户业务的人,很多小项目里,这个人就是项目经理本人,大项目里会配备行业专家(Industry expert),这样和客户沟通起来才不会鸡同鸭讲,双方才可以相互理解。我经常看到的情况是我们的技术人员和客户交谈时满口的专业术语,结果搞得客户一头雾水,反过来,他还指责客户不懂技术。其实,明白自己想做什么的客户已经是很好的客户了,不知道自己要做什么,更不懂怎么做还要指手画脚的客户到处存在,但是要明白,是客户选择了你,而不是你选择了客户,有了客户你才有工资拿,心平气和一点吧;

8. 现在你要面对三群人:你的领导、你的组员和你的客户,和这些人沟通,让他们知道你打算怎么做,什么时候要他们做什么准备这些事情将是你的主要工作。既然沟通这么重要,那些事先定义一下沟通的原则也是一件很要紧的事情。很多沟通原则都是潜规则,如果你在一个部门时间做长了,对这些规则的运用觉得是一件理所应当的事情,但是,你现在面对的是多个部门甚至多个单位,不把沟通规则说清楚,你以后就会吃亏。

下面的东西看起来无聊,其实还是很管用的:
第一个是规定信息的流动方式和介质,是推还是拉。推的意思就是项目经理将主动发布信息,不管通过电话、邮件还是书面方式,保证将信息传达到每个人。这种情况适合小项目,人少;拉的意思就是项目经理就是一个类似web服务器,你自己需要什么信息就去问他。当然,没有项目经理把自己搞得那么累,他会用发布信息到公共介质的方式公布信息,简单的是白板,复杂一点的是项目的公共信息交互区,潜规则就是我发了你没去看就不要说我没告诉你。说这些看似很无聊,其实里面牵涉信息传达不完全的责任问题。当然,这些都是指一般的方式,而且不要绝对化,一般情况下,主动沟通和被动访问是同时存在的,尤其是对领导,项目经理更加应该主动去和领导沟通。
第二个问题就是文档问题,很多人怕写文档,但是项目经理一定要牢记"好记性不如烂笔头"的道理。有理有时候为什么会说不清呢?就是因为没有证据。所以项目经理开始就要和客户说清楚有些文档是必须签字的,比如项目经理的项目日志,每个星期至少让客户签字,另外所有达成共识的东西,比如会议纪要,甚至领导的讲话记录,都要写成文档,双方签字,这样以后扯皮的时候,就能做到有据可查。记住:说了的就和没说一样,只有写下来大家签字后才算真正认可了的。还有一些问题,比如你提交的报告,给领导(包括本方领导和客户领导)做一个选择题,结果领导压住不批,让你无所适从,结果拖延了进度。这时候,你可以等,但是注意要留记录,标明是谁的责任;另外,如果你在开始阶段就和领导商定:如果批示提交三天后没有得到领导答复就算对方同意,这样你就会主动很多。再比如不同事件的审批流程问题:什么等级的事情记录在项目日志里、什么等级的事情要双方项目经理专门签署备忘录、什么等级的事情要双方领导出面签署合同附件等等。事先想得越周到,以后的工作就越主动。

好了,做了很多前期工作,定义了一些游戏规则,现在是坐下来做计划的时候了。这一节,任意找一本项目管理的书都会说得比我好,所以我就少写一点,说一些自己的体会就是了。

首先是找几个关键组员,比如客户业务专家、系统分析员等等,做一下项目模块划分工作。项目分成几块去做,每一块完成什么,模块之间的信息如何交换等等。需求定义的是做什么的问题,而这里说的是怎么做的问题。这里要强调一点:完成一个目标有很多种方式,你要选一种你最熟悉的,而不是看上去最完美的,这个思路会让你的项目减少很多风险。有时候客户会被某种新技术打动,坚持要你采用那种新技术,你就应该告诉他:你选我做这个项目,就应该容许我采用自己最喜欢的方式做事情,新技术之所以有诱惑力,就是因为吃亏的人还不多,我不希望你成为第一批受害者。采用一个计划会让你的工作更加明确,比如用微软的Project软件,你填写完表格以后,就可以知道这个项目有多少件事情要做,每件事情需要什么资源,他们之间的前后关系如何,消耗的时间有多长,完成后有什么标志等。所有的结果可以用例如甘特图的形式表现出来。你做完这个表以后会惊奇地发现,甘特图上项目的结束时间会远远落后于你的计划结束时间(签合同的人永远不会先征求你的意见的)。当然,学过项目管理的人会大谈什么WBS、优化路径之类的东西,但是我的经验是你再优化也不可能把这些东西安排到计划的时间结束。如果你没碰到这个问题,在我恭喜你挑了一个轻松活之前,请你再去确认你是否罗列了所有要做的事情和正确评估了他们所需要的时间。这时候,你就要考虑牺牲一些任务的时间(也意味着质量)了。按照什么标准牺牲?这个项目的战略!我们在第三节提到过的战略。我的经验是如果你什么都赶进度,其结果可能就是十件事情你一件也没做好,想想多么失败啊。所以,把资源投到你熟悉和有把握的事情上,最后的结果是十件事情,你有三件做成了精品,三件完成,还有四件因为某些原因延误,成绩单是否靓丽了很多呢?战略决定优先级,而正确排列事情的优先级是一个项目经理能力的主要体现。

好,现在项目已经完成了前期工作,了解了项目的目标、搞清楚了手上的资源,制定了项目的策略,然后编制了项目的整体计划,项目进入实施阶段。进入这个阶段反而是项目经理比较空闲的时候,不像前期的时候项目经理要象记者一样到处和不同的人接触,搞清楚他们在说什么,努力猜测他们在想什么和他们的真正目的,那才是最累人的事情。当然,小项目的项目经理往往自己也是一个资源,要做很多事情,这时候反而比谁都苦。项目经理这段时间的主要工作是保持和客户领导以及自己领导的沟通。和客户领导沟通时特别要注意,除非你需要对方给你支持,那么你才需要讲得具体一点,否则,告诉他一切正常就可以了,而且态度要积极一些,千万不要说一些领导不懂的细节,比如:

“王局长,最近项目进度还算正常,就是JVM经常发生一些内存泄漏的情况…”

王局长:“……(*&$@@”

和自己的领导汇报也要注意这个问题,除非他是一个技术高手,你需要他的技术经验,否则一般就汇报进度是否正常以及有问题时你的对策和打算就可以了,有些需要他支持的地方,比如资源调用需要说详细一点。

和组员开会,除了一些项目进度跟踪会议以外,还有很多讨论会,需要大家用头脑风暴方法给出解决问题。与会人员很多都是技术人员,他们的特点是注重细节、缺乏大局观、有点消极悲观、自尊心强(如果总结得不对,欢迎大家拍砖),所以,你作为会议的主持人,只要负责提出问题和记录下他们的观点,千万不要做评判者的角色。一个问题,有很多方面,从不同的角度看,现象是完全不同的,想想盲人摸象的故事吧。这些技术人员,他们往往精通一个方面,就自己的角度发表见解,除非一些很特别的情况,你都应该认为,他们提出的方案,从他们的角度来看是最合理的。你的长处是掌握事情的优先级,评估各个方面的轻重缓急,从而根据他们的意见得出一个合适的(而不是正确的)方案。所以,在会议上,你要充分尊重每一个人和他的意见,夸奖那些意见提得比较好的人,千万不要把会议带入无休止的争论(你要让大家知道事情不是非黑即白的,而是多元的,唉,我们的教育惹的祸…)。会后,你自己整理结果,写文档,做决定。会议上大家的面子都被照顾了,自然实施起来的阻力就小,如果还有意见的,你就私下找他聊,如果还不能说服他,你就要让他明白,因为你负责这个项目、你担当风险,所以,这个优先级应该你来判断。组织中的高层,并不见得水平会比一般的成员高,但是,他要承担组织的风险,加之信息的不对称性,所以,对事情的优先级的判断肯定比下属强。

另外,你还可以采用一些专业的方法论来解决这种讨论问题,比如著名的六顶思考帽。你可以按照不同的帽子颜色来组织大家思考,如在白色帽子里讨论客观的事实;在黄色帽子里讨论做这个事情的好处;在绿色帽子里发挥创新,看看这个事情能做成什么样子,发挥想象力;在蓝色帽子里讨论做事情的逻辑、步骤;在黑色帽子里讨论未来的风险和预防措施;在红色的帽子里谈谈大家对这个事情的主观感受。这样会议才不会失控,观点也被罗列得很清楚。

在开发过程中,内部管理还要注意的一点是时刻强调以验收为目的的思想,每个任务的最终可交付成果一定要是可以被检查的,比如,【界面要求:美观大方、简洁明快】,这个要求我就不知道如何检查。所以,给开发小组布置任务的时候就要考虑如何检查结果,比如我见过一个计划,里面有一个任务【开发人员熟悉EJB编程】,这个任务,除了让这些人去参加一些专业认证考试,否则,结果很难被检查。所以,时刻考虑如何检查结果、如何向客户交付是项目经理一直要注意的事情,我听说有些老项目经理拿到项目是倒排计划的,即首先看如何验收和验收标准,然后决定工作计划。很多项目开始了很久,还不知道如何验收,那么这个项目出问题的可能性就很大了。做项目就是为了验收,拿到钱,我们的角色不是研究机构,我们的目的就是在付出那么多劳动后得到结果。另外我插一句:我是极其不主张到客户现场开发的。尤其是一大群技术人员直接和客户交流,很容易引起冲突和矛盾(技术人员的本性决定的)。我的做法是项目经理和项目实施人员到现场,软件开发人员还是在公司做项目。项目实施人员就是初级项目经理,他们了解自己的产品,懂得一些客户的业务,关键是在于他们具有良好的沟通能力,俗称“皮厚”。他们是客户和研发人员的桥梁,其职业方向也是很机动灵活,以后可以有很多方向可以转,比如销售、行业顾问等,其出路反而比开发人员的路要宽得多。

接着,我们再谈谈最让人头痛的需求变更问题。变更通常分为两种:一种是部分更改了原先的目标,即需求变更;另一种是没改变目标,但是客户不满意目前的实现方式,大到流程的实现,小到界面的布局,都是属于这类。碰到这种情况是难以避免的,主要是事先沟通的不够充分和客户随着项目的进展,慢慢想清楚了问题,改变了以前的思路。这时候,如果需要改并且你的战略是容许这种情况的,那么注意下面几点:

1. 确保以前的文档,就是记载着以前的结论的东西,客户是否签过字,如果没有,赶紧把你的工作停下来,赶快再和客户自己确认一下你的方案,然后让他签字,避免以后说话没有凭据;

2. 和客户坐下来,自己探讨他修改的根本目的是什么,是不是有同样能达到相同目的,但是对你来说有代价更小的选择?

3. (项目初期的工作)明确更改流程,一般是客户指定一人签字(否则客户每个领导都有权力来插一杠子,你就废了),以正式项目文件的方式提交给你,然后,你做评估分析,分析对成本、进度的影响,在你的领导同意后,出相应意见书,主要是要说明更改设计的原因和指出由此带来的不确定后果(这个东西先写出来,后面如果真的发生了,至少不是你的错)。然后再让客户在上面签字。见过医院给病人做手术以前让家人签的免责条款吗?对,就学习那个,让大家都意识到任何的更改都有成本和代价。

所以,对于这种需求天天变的客户,你就一定要事先做好规矩:
一、统一联系人,客户指定一个人和项目组进行沟通,不能张领导、王领导都来说几句,如果他们意见不一致,那你只有得罪领导的选择了,所以,项目的最初就要定好规矩,我项目组只认一个的意见,有什么要求你们内部先统一再和我谈,我不想卷入你们内部业务部门之间的矛盾之中;

二、所有需求变更全部要有书面文字,这点切记!这样做好处多多:

*有书面证据,以后他还想改,你有了他以前要求的证据,告诉他:你以前可是这么说的;

*便于需求变更管理,需求如何慢慢演变的历史可以看清楚,从而更深切地体会客户的目的;

*对于客户来说,嘴巴一动最方便,反正是你们做,不花他的资源,所以要求是否合理,是否和项目的目的一致,他是不负责任的。但是如果要他写书面要求,还要签字盖章,他就要谨慎多了,而且一写东西,思想就会更加深入,很多无理要求也就这样胎死腹中了;

系统开发告一段落后,就进入客户培训、系统验收阶段,这个阶段,我一般会注意以下几个问题:

给客户做培训前,多注意一些表面功夫。很多程序员认为,既然很多系统采用原型法,有一个由粗到精的过程,那么系统的逻辑核心是否正确才是关键,至于界面如何,界面上的用词是否准确,那是无关紧要的问题;而且培训的时候也是空手上台、信手拈来,想到哪里说到哪里,下面听讲的人不知所云,云山雾罩,培训效果自然可以想象。我的体会是,给客户做培训的版本,如果你在做多次测试以后仍然不能确定逻辑是否合乎要求,那么,你至少要在界面上多花一点功夫。注意每个界面的布局、用词、链接的正确性等等,总之不要让客户看到一些他不该看到的东西,否则,仅仅因为一些无关紧要的报错就让客户第一印象觉得系统不稳定,那你就真的比窦娥还冤了。如果工作再做得详细一点,可以做一些类似Flash的东西,把一些你要强调的重点用通俗易懂、轻松愉快的方式表达出来。文档方面,准备至少两个文档:用户手册和培训手册。这两个文档的内容很多都是一致的,但是角度完全不同。用户手册往往是站在系统设计者的角度,按照自己的思路,分模块讲解系统的操作和功能;而培训手册,一定要站在客户业务人员的角度,根据每个角色面对不同业务的办理,如何通过使用本系统的一系列功能来实现目标。所以,第一次培训以前,系统界面是否完整正确、培训文档是否完备、培训时所举的例子是否有代表性都是很关键的因素,第一炮打不响,以后就麻烦很多。

上面讲的是培训的时候,丑媳妇要化妆好再去见公婆的问题。其实,项目实施中还有一个考验项目经理功力的就是如何调动客户积极性的问题。一般来说,客户是懒的,这就是他花钱找你做事情的原因。一个项目的成败,和客户的配合程度很有关系。根据我的分析,一般项目中的客户都可以分为三类:支持的、消极观望的、抵触的。他们人数的分布一般是一个纺锤形:支持的和抵触的人少,观望的人多(如果你接了一个人人都抵触你的项目,那你还是不要做了)。首先,分析一下那些人为什么支持你和抵触你。很简单,于公于私两个方面分析,上了新系统,谁的工作量有所变化?谁的潜在利益是否受到威胁?谁的岗位是不是因为新系统而消失?传统的利益格局因为新系统的使用而发生怎么样的变化,这些东西,都是项目经理必须去了解的,这样,你才能团结那些支持你的人,消减那些抵触你的人。项目经理是一个很奇怪的角色,属于典型的责任大、权力小的角色,他能做的只有借力打力,不管在自己公司还是在客户那里,一定要依靠别人才能完成自己的目的。只有了解哪些人会因为什么而帮助你,哪些人会因为什么而抵触你,你才能让客户配合你做工作。比如上一些内部计算机辅助管理系统,其必然后果就是让本来管理混乱时有人可以浑水摸鱼的一些利益消失掉了,这样,有些人肯定就要捣乱,到处诋毁这个系统。这时候,你就可以散布一些"谁抵制新系统就说明自己屁股上有屎"这类的论调去压制他们,减弱他们的影响。总之,团结积极分子,打压敌对分子,带动大多数是你的基本策略。

还有一个体会和大家分享:千万不要觉得对方的领导(中层干部)是应该配合你工作的,特别是一些国营单位,多一事不如少一事,他干吗要帮你?我的经验是:对方领导如果没有拿你的事情作为内部斗争的武器而从中作梗(当然,他针对的不一定是你),那已经是算合作的了,记住,他不捣乱就是帮你忙了。

作为项目经理,其实脑子里就是几样东西:做哪些事情、做到什么程度、怎么交货、手上的资源以及各个事情的优先级。所谓多快好省那是人类的梦想,这四个方面都是相互矛盾的,属于典型的又要马儿跑,又要马儿不吃草的类型。一般说来,项目经理在考虑问题的轻重缓急方面,往往是把快放在第一位,各方领导都会给你最后期限,所以保进度是第一位的;省是第二位的,企业的根本目的是盈利,如果收入不能增加的话,至少费用要控制住;好是第三位的,没办法,谁都想精益求精,但是,没有强大的资源保障,质量只好先牺牲了;最后是多,客户的要求源源不断,如何降低客户的期望值,把项目控制在一个合适的范围内,让客户从理想回到现实也是项目经理的分内工作。

验收前,除了做好文档工作,即可交付成果以外,多花时间搞清楚客户的做事情流程是很重要的事情,一个公司做事情必定有流程,所以搞清楚流程十分关键。比如验收、付款这些你极其关心的事情,客户那边的流程是怎么样的,谁牵头组织、哪些人参加,要什么文件、走什么程序、哪些人签字、最后出什么文档等等,都要搞清楚,特别要事先分析和打听哪个环节容易卡壳,做好事先的准备。

我对验收最大的体会就是举证问题。即千万不要让客户这么想:你必须有证据证明你的系统是没问题的。这样你就没戏了,微软那么多天才,做了个Windows还天天打补丁,要你的程序没问题,既不可能,你也没办法拿出证据。你要让客户明白,所谓验收,就是我按照测试文档的测试用例跑一遍,结果和预期结果一致就应该算通过了,而且还容许有一些小错误留在验收后改正,他可以对测试用例提意见。所以,验收前双方要确认测试计划和测试用例。如果他认为系统不符合要求,那么他应该举证,证明这个系统和最初设计相背离的。所以,参考法律概念,千万不要举证倒置。另外,认为系统完美了才能验收的想法也是错误的,软件开发合同里一定要注明验收以后维护期的费用问题,否则,客户担心一旦验收就得不到你们的支持,自然不配合验收,那么,你这个项目经理就很难交功课了。

最后,我想谈谈如何评价项目经理的绩效的问题,我认为,项目经理有以下几个档次:

*最差的项目经理:项目过程中总是出现意外,然后自己又解决不了,结果成为烈士;
*二流的项目经理:项目也经常出现意外,但是他一马当先,奋勇向前,解决了一个又一个问题,最后,勉强算把项目结束了,获得了领导的一致好评;
*一流的项目经理:平时很少见他做具体的事情,整天找人聊天,然后就是写报告、做计划,最后项目顺利结束,整个过程平淡无奇;

项目管理到底是一门科学还是一门艺术呢?所谓科学就是经过反复论证,输入和输出有必然规律的东西,种瓜得瓜;而艺术就是思想火花的闪耀,主要靠灵感。项目管理这个东西,据一个前辈说,在国外是科学,80%是有规律可循的;在国内是艺术,主要靠个人魅力、感染能力等东西。看明白了PMBOK,学会了一些做事情的方式,只是搞懂了那个20%的科学的东西,还有80%的空间,属于见仁见智的领域了。所以,加强很多方面的个人能力,如练就出色沟通能力、提升自己的个人魅力对于项目经理来说是多么重要啊,无论是对内还是对外。作为一个一流的专业人士,在顺利让客户签字的同时,如何让自己的领导知道你的价值,这也是体现自己能力的一种途径。

2009年3月17日星期二

开源脑图软件Freemind



脑图(mind-mapping),不是脑电图,是一种整理、组织和记录想法、观点以及信息的方式。一个脑图软件可以帮助你或者你的团队完成一次头脑风暴、规划一个新的项目、跟踪一个项目的发展、整理为一篇论文而搜集来的资料等等很多用处。

脑图(mind mapping)是一种整理思路,启发创造性和寻求解决方案的实用技能。通过脑图,你可以很快将凌乱的信息结构化,以一种易写易读的方式组织起来,帮助你理解问题本身。

脑图可以用于完成下列工作:
总结归纳信息
汇总来自不同资源的信息
辅助思考复杂问题
展示问题的主要框架

脑图因为非常形象,还很适合于辅助记忆。

下面是一个脑图的简单例子:

将一个问题化解成一个脑图,可以按照下面的步骤:
在中间写下问题的标题。
将主题分解成若干子问题,作为主题的分支。
如果子问题还可以化解,或者某些信息属于子问题,还可以继续产生下一级分支。
对于相关的事实或者产生的想法,都可以标注在相关节点周围,层层发展下去。

每出现新的情况、信息或者想法,很容易将它们添加到脑图合适的位置。一个完整的脑图就是以主题为中心放射性发展的结构。子主题或者相关信息都是一个个的分支。
一旦你开始熟悉脑图的实用方法,就可以自己总结一些技巧和使用习惯。这里有一些建议:
尽量使用简洁的文字来描述信息。
字迹清晰。如果用脑图软件应该没有这个问题。
使用不同的颜色区分不同的想法。
善用符号和图标。
对于不同部分有关联的内容可以使用交叉连接。

脑图是一种非常有效的记录整理工具,不仅可以展示事实,还可以表现它们之间的关系,甚至发现你本来没有发现的联系。

Freemind是一个基于java的开放源码脑图软件,支持Windows、Linux和Mac多种操作系统,曾被评为sourceforge 2006年二月当月软件。如果你也经常感到思维发散,头绪繁多,可以试试脑图软件。

http://freemind.sourceforge.net/wiki/index.php/Main_Page

2009年3月11日星期三

test.java, customer.java

// test.java

import org.hibernate.*;
import org.hibernate.cfg.*;

public class Test {

public static void main(String[] args) {

try {
SessionFactory sf =
new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
Transaction tx = session.beginTransaction();

for (int i = 0; i < 200; i++) {
Customer customer = new Customer();
customer.setUsername("customer" + i);
customer.setPassword("customer");
session.save(customer);
}

tx.commit();
session.close();

} catch (HibernateException e) {
e.printStackTrace();
}
}
}

// customer.java
public class Customer {

private int id;
private String username;
private String password;


public int getId() {
return id;
}

public String getPassword() {
return password;
}

public String getUsername() {
return username;
}

public void setId(int id) {
this.id = id;
}

public void setPassword(String password) {
this.password = password;
}

public void setUsername(String username) {
this.username = username;
}

}

Customer.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Customer" table="CUSTOMER">
<id name="id" column="CID" type="java.lang.Integer">
<generator class="increment" />
</id>
<property name="username" column="USERNAME" type="java.lang.String"/>
<property name="password" column="PASSWORD" type="java.lang.String"/>
</class>
</hibernate-mapping>

hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory name="java:/hibernate/HibernateFactory">

<property name="show_sql">true</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://127.0.0.1:3306/javatest
</property>
<property name="connection.username">
javatestor
</property>
<property name="connection.password">
secret
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>

<mapping resource="Customer.hbm.xml" /> <!-- 指定Customer的映射文件 -->

</session-factory>

</hibernate-configuration>

apache build.xml for a hibernate demo

<?xml version="1.0" encoding="utf-8"?>

<project name="build.xml" default="build">

<!-- path -->
<property name="src.java.dir" location="src"/>
<property name="build.classes.dir" location="classes"/>
<property name="hibernate.lib.dir" location="C:/java/hibernate-distribution-3.3.1.GA"/>
<property name="mysql.lib.dir" location="C:/java/mysql-connector-java-3.1.14"/>

<!-- classpath -->
<path id="project.classpath">
<pathelement location="${build.classes.dir}"/>
</path>
<path id="library.path">
<fileset dir="${hibernate.lib.dir}/lib">
<include name="**/required/*.jar"/>
</fileset>
<fileset dir="${hibernate.lib.dir}">
<include name="hibernate3.jar"/>
</fileset>
<fileset dir="${mysql.lib.dir}">
<include name="mysql-connector-java-3.1.14-bin.jar"/>
</fileset>
</path>

<!-- action -->
<target name="init">
<mkdir dir="${build.classes.dir}"/>
</target>

<target name="build" depends="init">
<javac srcdir="${src.java.dir}" destdir="${build.classes.dir}">
<classpath refid="project.classpath"/>
<classpath refid="library.path" />
</javac>
<copy todir="${build.classes.dir}" >
<fileset dir="${src.java.dir}" >
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>

<target name="run" depends="build">
<java classname="Test" fork="true">
<classpath refid="project.classpath"/>
<classpath refid="library.path" />
</java>
<echo>If you see this,it works!!!</echo>
</target>

<target name="clean">
<delete dir="${build.classes.dir}"/>
</target>

</project>

2009年3月5日星期四

epoll为我们带来了什么

Q:网络服务器的瓶颈在哪?
A:IO效率。

在大家苦苦的为在线人数的增长而导致的系统资源吃紧上的问题正在发愁的时候,Linux 2.6内核中提供的System Epoll为我们提供了一套完美的解决方案。传统的select以及poll的效率会因为在线人数的线形递增而导致呈二次乃至三次方的下降,这些直接导致了网络服务器可以支持的人数有了个比较明显的限制。

自从Linux提供了/dev/epoll的设备以及后来2.6内核中对/dev/epoll设备的访问的封装(System Epoll)之后,这种现象得到了大大的缓解,如果说几个月前,大家还对epoll不熟悉,那么现在来说的话,epoll的应用已经得到了大范围的普及。

那么究竟如何来使用epoll呢?其实非常简单。
通过在包含一个头文件#include 以及几个简单的API将可以大大的提高你的网络服务器的支持人数。

首先通过create_epoll(int maxfds)来创建一个epoll的句柄,其中maxfds为你epoll所支持的最大句柄数。这个函数会返回一个新的epoll句柄,之后的所有操作将通过这个句柄来进行操作。在用完之后,记得用close()来关闭这个创建出来的epoll句柄。

之后在你的网络主循环里面,每一帧的调用epoll_wait(int epfd, epoll_event events, int max events, int timeout)来查询所有的网络接口,看哪一个可以读,哪一个可以写了。基本的语法为:
nfds = epoll_wait(kdpfd, events, maxevents, -1);
其中kdpfd为用epoll_create创建之后的句柄,events是一个epoll_event*的指针,当epoll_wait这个函数操作成功之后,epoll_events里面将储存所有的读写事件。max_events是当前需要监听的所有socket句柄数。最后一个timeout是epoll_wait的超时,为0的时候表示马上返回,为-1的时候表示一直等下去,直到有事件范围,为任意正整数的时候表示等这么长的时间,如果一直没有事件,则范围。一般如果网络主循环是单独的线程的话,可以用-1来等,这样可以保证一些效率,如果是和主逻辑在同一个线程的话,则可以用0来保证主循环的效率。

epoll_wait范围之后应该是一个循环,遍利所有的事件:
for(n = 0; n < nfds; ++n) {
if(events[n].data.fd == listener) { //如果是主socket的事件的话,则表示有新连接进入了,进行新连接的处理。
client = accept(listener, (struct sockaddr *) &local,
&addrlen);
if(client < 0){
perror("accept");
continue;
}
setnonblocking(client); // 将新连接置于非阻塞模式
ev.events = EPOLLIN | EPOLLET; // 并且将新连接也加入EPOLL的监听队列。
注意,这里的参数EPOLLIN | EPOLLET并没有设置对写socket的监听,如果有写操作的话,这个时候epoll是不会返回事件的,如果要对写操作也监听的话,应该是EPOLLIN | EPOLLOUT | EPOLLET
ev.data.fd = client;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
// 设置好event之后,将这个新的event通过epoll_ctl加入到epoll的监听队列里面,这里用EPOLL_CTL_ADD来加一个新的epoll事件,通过EPOLL_CTL_DEL来减少一个epoll事件,通过EPOLL_CTL_MOD来改变一个事件的监听方式。
fprintf(stderr, "epoll set insertion error: fd=%d0,
client);
return -1;
}
}
else // 如果不是主socket的事件的话,则代表是一个用户socket的事件,则来处理这个用户socket的事情,比如说read(fd,xxx)之类的,或者一些其他的处理。
do_use_fd(events[n].data.fd);
}

对,epoll的操作就这么简单,总共不过4个API:epoll_create, epoll_ctl, epoll_wait和close。