2007-07-15

激励

李广和程不识在管理上,一宽一严,都成功了。士兵爱戴李广,愿意随之出生入死,而司马光却告诫后人不用随便学李广,除了说李广是学不来的,后继者无法继续外,还说:

夫小人之情,乐于安肆而昧于近祸,彼既以程不识为烦扰而乐于从广,且将仇其上而不服

至此,司马光这个老封建的反动本性显露出来了,诬蔑我们“人民子弟兵”好逸恶劳,还试图扼杀李广式的爱兵如子的将军,以免大家有逃离大棒,转投胡萝卜的想法。这事放到现在判一个反人道主义罪或反人类罪应该没啥问题!

当然,对于一个千年以前的人愤怒是毫无意义的,心平气和地分析才是更重要的。

李广真的不能学吗?其实不是不能学,而是一般人学不会。李广“行无部伍、行陈,就善水草舍止,人人自便,不击刁斗以自卫,莫府省约文书”,以至“咸乐为之死”,这对一般人来说太高深了,对士兵实行的是内在激励方式,使士兵自己主动卖命,而不是需要后面跟着一个端着刺刀逼迫才前进的。这当然不是例行公事的领导所能做到的,因此才说后继的很可能就做不到。

程不识呢?和李广相反,“正部曲、行、伍、营陈,击刁斗,士吏治军簿至明,军不得休息”,靠的是严酷和纪律,但“士卒亦多乐从李广而苦程不识”,典型的外激励方式。这种方式需要做到严格执行,例行公事即可。

这两种方法的境界有高低,但效果很难说哪个更好,得看环境。抛去阶级感情来看,对于军队来说,司马光分析的还是很有道理的。军队里工作方式是要真正拼命的,要使内在驱动力达到能使人拼命的程度,激励的成本是很高的,相较之下,由国家机器在背后支持下的大棒式外在激励却成本低廉,对于全国大规模推广具有可行性。

2007-07-13

和平演习

冯唐易老,看来俺也老了,上周轻微的气温波动就带来了一场不大不小的感冒 :(

也可能是刚又看了一遍《系统思维导论》的缘故,潜意识里对免疫系统很久没有大规模实战感到担忧,于是发动一场实战演习。从回复的速度上来看,效果还是蛮好的 :)

同时也提醒:对“储备”的透支需要及时补上……

2007-07-08

冯唐易老,李广难封

嗟乎!
时运不济,命运多舛。
冯唐易老,李广难封。

这是《滕王阁序》中作者在暗怨自己生不逢时,怀才不遇,用古人的事例宽慰自己。看来这怀才不遇的抱怨是由来已久,因“时运不济,命运多舛”而郁闷的人何止一人哉!

冯唐就不说了,除了为人耿直直言之外好像也没有太多的英雄色彩。但飞将军李广就不一样了,从小学课本的“但使龙城飞将在,不叫胡马度阴山”、“林暗草惊风,将军夜引弓。平明寻白羽,没在石棱中”等诗句就开始知道并崇拜这位名将。高中时读《史记》,看到司马迁记载的李广传,更深入了解其一生的传奇经历,更认同《滕王阁序》中的感叹:时运不济,命途多舛。如此勇猛的战将,一生对匈奴七十余战,却终生没有获取封侯的荣誉,最终落得个自杀的下场,不禁让人扼腕叹息,为其鸣不平。

最近在读《资治通鉴》的时候,再次读到关于飞将军的记载,和史记中的记载类似,只是按年代将其他人同时发生的事穿插记载,更有时间及背景关联。又感叹了一番。

其实,在《史记》和《资治通鉴》中对李广治军和才能描述中都有和另一位将军程不识的比较:

广行无部伍、行陈,就善水草舍止,人人自便,不击刁斗以自卫,莫府省约文书;然亦远斥候,未尝遇害。程不识正部曲、行、伍、营陈,击刁斗,士吏治军簿至明,军不得休息;然亦未尝遇害。不识曰:“李广军极简易,然虏卒犯之,无以禁也;而其士卒亦佚乐,咸乐为之死。我军虽烦扰,然虏亦不得犯我。”然匈奴畏李广之略,士卒亦多乐从李广而苦程不识。

从这段记载可以看到,李广和程不识,一宽一严,但都能达到御敌的效果。但从人性化及受欢迎程度上来讲,李广显然要胜出很多,士卒“乐从”、“乐为之死”,这是领兵很高的境界,也是很多名将共同的优良品质,在史书中大书特书。因此,读过这个对比,对飞将军的敬佩更进了一层。

但是,在《资治通鉴》中,这段之后,司马光紧接着就是一段点评:

臣光曰:《易》曰:“师出以律,否臧凶。”言治众而不用法,无不凶也。李广之将,使人人自便。以广之材,如此焉可也;然不可以为法。何则?其继者难也;况与之并时而为将乎!夫小人之情,乐于安肆而昧于近祸,彼既以程不识为烦扰而乐于从广,且将仇其上而不服。然则简易之害,非徒广军以禁虏之仓卒而已也!故曰“兵事以严终”,为将者,亦严而已矣。然则效程不识,虽无功,犹不败;效李广,鲜不覆亡哉!

这个点评点出了很重要的一点,对心中的一个疑问“宽和严,到底哪种方法好?”有了很好的分析。司马光首先肯定了李广的才能,承认以李广的才能完全可以这么做,但这种做法不能作为学习的榜样,因为他的继任者很难办。

这点太重要了,李广凭借其个性和才能,能成功统帅这只军队,但他的下一任怎么办呢?这样的个性和才能其他人是很难有的,或者说不可能有的,习惯了这种领导方式的士兵很难被其他将军统领。以至于无法保证持续的战斗力。

这也许也部分解释了“李广难封”的原因。

2007-07-02

Cunningham's CRC for OOD training

做开发的恐怕没有人不知道“面向对象”这个词,虽然对其不感冒的人也是有的,但毕竟是极少数,大部分程序员还是极力拥抱“面向对象”的。您要是指责某人不懂“面向对象”,非跟你急不可。

对于“面向对象”的特性和特征,大部分人应该还是说的上来的,但要说动手练练,那又是另外一回事了,“挂羊头卖狗肉”者大有人在,即用“面向对象”语言写着“过程式”程序,还一口咬定“我这就是货真价实的‘面向对象’,假一赔十!……”

其实,这也不能怨这些人,老师就这么教的,即使老师没有这么教,也没有说不能这样做,国内教科书也一样,简单堆砌了一些概念就以为“面向对象”结束了,结果的确学会了“类”、“成员变量”、“方法”……并且也能和以前用“过程”语言(如C语言)一样写出程序来,一样能跑通,于是简历上就加了一项“精通面向对象程序开发……”

曾经也经历过这个阶段,还用这种方式写出不少代码,这些代码还进入了正式系统 -_-!

最终的迷途知返是因为看了一些国外牛人的书,再加上之前摸爬滚打过程中的体验,才在“原来如此!”的惊叹中明白自己原来根本没有懂过“面向对象”,继而庆幸这些没有白读。

如下是一篇OOD文章中的片段,其中有一部分介绍了如下的CRC面向对象设计教学法,眼睛为之一亮:“今儿这文章没白读”

In 1989, Kent Beck and Ward Cunningham taught classes on OO design, and they had problems getting people to abandon the get/set mentality. They characterized the problem as follows:

The most difficult problem in teaching object-oriented programming is getting the learner to give up the global knowledge of control that is possible with procedural programs, and rely on the local knowledge of objects to accomplish their tasks. Novice designs are littered with regressions to global thinking: gratuitous global variables, unnecessary pointers, and inappropriate reliance on the implementation of other objects.

Cunningham developed a teaching methodology that nicely demonstrates the design process: the CRC (classes, responsibilities, collaboration) card. The basic idea is to make a set of 4x6 index cards, laid out in three sections:

  • Class: The name of a class of objects.
  • Responsibilities: What those objects can do. These responsibilities should focus on a single area of expertise.
  • Collaborators: Other classes of objects that can talk to the current class of objects. This set should be as small as possible.

The initial pass at the CRC card is just guesswork—things will change.

Beck and Cunningham then picked a use case and made a best guess at determining which objects would be required to act out the use case. They typically started with two objects and added others as the scenario played out. They selected people from the class to represent those objects and handed them a copy of the associated CRC card. If they needed several objects of a given class, then several people represented those objects.

The class then literally acted out the use case following these rules:

  • Perform the activities that comprise the use case by talking to one another.
  • You can only talk to your collaborators. If you must talk to someone else, you should talk to a collaborator who can talk to the other person. If that isn't possible, add a collaborator to your CRC card.
  • You may not ask for the information you need to do something. Rather, you must ask the collaborator who has the information to do the work. It's okay to pass to that collaborator information he needs to do the work, but keep this interaction to a minimum.
  • If something needs to be done and nobody can do it, create a new class (and CRC card) or add a responsibility to an existing class (and CRC card).
  • If a CRC card gets too full, you must create another class (CRC card) to handle some of the responsibilities. Complexity is limited by what you can fit on a 4x6 index card.

A recording made of the entire conversation is the program's dynamic model. The finished set of CRC cards is the program's static model. With many fits and starts, you can solve just about any problem this way.

2007-06-30

Java/OOP Code Inspection Checklist

Code Inspection的checklist可以分两方面内容:基本编程原则检查和语言相关检查。

基本编程原则

基本编程原则对大多数语言都适用,尤其是面向对象语言。

  • 格式
    • 由于有IDE(Eclipse, Netbeans……)的支持,代码格式可以很容易地自动编排,统一大家的代码格式很方便。
    • 乱糟糟的代码看起来很晕,没法让大家集中精力检查。
  • 命名
    • “编程语言”也是“语言”,需要传递信息。编程语言的规则能保证计算机能理解,但不能保证人能很好地理解。为了让人能理解,必须在变量、方法、类等命名方面下功夫,让人见名知意。
    • 有一些基本的规则,如:类用名词、方法用动词、变量用名词等,可以参考各语言约定俗成的编程规范。
    • 好的命名可以极大增加程序可读性。文档、注释也是为了理解程序。相较而言,程序同时还是最终真正“产品”,因此,应当让程序自身可读性加强,减少对文档和注释量的需求。这样在维护代码时会减少对文档和注释的维护量。
  • 消灭魔数
    • 所谓“魔数”指的是程序逻辑中包含的数字,这些数字可能在多处出现,或可能随时调整,如:
      • if(user.type==1) ......
    • 1代表嘛意思?得写个注释。如果定义成常量,有个名字,这地方就好理解多了。同时修改常量值比在代码中到处替换容易多了。
  • 注释
    • 意义就不用说了,老生常谈了。
    • 虽然老生常谈,但往往做成了两个极端:太少,太多。
      • 太少不奇怪,毕竟没有注释编译时也不会报错,人本性总有惰性。
      • 太多怎么可能呢,多了怕嘛?!的确有太多的情况出现,恨不得每一句话都写一个注释,解释这句话的作用,或者在每个方法、程序块前详细描述其中的操作过程,代码就是注释的映射。这就太过了:首先,打开程序看的应该都是程序员,看合格的代码应该不会比看大段的注释难,注释白费了。其次,稍微修改程序就得同步修改注释,否则以后以谁为准?麻烦得很!
    • 注释解释这段代码解决什么问题;代码本身接受如何解决。
  • 解决两地分居
    • 变量声明和使用相隔太远,或超过了必要的生命范围。
    • 在某些语言中,这是语言自身的限制,只得将就了。但对于变量声明位置灵活的语言,再这样做就不厚道了。
    • 变量就近声明;最小化生命范围。
  • 重复代码
    • 计算机上copy & paste太方便了,以至于大段的代码在程序中不断copy & paste。
    • 由于copy & paste的太快,往往该改的地方没有改过来,产生bug。
    • 修改代码的时候,由于被paste到太多地方,往往修改不完全,产生bug。
    • 应该训练一种意识,写代码时只要按ctrl+C的时候就好好想想能否把copy的东西抽出来做成共用方法,避免重复代码。
    • 即使没有copy & paste,多次手写重复代码也应有以上意识。
  • 长方法
    • 长方法难于阅读,受限于人脑的“缓存”,往往读了后面忘了前面,尤其在上下翻屏的情况下。
    • 抽出多个方法。主逻辑中通过方法名就可以知道逻辑过程,岂不美哉?!
    • 抽出的方法别其他地方调用的可能性大大增加,减少重复代码。
  • 巨类
    • 无所不包的类。由于包含了太多的功能,没有一个明确的现实对应,“四不象”。命名困难就是一个信号。
    • 一个类只应该有一个方面功能,不要多管闲事。
  • 耦合度
    • 类/模块之间的耦合度应尽量低。来回频繁反复调用应该避免。
    • 往往由于类/模块之间功能划分不合理造成。把方法放到合适的类/模块中去。
    • 调用者在一个逻辑中多次调用被调用者的方法。可以认为是“微观管理”。
      • Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.
  • 滥用全局/成员变量
    • 全局变量是否是必须的?
    • 成员变量是否应该是类的一个属性?
  • ……

语言相关检查

各语言有自己的pitfalls需要检查。例如Java中:

  • null
    • 是否在使用对象变量前判断不等于null?
  • equals
    • 对象的比较应该用equals。除非比较两个对象是否为“同一”对象,否则不能用==比较。
    • 自定义类,如果需要用equals比较,是否重写了equals方法?
  • 资源释放
    • 如IO操作使用的file、socket等资源,需要在使用后主动释放。
    • 为了保证资源的释放,需要在finally中主动释放。
  • ……

2007-06-28

Effective review

如何在软件项目中进行effective review?这是个问题。

在时间紧张的时候,大家过于关注自己的部分,往往对其他人的工作没有足够的熟悉程度,这时候进行review往往得不到好的效果,尤其是在不提前进行准备的情况下。

一直以来,认为大家先在底下独自review,然后再聚到一起把review结果汇报一下的做法不经济,所以选择让大家会上当场review,随着owner的引导,大家一路review过去。但一直有一个问题:很多人跟不上队伍,或者干脆不打算跟上,这样的review会留下很多隐患,以至于有些功能遗漏居然没有发现。其实大家独自review也会有这个问题,只是时间宽松一点,可以做的细致一点而已,但同样没有效率。

review最根本的功能有两个方面:例行检查与功能检查。例行检查目标是找出不符合普遍规范的地方,例如文档不完整,code形式不符合规范等。功能检查的目标是找出错误理解需求或遗漏需求的地方,也包括算法或架构性能、安全等方面的缺陷。

在采用现场review的时候,由于节奏很快,把这两方面的检查一起进行,可能就会导致很多人“身在曹营心在汉”的状况,review草草收场。

怎么办?分开呗,进行至少两遍review,第一遍例行检查,第二遍功能检查。如果有意见,也可以颠倒顺序。例行检查根据checklist进行,功能检查根据上一环节的input,如需求文档,设计文档等。

Document Review

首先owner展示文档,reviewer检查各部分是否齐全,是否遵守约定的模板。第二遍功能检查视各文档目的而定,如设计文档要看能否覆盖需求,如果不能,是否已在文档中指出。

Code Inspection

1.功能检查

按scenario进行,owner需要在会前准备scenario,并且标注每个scenario对应的需求点。

Inspection的第一步是检查scenario是否符合需求,覆盖所有需求点。

接下来对着每个scenario进行功能实现检查。

2.例行检查

例行检查的checklist需要在项目启动的时候定义好,或在编码前定义好,如果有人不熟悉,需要进行培训或沟通。

这个checklist需要经验的积累或借鉴别人经验的结晶,根据编程语言有所不同,例如C++语言需要检查指针操作、内存的分配/释放等,而Java项目就无须检查这些。但基本编程原则的check是一致的,例如变量命名等。

2007-06-21

按需解决:设计的“长尾”

以“长尾理论”的观点来看,“按需解决”就是对产品和服务的尾巴催长剂。

在产品供不应求的阶段,产品的设计在和客户接触准备交易前就已经结束了,对某一市场按照统一的设计生产产品或提供服务。当产品竞争激励的时候自然需要尾巴的增长,如何增长?在《尾巴可以再长一点!》中有过分析,其中对设计生产的分析提出了对生产设备智能化更进一步的要求,当然这是针对制造类产品,有了很容易更改设计的生产设备就能大规模生产定制化的产品。

其实,这里还有一个问题:如何设计?再智能的生产设备也还是需要输入设计才能生产产品。当然是根据用户的需求。

对于普通产品,所谓的设计可能让用户选择一些产品属性的参数就可以了,比如DELL的电脑直销,用户可以选择CPU、内存、硬盘等参数,然后DELL就会将这台定制的电脑送到你家里。这是很容易的。

对于一些针对行业用户的产品或服务,客户购买这些产品或服务是用来产生价值,对这类产品或服务的设计就没有上面所述的那么简单了,因此会有《按需解决之道》这本书专门写这个。通过按需解决产生的解决方案满足了客户的特殊化需求。

因此,按需解决实际上是设计上的“长尾”。

2007-06-18

按需解决之道

自从郭士纳喊出“谁说大象不能跳舞?!”之时,IBM这头笨重的大象就开始跳着舞步从“产品提供者”到“服务提供者”的转变,虽说这大象的舞姿不那么婀娜多姿,但到底是跳起来了,并且据说真的跳到了彼岸。当然,在彼岸的大象并没有停止跳舞,继续迈着舞步跳到了“按需解决方案提供者”的黄金海岸。

这就是《IBM按需解决之道》里描述的名为IBM的大象之舞。这本书描述了一个买方市场中卖方如何生存的“大道”:按需解决之道。

在产品提供者可以生存的时代,基本上是卖方市场,产品不愁没有买方,因此,产品提供者可以按照自己的想法设计产品,让买方适应产品,按照产品提供的功能凑合着使用产品。

当市场中的产品提供者越来越多,提供的产品越来越丰富,买方可以选择越来越多,于是买方开始关注产品提供的功能,而不在乎产品本身,这也是符合逻辑的,用户其实想要购买的是功能,而不是产品,在市场上能直接买到鸡蛋,何必非得买只会下蛋的母鸡回去呢?!即使市场上有不同类型的母鸡,如两条腿两个翅膀的、四条腿两个翅膀的、两条腿四个翅膀的等等,对于需要鸡蛋的人,这些都不重要,如果需要在这些参数上面花时间挑选,那太不经济了。于是乎,“服务提供者”粉墨登场,对客户直接提供服务,而非通过产品间接提供,比如不卖软件了,改为出租软件能力,如本来卖财务软件的,现在不卖了,把财务软件放在自己的服务器上,通过网络开放给客户,客户不用付软件本身费用,而是用一次付一次租用费,不用不付费。这样的好处是节省了用户一次性产品购买费,而转变成按需使用付费,和用电用水的流量付费一样。另外,客户不用为产品升级付费,这也减轻了产品快速更新换代对客户形成的成本压力。

随着时间的推移,服务市场上的竞争对手也越来越多,原来的“蓝海”被血流染成了“红海”,想活得更轻松只有去开辟新的“蓝海”,IBM这头大象于是继续前进,发现了“按需解决方案”的蓝海,率先进入。在这块“蓝海”中,服务提供者不简单地提供现成的服务,而是和客户一起研究客户面临的问题,提供相应的解决方案。至于产品,那早就是很古老的事物了,解决方案中选用产品的标准是能否解决客户问题,而非到底是谁的产品,解决方案提供者可以不提供任何产品或服务,而只需从第三方获得产品或服务,满足用户需求,为用户创造价值。

从销售产品到销售解决方案,看似小小的改变,却对方案提供者提出了很多公司组织制度上的改变。例如以前的销售人员只需要将产品介绍给客户,即将价值从产品生产部门传递给客户,做一个中间人,没有增加任何额外的价值。而销售解决方案的过程其实是和用户一起创造价值的过程,销售的过程直接就是创造价值,因此,企业组织就和以前有不小的改变。解决方案完全是知识工作及创新的结果,因此,提供解决方案的公司也必然是知识型企业,并且需要很好的创新能力,如何管理知识、激发创新也是很重要的方面。

虽然说不能对所有产业一概而论,但总得来说对IT及电信行业,这本书还是有一定指导意义的。尤其在电信行业,客户就那么几家,设备提供商的竞争日趋激烈,如何主动和客户一起发现问题、解决问题,帮客户产生额外价值,是设备提供商的一个很重要的生存技能。其实,在电信行业,类似做法已经比较普遍了,比如运营商在招标前会汇集各设备提供商的方案建议,综合分析后,得出一个实施方案,再进行招标。当然,这和按需解决之道还是有差距的,比如很多设备提供者为了中标,在投标过程中对用户需求无所不能,而在中标后又去努力遮遮掩掩,最终提交了一个和用户需求相差很大的产品,不要说创造额外价值,连正常价值也是掺了水的,这是非常不负责任的。

正是这个差距,形成了一个蓝海。就看谁的水性更好了!

2007-06-17

当一切已成为习惯

上天是会捉弄人的!

没有拥有的时候是无所谓失去的,但当拥有并一切已成为习惯后,突然又从手中夺走,这种打击是让人无法立即接受的!

因为习惯了,总会不自觉地想起或在潜意支配下而做出习惯性动作,于是发现已经失去了,继而悲伤。

为何悲伤?感情的东西是无法说清楚的,也无意于搞清楚这些,但有一点应该是无疑的:把对方看成是和自己对等的,才会真正悲伤。

什么能和人称得上对等呢?只有人,有思想、有感情的人!

当然,人的感情判断是主观的,对于什么是有思想、有感情也是主观的,甚至什么算是人也是主观的,因为所有的东西都可以被拟人化,对着怀里抱着的宠物大喊“心肝宝贝”的大有人在。

所以,人真正是为自己、为自己投入的感情而悲伤,而不论悲伤的对象是否真的有思想有感情。这是否也说明感情是单向的呢?即使有看起来是双向的爱,或许那也仅仅是因为两个单向的爱在时间上重叠罢了。

悲伤让人痛苦,或者痛苦让人悲伤,分不清因果,或者本来就互为因果,无所谓。但如何才能让人没有悲伤、没有痛苦呢?也许永远办不到,已经吞下的智慧果是无法再吐出来的,作为万物之灵,“百忧感其心,万事劳其形”,这就是拥有智慧的代价。智慧(情商)越高,痛苦越多;之前的快乐越多,之后的悲伤也越强烈。大观园中的多情公子贾宝玉一开始极尽快乐,最终却逃不脱“宴席散去”后的无限悲痛,直到避入空门。

其实何止是人呢,只要是稍微拥有点智慧的动物都摆脱不了这个“诅咒”,智慧越多,“忧”也越多。有一集《动物世界》里有个猴子妈妈的一个幼猴死去,猴子妈妈就一直带着幼猴的尸体行走,好像没有死去一样,这样过了很多天,猴子妈妈才接受现实,放下怀中幼猴已经腐烂不堪的尸体独自离去。虽然猴子妈妈没有用人类可以理解的语言表达出自己的悲伤,但相信每个人看到如此行为都能感觉到她撕心裂肺的悲痛。

人不能免于悲伤。但对于具体的某一个悲伤是会痊愈或忘记的。时间会带走一切,包括曾经的习惯。当一次次下意识想起或动作,又一次次认识到已经没有意义并悲伤后,悲伤也就随着习惯就慢慢地走了。

2007-06-11

数据揭示的软件项目管理

偶然之间,再次读到developerdotstar上转载的Robert L. Glass的文章《Success/Failure Criteria: Some Surprises》,上面罗列了最近的一些从真实软件项目中收集来的数据,总结了一些决定软件项目成功与失败的因素,其中的一些数据对习惯于传统软件工程思维或停留于纸上谈兵的人们应该具有很大刺激性,Some Surprises是肯定免不了的了。

去年差不多这时候就读过这篇文章,当时就觉得很有意思。有意思之处不在于使我surprised,恰恰相反,在于很多数据或结果佐证了我的想法。原本对自己的与众人“格格不入”的想法还心存疑虑,这下有了真实世界的数据撑腰,可以直起腰板了:)

当然,虽然我的某些想法或做法可能在Process非常严格的公司环境下显得有些格格不入,并不是因为刻意想标新立异,而是实际的情况使然,从本科做毕业设计开始参加的第一个实际软件开发项目以来,大大小小的正式项目(学校里的作业当然不算,只算最终软件要投入使用的)也有十来个了,在此过程中发现现实中的软件项目实施过程因为各种原因,往往与“传统智慧”不那么相符,或完全相反,而影响项目成功的各种因素也不是理想中的那么简单。

困惑引人思考,而思考就会有怪想法(上帝发笑),怪想法被证明为符合真理当然是令人得意的,不过得意忘形就不对了,所以还得时刻对自己的想法做检讨和检验。从最初看这篇文章到现在,一年过去了,现在就着这篇文章对软件工程作一番思考应该也是有价值的,学习老牛吃草的精神,吃的时候快速吃,吃过以后再抽空反刍。

现在反刍时间到了,以下英文为原文,中文为评:

Brisbane, Australia - At a breakfast seminar here June 6 on "Factors for IT Project Success and Failure," Prof. June Verner of NICTA (the National Information and Communication Technology institute of Australia) provided a fascinating mix of surprises and predictables related to her subject topic. The findings came from NICTA’s study of 400 projects in the U.S., Australia, and Chile, using questionnaires and interviews to discuss success and failure factors with practitioners.

What were the surprises?

  • Most projects that had no schedule were successful
    • 没有schedule的项目居然会成功?第一条就让很多人感到非常surprise了。
    • schedule的用处何在呢?是不是说在项目开始之前定一个schedule就意味着项目会按照schedule进行?当然不是了,下面就有一条说75%的项目都会估计不足,因此延期是太正常不过了,Microsoft等软件巨头就经常宣布软件延期发布。因此schedule的存在对项目实际进行只能是辅助作用,在团队之间或内部起交流沟通之用,使大家在时间上有共同概念。如果团队成员间的沟通很好,或大家能有默契,把工作分块后放入工作池,每个人都从工作池中以最优化的分配算法选取任务,以最快的速度完成任务,再次取任务,如此循环。有什么理由需要事先制度一个详细的schedule呢?
    • 详细的schedule可以项目开始时制定出来吗?当然可以,但要想准确就难了。随着项目的进行,总会有很多一开始预计不足或变化的情况出现,按照之前的schedule肯定没有办法执行。因此,schedule的制订并不是一劳永逸的,需要在项目进行中随时调整。
    • 有schedule意味着最有效率吗?当然不是。上面所设想的工作池方式才是最有效率的,当然那是理想的情况下,团队成员没有个人的私心,一心为公,实际是否行的通还没有验证过。在事先制定schedule的情况下,由于大部分人都有把工作拖到最后一分钟的弱点,往往即使在工作可以提前完成的情况下也拖到最后,使效率比理想情况下低很多,往往还造成延期。为了克服这点,往往在安排schedule的时候会刻意把任务完成时间提前,将克扣的时间放入缓冲池,以待不时之需。
    • schedule是如何制定的呢?当然理想情况下是根据项目从需求到任务分割,再根据关键路径排出项目的详细schedule,得出一个软件发布日期。实际情况呢?往往很多项目先有一个deadline,根据deadline往前推,这是项目时间紧张情况下的惯常做法,往往安排的schedule是“不可能完成任务”,造成不是延期的“延期”。
    • 如此看来,这条并不surprising。只要对团队的管理和建设做的很好,完全可以在没有schedule的情况下更有效率地工作,成功有什么惊奇的呢?!
  • Requirements are needed for project success, but not necessarily early in the project
    • 做项目当然得有需求,大家总得对做什么东西有个共同想法,这是毫无疑问的。但很多人往往又对需求太过强调了,以至于非得等所有需求确定后才能开始工作。这又走火入魔了。尤其在做项目的时候,往往客户是不可能一次性给出所有要求的,我们也没有办法做出一个一百年不变的需求设计,在项目的实施过程中会很经常地改变需求,这是正常的。因此,在项目的早期可以根据一个很粗略的需求开始工作,待项目过程中和用户的不断互动逐步明确需求。
    • 需求天天变,开发也时刻跟着变,还怎么往下做啊?需求的确可能天天变,但开发不需要时刻跟着变。可以对需求改变做管理,分批处理。
    • 如何使软件开发更适应变化?这是很大的话题。但有个总的原则:使开发团队能力提高,反应越敏捷就越能适应变化。一些技术可以帮助项目更适应变化,如code refactoring、test driven、AOP、OOP等。
  • Projects often continue successfully for some time with unclear requirements
    • 项目可以在一段时间内在不清晰的需求情况下顺利进行。但接下来呢?当然需要清晰的需求了。
    • 如何能获得清晰的需求呢?快速原型法当然可以。但是编写原型花费的努力就白费了,并且通过一次原型演示就让用户说出所有要求好像也难了点。近几年的Agile方法更进了一步,在开发过程中引进客户代表一起工作,用小的release让客户代表反馈,利用反馈收集需求信息,逐步明确需求。
    • 客户代表的想法不错,但往往是请不到客户代表的。怎么办?只能在初步了解用户需求后,按照自己的设计开始工作。完成第一版后让用户反馈。只所以说自己设计是因为中国的客户很少有自己能说出需求来的,往往都是我们按照自己的想法去设计,引导客户。这点在国外的客户可能会好一些。
  • The choice of requirements methodology does not matter; UML was "no help"
    • 这对UML的“粉丝”来说是不可接受的,软件工程可以没有人,怎么可以没有UML呢?当然不否认UML在某些情况下的价值,但对UML的顶礼膜拜大可不必。UML只是一个工具而已。requirements methodology 是需求管理的工具,UML也是,工具嘛,使着顺手又有效率就可以了,管他是什么UML呢!
  • Using a development methodology was a success factor, especially when it was "appropriate to the application"
    • 无论采用什么方法,总得有个方法,这个方法会指导项目成员做事的方法、过程,统一团队的行动及标准。其实无论成功或失败的项目,都有其开发方法,即使完全没有所谓的methodology,那也是一种methodology
    • Methodology没有好坏之分,但在具体项目中是否有效是有差别的。各种开发者论坛里经常有Methodology之争,这个说要遵守严格的瀑布模型,那个说不应该守旧,应该用Agile,其他人则有Lean、Rup等等,公说公有理,婆说婆有理,谁也不让谁,都说自己的是最好的,其他人的是错误的。其实这和瞎子摸象一个道理,大家说的都对,在自己的项目环境下,他们所坚持的methodology都是有效的。
    • 每个项目应该以自身的特点选择methodology,开发一个用户社区网站和开发航天飞机系统软件当然不需要用同样的methodology,好比杀鸡不用宰牛刀,宰牛当然也不能用杀鸡刀。
    • 选择methodology一定要大家公认的methodology吗?当然不需要。更有效的做法应该是在每个项目开始前和项目组成员一起根据情况自己制定一套methodology,这个methodology独一无二,也许其他人不理解不认同,但只要项目组成员一致认同就可以了。遵守自己的methodology,让别人说去吧:)
    • 法无定则,随需应变。盯住目标,关注环境变化及上下文。
  • Very few projects use risk management, and those that do rarely manage those risks
    • Risk永远都会有的。对于可预见的risk可以未雨绸缪,甚至立下制度,而对不可预测的risk也无需那么战战兢兢。如果不能提前知道山上是否有路,又必须越过这座山,而不能绕过,那么就相信“车到山前必有路”好了。
    • 可以在项目过程中把各种risk收集到一起,关注可以采取什么行动可以mitigate或者remove这些risk,追踪这些行动执行情况,及时update这些risk状态。
  • Post mortem reviews are rarely held, and when they are it is almost always on successful projects
    • “失败乃成功之母”,这句话从小至今作文中无数次提及,人人熟知。但“成功之父”在哪儿呢?应该是对失败的反思。如果不能对失败认真反思,何谈吸取教训走向成功呢。
    • 每个项目(无论成败)过后都应该举行反思大会,根据目的不同,可以分几次举行,每次相关人员都必须出席。会议上回顾本项目做过了哪些事,哪些效果好需要继续保持,哪些效果不好需要改进,哪些无须做,哪些没有做而应该做等等。每个人畅所欲言,最后总结。作为项目介绍的一个反馈环节,可以对下一个项目很有帮助,对项目组成员也是一个学习改进的机会。
    • 时间比较长的项目在项目中适当的时候也可以举行。
  • In the U.S. (but not elsewhere), developers are involved in project estimation only when there are poor requirements (Verner speculated that this is because the powers that be were looking for someone to blame!)
    • estimation一般由最了解项目的人来做,是否必须由developer来做倒是不一定。
    • 鄙视寻找替罪羊行为!

And the predictables?

  • Success comes from a culture that investigates and deals with problems
    • 每个项目都会有问题,要想成功必须解决问题。解决的必要步骤就是investigation,了解清楚后根据情况提出解决方案。
    • 问题解决文化是一种不畏惧问题、不躲避问题的文化。
  • The vision for the project (its business goals) must be shared among all project personnel, especially the project manager
    • 让团队成员都清楚项目的vision或目标,看似很明显的基本原则。
    • 实际的项目中经常是:不知道项目vision的PM有之,不知道项目vision的成员也很多,这往往给项目的进行造成很多麻烦,但实际情况就是这样的。
    • PM往往认为自己不需要懂技术,进而对于项目做什么、做成什么样也不去了解,或没有能力了解。最终往往变成schedule的recorder。
    • 很多成员认为自己只需要知道自己的那块任务就可以了,对于整个项目无须了解,也懒得花功夫。最终很多人只知道自己的任务,而不知道自己的成果对项目的作用何在,不能从全局考虑问题,埋藏很多bug而不自知。在这样的环境中,各种review机制很难执行,因为大家对其他人的工作没有足够的了解。没有vision的成员也很难获得成就感,很难打造一个强凝聚力的团队。
    • 解决这个糟糕局面只能靠一个或几个“操心”人,掌控大家的工作,粘合到一起,面面聚到。对这些“操心”人就一个字:累!
    • 解决这个问题:
      1. 成员努力了解整个项目的vision,不仅仅有这个权力,更有这个责任。
      2. 创造机会让团队参与vision的设定与维护。比如重要的会议让全体成员参与,其他会议的会议记录放在公共的地方或发邮件给全体成员。
  • Project managers should be involved in the estimation activity
    • PM往往由于认为estimate是技术人员的事,往往只拿到最终结果。
    • PM需要知道项目要做的几块事,需要了解大体情况,和相关人员一起estimate是一种必要方式。
  • Project managers should be good at customer and developer communication; they need not be good at the technology
    • 和用户沟通中的相关技术细节可以指定一个技术负责人和用户沟通,SE当然可以。 
    • 还是那句话,PM还是需要懂一点技术的,虽然不需要good at,至少要有共同语言。

There was some interesting data from the study, as well:

  • 60% of organizations have no process to measure benefits
  • 86% of projects had a business case, but 60% ignored it
    • 结合市场可能是大家都知道的,但大部分仅仅停留在口头上,没有好的措施来在行动上也保持对市场的关注。
  • 33% of projects said they had no risks, but 62% of those failed
    • 身在祸中不知祸,只缘身在项目中! 人总有一种盲目的乐观。
  • 49% or organizations have had (one or more) project failures
    •  可能有90%的组织或公司会否认这点。他们的确大部分项目都完成了,产生了软件。但这些软件是否在用户那里运行的很好,和客户预期相符或超出预期?问到这里估计就“顾左右而言它”了。当然这条的failure标准下面是有的。
  • In one-third of the projects, the project manager had no say in schedule/budget targets
  • 75% of projects were underestimated, none were overestimated
    • 同样的原因,人有盲目乐观的倾向,对困难会预计不足。同时,随着项目的进行,用户的需求会逐步细化,并且越来越多,很容易失控,一开始的估计不足也就不足为怪了。
    • 从本人的经验了来看,也有同样的问题,一般我的估计*2是比较符合实际的,所以有时候不得不在最初估计之后再乘一个系数:(
  • 5% of projects had no project manager; 16% changed project manager at least once (and that was correlated with project failure)
    • 有没有正式的PM这点不重要,关键看有没有人负起这个责任。小的项目没有必要设置一个专职的PM,可以兼任。
    • 在项目过程中换PM是比较忌讳的,尤其是PM参与项目的越深入,换PM带来的影响越大。PM往往决定了这个项目的运作方式,甚至一下methodology的选择。无论对国家还是对项目,政局不稳都不是好事。

Verner also asked developers what their criteria were for project success. They said:

  • They had a sense they had delivered a quality product
  • They had a sense of achievement
  • They had enough independence to work creatively
  • The requirements were met and the system worked as intended
    • 这些标准也挺有意思,来自于developer,而非商务部门,如果换成商务部门,肯定就不是这样的标准了,相信成功率也会提供很多,因为他们关心的是有没有赢利。而很多项目的确赢利了,但对于developer和客户来说,这样的项目还是失败的,因为这些项目或者没有给developer带来成就感和自信,或者没有给客户带来价值。

当然,上面的数据收集过程以及数据分析方法是否正确无从知晓。数字能说明很多问题,也有很多问题无须数字说明或数字说明不了。无论怎样,实践检验真理,在软件项目管理上,这点是没有错的。