临危受命 — Bug大决战

Bug大决战

在我接手项目之后,第一个交付发生在三个工作日后。本来项目的初始情况都已经在谷底了,所以我们需要在短时间内,迅速恢复产品总监,公司高管以及整个项目团队的信心。于是这三个工作日的交付,是那个产品总监的期望。

时间当然不够。做了两三个月的项目,虽然每个模块都完成了70% – 80%,最后没集成起来。这些需要在3天的时间的内完成部分模块前台后台的集成风险太大,于是在如此被动局面上自然算上周末,5天的时间加上这么多人,应该可以全力拼一把。这一战为信心而战。

到了交付日的头天晚上,情况是基本集成完毕,但是有一票Bug。很多Bug留在这次交付里是致命的,所以必须修复掉。项目团队不敢怠慢,于是拼命干到夜晚9点多,依然还有一票Bug。此时,软件开发总监A走进会议室……

面对在会议室里面项目组的所有人,以及投影仪上的Bug列表,总监已经意识到了今天大家要奋力拼一次了。他首先对大家说:为了这次交付大家都非常辛苦,明天交付顺利后,给大家好好调个休,放个假。这么一说,一来是慰籍前线的战士,承诺胜利后会给大家休息;二来是坚定地表明今天大家要熬夜奋战了,成败在此一举。

然后所有Dev被请出会议室,只留下QA们和项目经理。

讨论的第一个问题是为什么有大概2/3的Bug全是P1的Bug?如果全是P1,那还要Bug优先级干嘛呢。细看每一个Bug,有的是说程序会在什么情况Crash,有的是说UI有个明显的问题等等。Bug优先级是QA来订,基本上QA认为P1的Bug是不能容忍的,所以从程序Crash到明显前台UI的问题都报P1。

Bug优先级,是指为这次交付而言,哪些Bug优先级高需要优先修复,哪些低。QA的心情可以理解,每个Bug都”看起来“那么重要,但是假如只有两个Bug,一个是Crash,一个是明显UI问题,而给予的时间只能修复一个,你会修复哪个?

如果我们重新回到Bug优先级的定义,并且重新解释其涵义,可能定Bug优先级就会稍显简单。
P1 — 程序崩溃,数据丢失;
P2 — 主要功能问题,用户没有其他途径达成功能目标;
P3 — 主要功能问题,但用户还有其他途径达成功能目标;
P4 — 次要功能问题;
P5 — 界面显示,镀金功能等。

有了这些定义,就可以让QA的自主定性Bug优先级在一定的框架下进行,而不是完全凭主观“紧急程度”“焦虑程度”来定义Bug优先级了。

其实用来描述Bug除了优先级(Priority)还有严重性(Severity)。这个在很多教科书上有很清晰的定义,但是在实际应用中,两个维度的描述通常会让人感到迷惑。比如一个优先级很高但是严重程度不高的Bug,和一个严重程度很高但是优先级别不高的Bug到底应该先修复哪个?有人说,当然是优先级很高啊。问题是,这个是已经给好的前置条件,而在现实中,定义一个“严重程度很高”的Bug为“优先级别很低”本身就会让人捉拿不定。于是,为了让实际使用效果简单,不妨就保持一个维度。

随后经过这么一轮调整,所有Bug的优先级被重新定义,P1到P5有着合理的比例。这样来讲,即使在最危急的时刻,开发团队也会有个明确的目标,而不是说一股脑地视任何Bug为高优先级。全部高优先级,就是没有优先级。

随后QA被请出房间,Dev们被叫入房间,和项目经理一起过Bug列表。

刚才的Bug列表已经被标明了优先级,通常情况下,P1到P3的Bug是我们为交付修复的目标。为何?通常情况下时间和人手资源都是紧缺的,如果所有的Bug都可以被修复,那就不要分优先级好了。正是因为不是所有Bug都会被修复,所有才分出优先级。于是项目经理在定义目标的时候,就是只分P1到P3的Bug。P4和P5的Bug就算修复再多,也不如留一个P1到P3的Bug对这次交付的危害打大。

Bug该谁修,一般谁写的模块的Bug就该谁修复。但是如果遇到一个模块的Bug特别多,那么可以分配有Bug较少的Dev去参与修复Bug较多的模块,不过这样的情况就是要确保预防Regression Bug的产生,加强修复同一模块的Dev之间的沟通。

Bug什么时候修完,这是一个很让人难受的问题,特别是在最危急的时刻。不过再让人难受,项目经理一定还是要问。在Bug列表里面有一列叫Due date,填好这个值之后,项目经理就会清楚地知道什么时候可以安排出一个内部测试版本,然后QA可以去检验Bug是否被修复。

这里有一个问题需要注意,就是在决定这个Bug由谁修复,然后决定什么时候修完的时候,项目经理容易说“这个今天修完没问题吧”“这个两个小时修完没问题吧”。项目经理当然可以对Bug的修复状况心中有一个估计,但是这个估计最好还是由Dev本人说出口。因为他不是你,你也不是他。Dev的职责就是修复Bug,所用的时间是他认为他需要的,可能会和项目经理有所出入,但通常情况下项目经理应该给Dev合理的尊重。除非Dev的估计和项目经理的估计差别太大,那么项目经理就需要深入细节和Dev进行讨论了。不过有一点没变,Dev在得到尊重的同时,也需要对自己的承诺负责。

同理,一个Bug在QA Verify的时候,是不是Pass也是由QA说了算,项目经理虽然心中放着交付,但是还是需要对QA这个职位表示尊重,即Bug该不该Pass由QA说了算。

临危受命 — 项目到底要做什么

项目到底做什么

我们经常在口中念叨软件项目,而一个项目到底是什么呢?从物理世界看,就是一群人,一堆代码,一堆文档。

一群人,这个项目中参与的人群都在前传里面介绍过了;一堆代码,放在美国的SVN服务器里面,中国人,美国人和乌克兰人都有读取和写入的访问权限。代码有四个模块:Web, DB, Server, HH;一堆文档,这个项目居然是没有FRD的,大家靠意念理解需求,靠翻看代码回顾需求。坦白讲,在项目开始3个月后还是这样的状况是谁都会吃惊。然后有一个已经被现实冲得支离破碎的Timeline。

在前传最后的电话会议中,经过协商,产品总监要求在短短的3天内,完成他钦点的几个功能模块。这短短3天内夹杂着一个周末,傻子都知道周末一定泡汤,现在如此的境地周末放假确实让所有人都不好接受。一个初步估计,由于这一些功能模块其实代码都写了个70% — 80%,所以不是完全实现新功能,在一个短周期内长时间工作拼一把是可以把这些功能“连起来”的 — 虽然达不到真正的交付标准,但是起码会给这样的寒冷的局面带来一丝暖意和信心。

如果说做一个软件之前需求先行,那么FRD应该是在软件开发之前就完成的。项目历史原因没有FRD已经是既成事实,而短短时间内美国团队也不可能写出一个像样的FRD — 项目开始3个月后都没有FRD难道还期望3天内有FRD?这便是残酷的现实。还好,团队之前工作的3个月也不是白干的,虽然没有FRD,但是需求基本掌握80%以上没问题,剩下的边角问题就靠沟通了。

我开始做的第一件事情就是制作一个新的Timeline,时间线。制定时间线其实是一种Schedule规划的技能,即针对于每个人,写出在什么时间段需要完成什么样的工作。

这里第一个要求是从当下到milestone里程碑的所有需要完成的事情需要列出来,不遗漏,不重复;第二个要求是需要合理规划工作之间的依赖关系,比如:一个开发者首先要开发完模块A,然后模块A才能被QA给测试,那么在模块A开发完之前这个QA应该安排什么任务呢?可以是测试已经完成的模块B或者写文档;但是绝对不能把“测试模块A”放在“开发模块A”的前面,就算那个QA在前面实在没有事情做也不行,这就是说“测试模块A”依赖“开发模块A”的任务;第三个要求是尽量规划每个人保证没有空隙时间,实际上不只有一个测试,也不只有一个开发,如何能让每个人都满负荷状态工作而没有人闲着便是这个要求的实质。

根据上面所说的内容,如果我们用Excel,可以很简单地规划出一些关键的列。ID列标明每个任务的编号方便引用;Task列标明具体的任务内容,注意任务的内容必须指代“完成什么” — 即结果,而不是说“去做什么” — 即过程。任务内容在表述上只求结果,不求过程;%列,完成百分比;Resource列写明这个任务是谁做;Duration列写明这个任务需要多少天完成 — 这样单个任务的人天就很容易看出来了;Start Date列,开始的具体日期;End Date列,结束的具体日期;Comments列,写明一些特殊的情况比如这个Task和客户的XX决定结果有依赖性等等。

就这样,一个崭新的Timeline就做好了。于是我带着这样的一个Timeline走进了晨会。在晨会上,公司的软件开发总监A导登场 — 他即将扮演这个项目的导师,也是在后面的日子里骂我最凶,教我最多,让我成长最大的人。

他看了看新的Timeline,皱起了眉头。他问,如何才能知道此时此刻项目的状况?我说Timeline可以反映啊,比如哪些任务Delay了。他说,一个任务Delay了对这个项目造成的影响多大?如何去衡量?如何就用简单的一些数字去反映项目的状况而不是一大堆诸如开发者A延迟了几个任务,开发者B延迟了几个任务 — 这些都是项目中过程的琐碎,但是不能直接反映结果。

如何让项目直接以结果的形式反映出来?答案是需求列表。一个软件项目的启动最根源的一定是需求,从需求上我们可以做设计,做开发,做测试,做文档,做交付,但是最最根本的起源点,便是需求。

需求列表,就是将这个软件项目的需求都列出来。根据颗粒度,需求列表可以有不同的效果:颗粒度越大,需求分得越抽象,便可以更概括地一览全局,把握大局观。但此法缺点是很难精确的反映实际情况;颗粒度越小,反映项目情况越准确,对项目的控制管理更细致更精确。但是要有大局观呢,需要统计一下通过的需求和作废的需求的比例。

实际操作中,以Excel为例,可以先将软件项目分好一级需求目录,一级需求目录通常是一个功能模块,或者一个屏;然后在一级需求目录下建立次级需求目录,次级需求目录可以就是一个功能模块,或者一个屏上的按钮功能,列表的排序功能等等。如果第一列是这个需求列表,那么第二列是状态栏,就是标明这条需求是Pass还是Fail,这一栏的状态只有QA才有权利填;第三列就是Bug Id列表,就是说造成这一条需求Fail的Bug Id有哪些;后面几列则分别标明这条需求负责的Dev是谁,完成百分比,什么时候做完(这一列只有Dev有权利填,PM不能主观臆断而需要尊重Dev),QA是谁,Test case写完了没,测试完成百分比,什么时候测完(这一列只有QA有权利填,PM不能主观臆断而需要尊重QA)。

这样一来,用Excel的筛选功能,就可以轻松知道,到底Pass的需求有多少个,Fail的需求有多少个,Pass需求所占整个需求列表比例是多少,这样对于每次交付目标,我们就可以轻松地知道项目的开发和测试进展了。

这个说的是在开发编码过程中的操作手法,那如果是所有需求开发完成了开始进入Bug fixing阶段,那么该如何操作呢?请看下回分解。

临危受命 — 前传

 

临危受命 -- 前传

 

自从团队所服务的公司在去年底被一家大型的支付巨头企业收购之后,美国团队和收购他们的母公司之间进入了一段寂静的磨合期,之后2012年开年后大概2,3月份的样子,美国团队开始研发一个基于移动的零售行业的CRM解决方案。于是随后中国的团队也新成立了一个小组配合美国团队一起工作。

这个CRM行业解决方案的负责人是美国团队里面的一个产品总监H,印度籍美国人,生性暴躁,但是还挺富有责任心。他在平常的时候表现出来的是对团队产出质量的高要求,而在暴躁焦虑状态下,会以把小事放大的作风拉一票人跟着他一起分享他的暴躁焦虑。

产品总监H的手下是两个得力高级工程师,一个是负责写后台Server的V,还有一个是负责写前台Client的A。V和A的工作一般都会极大的得到产品总监H的支持,应该算是他的亲信 — 为什么这么说,是因为从名字上看V和A应该也是印度籍美国人 — 当然这是玩笑话。这两个工程师所负责的的确是各自组件的核心代码,而且又和产品总监H坐在同一个办公室 — 要知道,在一个全球性型的团队中,即使是技术团队,我们依然需要考虑人的因素。

产品总监H还有两个手下,可以算是普通工程师,不过他们俩在乌克兰。一个是负责Web开发的L,另一个是负责前台Client开发的R。他们所充当的角色不管是从负责的具体内容还是地理位置来看,都应该算普通角色。

最后就是中国的团队,这边有一个兼职的PM,两个既可以开发Web又可以开发Client的开发者,还有一个QA。为了区分定义,我们姑且叫这个中国团队为“产品组”。兼职的PM主要负责项目组那边的日常工作,在产品组这边的角色定义为“沟通”以及“保证产品组的日常运作”。两个开发者对日常的Web开发熟悉一些,对新上手的iOS Client开发稍微弱一些。对于QA,没错,这个产品总监貌似不太重视QA的角色,又或者说他非常重视QA的角色以至于他自己承担起QA的角色或者让他的两个开发手下承担起部分的QA角色。

再后来,中国的产品组这边因为项目需要有所增援,又增加了一个小组,也是有两个既可以开发Web又可以开发Client的开发者,还有一个QA。

好了,上述便是这个故事的基本主角。故事从2012年2月开始。

开年后,产品总监H宣布开始研发CRM行业解决方案。那个负责写后台Server的V和负责写前台Client框架的A早早地将框架完成,并且在写功能模块的代码。V同时还负责DB的设计和开发。

乌克兰方面负责Web开发的L一个人聚焦于Web的开发工作,他的工作会受到V的指导以及Review。R则和写前台Client的A一起完成功能模块的代码,但是实际上R主要来开发,而高级工程师A,则不知道被产品总监H派哪里去东一天西一天。

中国团队则负责修复一些在Web,Client, Server端的Bug以及相关功能模块的开发,同时中国团队这边的QA,尽管很少,却起了极大的作用因为几乎所有的Bug都来自中国的QA。中国的团队开发们没有DB和Web这边的Check in权限,然后只有Client 和 Server这端的Check in权限。在中国团队开始运作之前,按照惯例我们依然做了个Timeline申明交付日期。

日子就这样一天天的过着。中国的产品团队每天或者几天会收到一些来自美国团队的邮件,说把这个给干了,然后把那个也给干了。然后中国团队就给干了,然后交付更新过去。偶尔会开个电话会议,讨论需求。因为当时整个产品是边做边在构想 ,特别是一些功能模块对于产品总监H本身也没考虑青春,所以有些东西都没想清楚怎么设计之后在电话会议上也就不了了之了。

另外,中国团队以前也几乎没有经历过国际团队合作,做一个项目需要三个地方的人同时合作,怎么能保证这些不同国籍,不同文化的人对需求和问题的理解一致,沟通充分,代码级别合作没问题是当时的团队所面临的难题。所以由这些缘由构成的问题似乎成为了平静的项目周期中的调味料。

从中国团队来看,我们很好地完成了客户,即那个产品总监分配下来的任务,而且同时也会及时地把问题上报上去,只是总是奇怪没有什么反馈。中国团队认为美国团队知晓这些问题,并且知晓因为这些问题带来对交付日期的影响,所以只从中国团队的视野看来,我们做得很OK。一切都没事。

事情的转折发生在临近中国交付日期的头3天,而且形势急转直下。

产品总监开了个电话会议想跑一跑我们在这几个月做的成果,结果发现很多功能虽然代码写了,但是都连不起来。于是大怒,质问中国团队究竟干了什么,矛头都指向了那个中国团队的PM。PM一肚子委屈,我们在很早之前也提交了问题为什么你们没有回复呢。产品总监反过来质问为什么PM没有Escalate(指将问题升级上报,直到追踪到解决人为止)。于是在反复地交流中,我们终于明白了产品总监在项目伊始时的想法:
1. PM,Project Manager,当然对项目的交付成败负责。
2. PM如果只有一个,那么他不应该只是中国团队的PM,而是整个国际化团队的PM。PM需要在国际化团队中整合资源,协调沟通从而推动项目。
3. 遇到问题而阻碍项目进度时,因为第一条,PM应该尽所能找到问题解决人,推动项目前进。

而在项目开始之时,产品总监的想法是否如此已经不得而知。不过商业只相信事实,项目在交付的前3天居然没有一个功能能够连起来,需要有人对此负责。

此时,中国团队的”Account Manager”USP,况且就叫他S吧,跳出来说你也不能全怪我们的PM,因为这么一个国际化项目组,而且你又有如此宏伟的计划,为什么不需要一个全职的产品组PM而是找一个项目组的PM来兼职,项目组PM精力上当然分配不过来了。吵架的事情,就是坚持与妥协,最后达成共识。

随后,我们开了一个令人难忘的电话会议。当时,我,项目组PM,产品组团队,美国产品总监P,客户经理S都在电话上。产品总监豪不客气地说着一些让人情感上难以接受但是却不得不让人面对现实承认错误的话语,简直就是指着鼻子骂,场面令人非常难堪……这个电话会议之后,也宣布了我的走马上任 — 在这水深火热的时候,从项目组调过来出任产品组PM,临危受命拯救这个CRM项目,同时也拉开了产品组团队接下来5周无周末工作的序幕……

临危受命 — 开篇

 

 

临危受命

 

 

这是一个最坏的项目,也是一个最好的项目。 — 菠萝头

从这个项目结束到现在已经持续很长时间了。在这新年之际,还是想将这发生的一切记录下来,正视过去,才能拥有更好的未来。

这大概是我从职业生涯开始至今最失败的成功项目吧。失败,来自于过程;成功,来自于结果。幸运的是,我不是从最开始进入这个项目的,而是从这个项目最失败的谷底进入的,临危受命,受到各种炮弹的轰炸以及受到各级领导的支持帮助,最终扭转局势并将项目拖上正轨。

这个项目,在我看来,应该算是最近两年来我所经历的最惨烈的项目,没有之一。事实再一次证明了经验 — 做最惨烈的项目所获得的经验值是最多的。在这个项目里,各种项目管理的招数,临场应变的话术,左右逢源的协调,虚实之间的沟通,层出不穷,实在精彩绝伦。以至于时隔些许日子,我依然对里面的种种扣人心弦的场景记忆犹新。为了不让这段记忆随着时间的流逝而被灰尘掩盖,只好写出这一系列博客《临危受命》,一来总结经验,二来思考未来。

如果说每到年末公司都要求写年终总结,那么这一系列博客应该足矣。

2013年新年目标

工作

1. VFKit。
2. Testing automation framework.
3. Business Research Institute — mPOS。
4. 去美国公差一次。
5. 更新一次简历。

培训
1. iOS 用户体验培训。
2. Email– 中级篇 培训。

充电:
1. 读书50本。
2. 写博客每个月一篇。
3. PMP课程学习。

生活
1. 掌握通过各种技能买到物美价廉的东西。
2. 认识更多的武汉街道,景点。
3. 生活要由情趣,不再做生活白痴。参考OFF学。
4. 有效减少微博时间。
5. 取出一次公积金。
6. 彻底处理掉拇指的伤口。
7. 可以随时随地地翻墙。
8. 将网站迁移到墙外,wordpress, 换首页。
9. 将存款进行理财。

爱情
1. 认真去爱一个人,做一个真正的男人,结果顺其自然。
2. 和爱的人共同成长。