程序员要面临的挑战千千万,项目进度评估是有史以来就存在而且到现在也没有完美解决的重量级问题。
项目进度这个坎儿其实又可以拆分为两个:
项目执行与评估
前一阵圈子里流行一篇文章,题目是“做一个这样的APP要多久”,类似的版本还有“做一个这样的网站要多久”、“做一个这样的APP要多少钱”、“做一个这样的网站要多少钱”……
多年的软件开发经验给我施了墨刑,在脸上刻了三个字:“程序员”,所以我走到哪里都会被识破身份。嘿嘿,都不用介绍了。这不,前一段我去洗车时,就被一个兄弟认出来是搞软件的。然后呢,他就问我,做一个点餐的APP要多少钱。我马上一脸黑线,他又说,就是那种很简单的,送外卖用的,这边点一下,那边收单。就要最简单的,他强调。
那几天西安正是持续高温,悟空都把西安错认为火焰山了。我和那个小伙子站在39度的夕阳残照下,沐着水泥地面源源不断升腾的热浪,认真的讨论“做一个这样的APP要多少钱”这个严肃的话题。从美团外卖、饿了么、百度外卖这些现成的大家伙,说到微小的微信公众号,又说到自己实现的各种问题,比如客户端的样式、后台的功能、服务器的托管……我们断断续续地聊了将近半个小时,最后互加了微信,他送了我一张5元的洗车抵用券,我告诉他最简单的外卖App也得几万块,我还告诉他其实做一个App不是最花钱的,最花钱的是营销和推广。OK,他同意这一点,也表示很难。
后来呢,没有后来了,我走了……
这是个有意思的小插曲,我今年已经遇到至少三次了。还记得的一次,是一个朋友问我开发一个电商网站要多少钱,说“不用太复杂,能买能卖跟京东的功能差不多就成,界面不用太炫”,我最后说京东做了好多年,花的钱数到手抽筋,作为一个个人电商的尝试者,再简化,也得花个十来万吧。
还有人问我开发周期的……
有时候看着发问者期盼的眼神和殷切的表情,你不告诉他一个数字就会在良心上受到煎熬。我这里有一个类比,就好像你觉得自己犯了病,莫名其妙但表现很严重整个人都不好了,于是巴巴地跑到高新医院挂了个专家号,人家告诉你你没病,你几乎不能相信,总还得再跑几家医院再找几个专家,直到有一个专家说,“哎呀你摊上大事儿了,直男癌”,你才会如释重负,说,哎呀,原来我真的有病。有时候我(程序员)就是那个必须说没病的人有病的专家,不说不行啊,你得让他心里安稳下来。
扯太原去了,先打住吧,我们扯正事儿。
其实呢,什么是正事儿,像“做这样一个APP要多久”这类问题,本质上是“根据需求评估工作量”这一经典问题的变体。而“做这样一个APP要多少钱”这种问题,如果前一个问题解决了,它就不是问题了。
作为程序员,也可能你在生活中没那么高的频次被一个行乞者拉住问你做一个乞讨O2O的APP要多少钱,但在工作过程中,你肯定经常被这种问题挑战。那么,问题来了,你都是怎么应对的?
嗯,你先想想看……我要接着往下逛。
工作量评估,到底该怎么做?以摊煎饼果子为例,一个煎饼果子,鸡蛋、火腿、辣子、葱、生菜,无论怎么配置,熟练工做一个也不超过5分钟。可软件就不一样啊,每一个产品每一个项目都是不同的,即便可以代码复用,也总是存在需要重新设计重新开发的部分,否则,这个项目就不可能单独列出来给你做!而只要是新的,哪怕一部分是新的,就一定存在你不试不知道的梗,就一定有出乎你意料的问题蹦出来,最终在这个项目上花费的工作量,就一定和你估计的不同。
在一个项目开始之前评估的工作量,一定是不准的,这是天条。那那那,为什么还要评估呢?
从需求方,从客户,从领导,从市场,从开发,从测试,从产品,从UI,从客服……从各个口的干系人来看,都需要一个时间点,所以,必须要评估出工作量,才可以给出一个时间点,然后大家才能转起来,各做各的准备,为着一个共同的目标去努力。
但是,在完成之前的工作量评估都是不靠谱的,所以,初始的工作量预估,只是为了制定一个粗略的计划,然后通过执行计划达到目标。
一个项目的工作,必然是由已知可评估部分和未知待实践部分组成的。对于已知可评估部分,过往的经验可以帮助你做出相对准备的判断,比如你要实现网站后台管理系统的管理员权限,管理员、角色、权限这种通用的做法,放在哪里都差不多,你做A站和B站,这块的工作量基本相同。而对于未知待实践部分,则次次不同。因为每一次的未知都和上一次不同(哭了,相同就不叫未知了),而未知即风险。软件项目的风险,相当大一部分就在这未知里面。未知的东西,不试不知道。评估这回事儿,却往往是拿知道的推测不知道的,还总要给自己找这个那个理由来说服自己也说服别人。其实根本就颠倒了,绝大多数时候,已知经验预测不了未知的未来,我们只能走走看看,试探着前行。
那么,工作量评估到底该怎么做?我有一些不成熟的经验,说说看。
我们的经验都是过去的,用过去的经验评估不了未知的未来。这是必须接受的现实。当我们分析一个新的项目时,一定是会从经验出发,拆分出根据经验可以把握的部分和看不透的部分。可以把握的部分,可以用已有经验类比,将功能从大拆小,考虑实现的方案,对每一个小模块都进行实现上的设计和考虑,估算一个时间。这样叠加起来就可以得出大概的工作量。
对于看不透的部分,也还是要进行估算。尽管这样的估算百分百不靠谱,从让相关干系人安心的角度讲,也还是要有一个结果。这是软件工程必须要做的工作。
通常老板或领导上给我们描述一个东西,然后就会问:“做这么样一个软件需要多长时间?”并且希望我们像士兵用“是”或“不是”回答长官提问一样,立马用洪亮的声音喊出“3天”或“20天”这样的答案。我们有时已习惯这种现实,不能立刻给出估算自己都会着急。其实,要对未知的、难以把握的部分做估算,需要花费相当的时间,一定要经过仔细推敲才可以答复相关人员。有时甚至需要先花两天做一些技术实验才成。所以,当我们心里没谱时,就先说明这一点——我不能立即给出评估结果,然后申请一些时间(可以是1天、2天、1周等)来分析,约定什么时间给结果。我相信大部分的领导都能够接受这样的方案。
一旦我们有了专门用于评估的时间,就可以多多考虑一些问题,比如看不清的部分,它的复杂度是什么样的,可能会用到什么新技术,新技术的学习成本是高是低,技术难点在哪里,有没有什么好的办法解决技术难点……考虑了这些问题,我们再去回顾以往的工程实践,有没有哪个项目哪个产品当时在做时也存在未知的部分,那时我们实际花费的工作量和预估的工作量之间的比值是多少,我们怎么做的?
总而言之,虽然未知的东西难以用既有经验准确估量,我们还是要硬着头皮去做。做的时候,一定要有一个心理预期,不但自己要有结果可能相当不准确的预期,也要告诉项目干系人,让他们接受这种预期。
如果能找到复杂度相当的历史项目,分析出它的数据,就可以对未知部分有一个相对靠谱的估算。这里说的靠谱,不是误差在3、5天内,而是指数量级上的相当,比如你估算要花2个人月,实际花了3个或4个,我认为这也是靠谱的。如果你花了20个,我觉得就不靠谱。当然人月本身也不靠谱(参看《人月神话》),不必迷信它。
有一点要提及的是,对于未知部分的评估结果,还要再预留一些余地。因为既然是未知,总会发生意想不到的状况卡停你前进的步伐,让实际花费的时间大大多于预期。当然,我讨厌那种“把明明20个人日能完成的事儿估算成200个人日,然后再预留200个人日”的做法,这是不能接受的。
由于工作量评估是基于估算者自身经验,天生就有另一个难点:不同的人会得出不同的结果,有时甚至天差地别。怎么处理这种情况?我没看到什么特别好的办法,最二的办法就是去掉最低和最高然后取均值。还有一个办法就是让经验更丰富的人来根据他的经验来做折衷。不论怎样,一个团队里的成员生产率都是参差不齐的,张三三天完成A任务,李四就可能是八天,赵六甚至可能十天,而且三个人都可能尽了全力。这就是天生的难题。而人月、人日这种估算方法,忽略了这种因人而异的生产率差异,所以有时你只能估算一个系数来处理,或者以生产率居中的那个人的估算为基础进行折衷。
项目进度评估
有了工作量,就可以做计划了。有了计划,老板们就可以放第一个心了。是吧,按计划行事,不管是A计划还是B计划,总归是有个计划了。
计划的执行会引导我们走向预期的结果。这是大部分人的想法,所以他们看到计划就会长出一口气,好像光明的结果就在前方向他们招手。
实际情况呢?往往是不尽如人意的。我们看看软件行业的各种跳票就知道了。
前面我们聊工作量评估时一再提到未知和不确定性,要谨记,我们得出的估算结果是不准确的,将来可能发生各种各样的意外。而基于这种估算结果制定的计划呢,在一些不可控因素发生时,必然需要改变,需要调整,需要重新寻找抵达目标的路径。用过导航的都有体会,你在一个高架桥或者环岛拐错了路,导航软件就会重新计算路径,告诉你怎么走另外一条路或者怎么绕回到之前设定的路径上。其实项目执行也是这个路子,只不过,我们不愿意接受这个事实而已。领导上客户上总觉得承诺的日期就一定要兑现,到时要么交代码要么交尸体。其实呢,换个角度来看,你就会发现,交付日期的变动也是可以接受的。
其实,计划是为了应对变化,计划本身也是要不断变化的。如果不允许计划发生变化,就不符这世界“唯一不变的就是变化”这种客观规律。
我们一定要有随时调整计划的心理准备,也要让项目干系人接受这种预期。不管我们的估算多么准确,都会遇到意想不到的状况,改变我们行进的轨迹。这些状况,就是项目的风险所在,项目管理的一大要素,就是要及时识别这些状况,及时调整行进路线,保障在合理的预期时间内完成目标。
经过分析我们都能用脑袋接受计划可能会变这种逻辑,但放在实际项目实践里,计划发生变化却往往是不被接受的。这一方面是公司已经协调了各种资源,甚至对外做了发布宣传,公布了日期,市场、营销等都已经投入资源运转,如果临时变更日期,不但无法向市场和用户交待,无法向各种项目干系人交待,还会造成实际的损失。这是现状,我们不得不接受。我们必须在此基础上来讨论如何保障项目进度。
其实我们在软件开发的过程中,能知道的是已经做完的事情和未完成的任务。我们每完成一个或一定量的任务,都来重新评估未完成的任务,用新的估算更新我们的计划,并且将新的计划发布给各个项目干系人。这就是动态交付日期策略。通过持续的、不断的调整评估和计划,我们会得到一个越来越靠谱的交付日期。相信日益明朗和确定的新计划会让领导上觉得曙光就在前面,会缓解他们的焦虑,即便最终交付时延期,也会有不一样的感觉——与持续的黑洞式无反馈和傻呵呵的自以为能按期交付却在最后时刻被告知要延期相比。
这就是动态交付日期策略,我们通过短周期的迭代,不断完成确定的任务以及不断评估未完成的事项来调整计划,最终获得动态却相对靠谱的项目进度评估。
不过说起来容易,实际执行却是相当的难,对开发团队是一种不小的挑战。
(本文曾发表于《程序员》2015.09.B)