临危受命 — 黎明前的黑暗

团队继续吭哧吭哧地前进,在经历过功能更新,用户体验更新以及性能更新的阶段后,剩下的Bug让我们看到了最终Release的曙光。一阵邮件和电话会议后,双方敲定了最终Release的日期。

在最终Release之前的三天,我们突然接到一个任务,要求换一些程序UI的元素。此时此刻,我相当不建议接受这个任务,特别是在最终Release的前三天。由于程序UI的界面图片实际是存储在数据库中,新UI的界面和老UI的界面尺寸大小都不一样,所以还需要调整项目的XIB文件以及相关的代码,这些改动在最终Release三天前发生是一个相当有风险的事情。

经过一番争取,产品总监依然坚持需要改动UI,而且这个比任何都要重要,因为客户需要看到新的UI设计,相对于后台客户“看不到”的功能反而变得其次。无奈团队只好接下这个新的任务。

墨菲定律,如果说你真心想避免墨菲定律发生在你的身上,那么墨菲定律就一定会发生在你的身上。

最终Release的那天早晨,团队成员在更新SVN之后发现程序不能成功编译,提示说缺少一些文件。可是前一天的下午我们的Daily build还好好的。调来SVN Check in记录一查,发现当天中国凌晨的时候有美国团队往里面Check in代码。出错的地方就是他们新Check in的代码。

团队计划好当天的下午Release,可是上午还有很多事情需要做,时间一分一秒地过去。一方面,我们紧急联系了美国的产品总监,说明了情况,要求美国的团队立即Check in缺少的文件,使我们可以编译成功;另一方面,中国团队先注释掉必要的代码让编译通过,然后继续工作。一阵折腾,美国团队最后在中国早上的11点左右才Check in那些丢失掉的文件。团队的工作才得以继续。

有一点不能忽略,就是为什么美国团队会在最终Release之前的一天Check in一些代码,并且不知会一声其他的团队,更没有通知项目经理。按理说最终一天的任何Check in都需要通知项目经理,由项目经理综合考虑各种风险才能批准Check in,否则新Check in的代码很有可能产生严重的回归Bug。

可惜理论和实际总是有一段距离,项目经理在中国团队,理论上可以对乌克兰团队和美国团队直接管理,可实际上并非完全如此。乌克兰团队没问题,问题是美国团队直接由产品总监坐镇。产品总监来自于创业公司,本来就缺少大团队合作的经验,两三个人一起做事儿还可以,人一多心里根本没有任何流程的概念。所以很多时候,产品总监会饶过项目经理直接和美国团队说需求,然后美国团队的高级工程师们一起就干了并Check in代码。所以至此,可能中国团队和乌克兰团队都不知道这回事儿,只有当工程师更新代码的时候,才发现Check in记录,于是再反馈到项目经理这里来,项目经理再去调查Check in代码到底改变了哪些功能。美国团队高效率的背后,留给的是跨团队合作的隐患。

早上11点,经过我们的努力美国团队最终Check in那些丢失掉的文件。团队重新打好Build,QA立即去测试新Build后果然发现各种Regression bug。这些Regression bug都似曾相识,以前团队修复过,但是都有复活。很多Regression bug都会直接导致程序崩溃。于是,在这个最终Release Day的时候,程序的表现还不如前几天的了。

之前预测到的各种风险在这一天都直接变成问题,临时改变UI设计样式,前一天不经过任何确认就Check in一些新功能,这些都造成了现有程序的大量Regression bug。同时,在修复这些Regression bug之后,可能会有新的Regression bug的发生。噩梦,总是接着一个噩梦。

接近晚饭时间,大家精神高度紧张一天,我决定还是让大家稍微喘点气去吃个饭。我自己没吃饭,回家冲了个凉,以让自己疲惫的头脑更清醒点,疲惫的身体得到一些放松。躺在阳台的躺椅上,我看着夕阳,心想这段日子终将结束,最后一天还是把团队搞得灰头土脸狼狈不堪,真不知道这是不是最后一天……

闭目养神了几分钟,跳起来,穿上衣服,去了公司。

来到公司后,发现大家都站着办公区停止了工作,似乎在等着我回来。看见我来了,立马跑过来说UI的改动需要回滚,我说怎么了,他们说Bug太多了。我知道,大家在等着我的决定。现在要么回滚所有的UI改动,这几天白忙活,而且美国特别要求的任务没完成,换来的是现在的Release安全了(可能安全了,可能不会);要么坚持继续下去,修复完所有的Bug,然后交付,换来的是极大的风险导致不能交付。

在做决定之前,我还是想先看看现场到底发生了什么,而且在这危急时刻PM需要自己来判断而不是完全根据别人提供的信息来判断。我要求QA给我展示她们发现的一个个Bug,然后我和Dev一起判断这可能是什么原因引起的Bug。当我看完了所有的情况紧急的重大Bug后,我发现真正由替换UI引出的Bug不过一二,其他的Bug来自于非UI替换的组件。于是我做出决定,不要回滚UI改动,继续推进修复完所有Bug完成交付。

回过头来想,为什么当时大家都站在办公区停止了工作,为什么会认为UI的改动需要回滚。我想那个时候,大家跟我在自家阳台躺椅上的心境应该差不多。坚持了大概一个多月没休息,最后一天出了这么多乱子,使得大家士气很低落,于是开始怀疑自己的努力,并且想放弃自己的努力。我想,这个时候就需要PM站出来,勇敢地做出决定,并鼓舞大家的士气。

我召集所有人开会,告诉了大家我们看完了所有的Bug后,真正由替换UI引出的Bug只有2个,说明我们的替换UI的改动还是非常成功的。剩下的所谓的很多Bug,加起来也不过7到8个。很多都是以前修复过的问题不知道什么原因又重新打开了,换句话说,大家都肯定熟悉那块地方的代码,修复起来也不会太难。现场有这么多人,大家加把油,今天最后一天,做完就成功。

其实数据都摆在那里,需要一个人High level的说出来分析给大家听,大家才放心。我并没有“望梅止渴”,我只是在陈述事实。

最后晚上还算顺利,临近12点,基本开始进入交付流程了。我拿出钱,让大家去公司对面买些烧烤和啤酒,大家一起庆祝最后的交付。尽管最后已经快到2点了。

有人说,等下4点有球赛,干脆等下一起喝啤酒看球赛算了。呵呵,一群可爱的人。

最终还是没看球赛,大家各自在香甜的睡梦中,迎接了黎明的到来。

临危受命 — 功能,用户体验和性能

 

自从项目组成功的交付了前几个软件包之后,压力减少了许多。现在的软件看起来还是那么回事儿,而不是像几个星期前那样一堆跑不起来的玩意儿。可是我们的活儿还没完,接下来的几周主要是针对目前的版本做维护更新。

现在回顾起来,这几周的维护更新基本上是被美国产品总监驱动着前进。先后经历了功能完善,用户体验完善和性能完善阶段。

首先说功能完善阶段。一个软件最基本的功能都没能实现,当然不用谈其他的。整个软件团队分为三地,美国,乌克兰和中国。软件有四个组成部分:Server, HH, DB, Web。软件开发阶段的前期貌似没有非常明确的说明团队是按照横向分工还是纵向分工。所谓横向,就是四个组成部分一个团队专门负责一块或两块,不会有一个组成部分同时由两个团队进行维护;所谓纵向,是按照需求功能分,一个软件需求可能四个组成部分都会涉及,那么同一个团队为了完成一个需求会四个组成部分都用到。

现实的情况是乌克兰团队负责HH和Web;中国团队在开发阶段主要负责Server和Web;美国团队负责DB,HH以及Server。所以应该算是偏纵向分工。在开发阶段,中国团队的作用基本上是处理分配过来的任务或者需求,没有一个整块。其他两边的团队也各自为政。最后导致的结果是,貌似每个需求点都有开发,但是又都连接不起来。所以我们的任务是在别人70%的代码上做补充修改。经过分析,其实所谓的需求都不太难实现,只是横跨的组件非常多,而团队之间又缺乏沟通,所以导致很多事情做了但是没做完,半吊子。

好吧,开始工作了。首先,该项目并没有正规完善的功能需求说明书,于是先让QA根据界面设计测试用例,然后让QA进行测试 — 结果当然是Bug一大堆了。于是,在没有功能需求说明书的情况下,开发们可以根据Bug来有目标地进行工作了。(想想极限情况是什么,就是一行代码没写,于是功能说明书就完全以Bug列表的格式展现了)。

此刻最大的变化是,中国团队开始介入HH的开发,于是Server, HH和Web中国团队就都有横跨,这样可以极好地解决跨团队沟通效率低下的问题。这时候有人提议,干脆以后就把所有的模块都接过来得了,免得出现其他团队不好合作的情况。这个建议立即被我们的软件开发总监驳回了,因为从商业上和实际上很难一个团队把所有的模块都接了,另外奢求这样的工作模式实际上是管理低能的表现。

吭哧吭哧地前进,随着主要的功能性Bug被修复,软件也可以慢慢跑起来了。美国产品总监在点击某些按钮时发现结果也可以正常显示出来后,就开始注意用户体验了。

以前三地的团队都是做企业级应用的,和互联网应用不一样,通常企业级应用对用户体验的要求比较少,所以印象中企业级软件的界面都比较丑陋。可是我们做的是iOS,iOS有些基本的用户体验规范,这些用户体验规范由苹果官方出品为的是所有的iOS应用有着相同或相近的体验。在我看来,有些iOS基本的用户体验已经不是传统上的用户体验,而是默认的必须要的功能。

举个例子,某条规范说用户在触发一个事件后,如果结果不能立即出来,应该有某种提示进度的方式。即如果你点击一个按钮,在去下一个屏幕的之前需要等待很长的时间,那么需要设计一个提示框或者转圈指示器显示在屏幕中央,如果没有,那么用户体验是相当恶劣的。

再举些例子,有的时候一些iOS应用就是把用户体验做到极致,比如打开App store,里面介绍应用的页面通常会列出好多应用,而这里的显示逻辑是先加载基本的框架,然后再加载所有应用的文字,最后再加载所有应用的图片。想想看,如果给了一般团队做,估计是对一个应用进行框架,图片和文字的加载,就算多线程也会出现在界面上时快时慢的现象。

吭哧吭哧地前进,对用户体验类型的Bug做了一轮整体的修改,于是软件又看起来更像那么一回事儿了。美国产品总监开始考虑性能的问题。

在我们的测试过程中,发现有些环节的数据加载特别慢,于是调查代码实现,发现加载慢是因为前期设计有问题,设计地非常草率。现在看来哪怕一点点的思考力,就足以解决这些性能问题。换句话说,解决性能问题的根本不在维护阶段,而在设计阶段。设计阶段越草率,后面的维护工作就越麻烦。

所以,在设计阶段就需要开始考虑上线后预告有哪些数据,对每个功能点的开发都需要有足够的思考 — 如果这里有很大的数据量怎么办。进行过这样的思考和不进行思考就显得不一样,甚至代码的实现角度都会不一样。上面的用户体验的例子也可以放到这里作为性能的优化方案来讨论。先UI框架,然后所有的文字,然后所有的图片,就是为了对付图片下载的性能问题,所以把图片的下载放到最后,而把主要的页面框架文字放在前面。

好了,功能也完善了,用户体验也OK了,最大的性能问题也解决了,准备终极Release了吧。

临危受命 — 一次完满的Release

Release,即软件发布,俗称发包。在整个软件开发生命周期中,Release算是最扣人心弦的环节,因为这是整个周期的最后一个环节,而又往往是麻烦最多的环节。

之所以说Release扣人心弦,是因为大多数情况下,项目总是在资源有限的情况下进行的。要么是时间资源有限,要么是人力资源有限,最后为了能够保质保量通常不是以非常”优雅“的姿态,甚至以”狼狈“的姿态完成,最后惊心动魄地“刚刚好”完成任务。

另外一个原因导致Release总是让人提心吊胆是因为这个毕竟是软件开发周期最接近Deadline的环节,所以一旦项目出了一些错几乎没有什么多的机会加以改正,直接会导致项目延期。

从Release的作业内容来说,发布团队需要将一个软件的各个组件衔接起来,再加上项目上的文档,说明,七七八八的千头万绪,一点点的意外和疏漏少则提高所有人的荷尔蒙,多则需要重新来过,所以不得不让人绷紧了弦。

所以一次正常的,在各种资源有限的情况下完成Release,需要一个PM甚至一个团队倾尽全力完成。团队越大,合作起来越复杂,PM在里面倾注的心力越多。

幸运的是,我们依然可以从那些成功的Release中总结一些经验,并形成一个框架模型。不同的项目参考这个模型或许可以让自己相对“优雅”的完成项目的Release.

通常来说,Release环节的进入标志为Code Freeze,即代码冻结 — 所有人不得做代码Check in. 通常这个代码冻结的时间点由PM给出,而定这个时间的标准则是根据项目规模,复杂度决定的。比如,临危受命的这个项目,在交付日当天的下午1PM开始进入代码冻结。下午1PM是怎么定出来的呢?是有经验的项目管理人员,根据这个项目的规模大小,根据一次冒烟测试的时间做出的估算。有的大型的项目估计会在交付日提前两天开始进入代码冻结,因为需要留足够的时间进行交付测试。

交付前为什么要做代码冻结?每次代码Check in,都会改变整个代码库编译的版本。Check in要么是提交一个新功能,要么是修复缺陷,要么是改进代码,任何的代码的改动除了带来本身的价值外,都会引入回归(Regression)的风险。简单地说,任何代码改动可能会带来新的问题,轻则出现新的缺陷,重则整个包打不起来。如果现在已经进入交付测试阶段,不做代码冻结,开发者在测试阶段做的任何代码改动,都会让现在的交付测试报废 — 因为你无法确认这次代码Check in会不会引入以及引入什么样程度的缺陷,所以交付测试需要在每次改动后再重新来过一遍。为了让整个交付程序更加的顺畅而不是一遍遍重新来过,需要做代码冻结。

代码冻结后干什么?当然是打Build,就是把这套软件的各个组件进行编译然后连接成的软件包。这些软件包叫Release Candidates,即“交付候选”,这些候选包会做一轮Release testing确保没有大的问题才能真正Release出去。

Release testing的级别通常由项目经理和QA Leader做出决定,是做一轮完整测试,还是做一轮冒烟测试,亦或是最简单的Bug verification和小范围的回归测试。做此类决定的标准一般有三:1. 交付包的内容。如果这个交付包里有大量的改动,那么还是做一次完整测试好,否则一般改动就做冒烟测试。2. 本次交付的重要程度。非常重要的交付比如要直接上线那么还是需要做一轮完整测试的好。3. 留给做测试的时间。这是一个非常现实的问题,如果交付前期花费了大量时间,最后留给交付的时间不多,那么项目组不得不接受一个现实是没有足够的时间测试而只能妥协做低一级别的测试,从而背上一些交付失败风险,或者项目经理出面协商交付延后,当然这个也会对团队的信誉产生负面影响。

刚刚做完了一次Release testing,QA组发布了一个Bug列表。这些Bug需要在这个版本里面修复掉吗?如果选择修复Bug,那么不可避免地需要一个新的Release Candidates,而且附带有一轮新的Release testing,而且还会有新的Regression bug产生。在争分夺秒的交付时间线里面,每一次代码重新改动都需要仔细考量,因为上面的Release流程耗时很长,但又是必须的。

基于这些想法,所以一次Release testing,通常只会修复P1到P3的Bug,P4和P5的Bug就不用看了。当然项目经理可以对临场的情况做出决策,因为坏情况在于有时候P1到P3的某些诡异Bug修复时间会过长而影响Release,所以最后可能会缩小修复的范围到P1到P2,剩下的作为已知Bug列表报给客户并做出计划什么时候修复。当然,如果P1到P3的Bug太多而导致这次交付基本不可能,那么团队在交付期已无力回天,别怪交付了,好好复盘一下整个的开发过程吧。

最后整个的一轮轮做完,最后一个Release candidates将会作为交付的正式版本发给客户。用7z或者zip等压缩软件,将你的软件精致地打包好,传上FTP或者附件吧。最后一个环节也不要出错,确保你的软件包不会因为网络原因而上传不完整,否则刚才的一切努力在客户那边都白费。

最后的最后便是Release Email, 一般来说一封Release Email会有一个稍微正式的格式,让阅读者体验到“看,这个Release是我们静心准备的”。内容上会包括这次交付有哪些组件,交付版本号,代码SVN存放处,Build的存放处,还会包括一个Release Note的附件。Release Note里面会写这次交付具体有哪些更新;会有已知Bug列表,告诉接包方这个包里面还有哪些Bug,这些Bug计划在什么时候修复;当然还会有下一阶段的计划等等。

经历过上述这么多步骤后,终于可以说这次Release成功,大家可以回去好好睡一觉了。

临危受命 — 一切用数字说话

 

一切用数字说话

 

依稀记得在项目开始的时候,当时项目的USP将我的手机号发送邮件到一大票大佬们,我就觉得情况不妙,估计我的所有时间都真的和这个项目绑定上了。

之后,不论是内线电话,还是Skype,还是手机,还是MSN,还是邮件,我会经常被各种大佬找到,我想这便是PM经常的状态了。重复说一遍PM项目经理的职责,对项目的所有负责。所以即便你的项目组里面有成员若干,项目组外围的各种角色,不论是高管,还是客户,还是其他角色,如果有问题都会找PM项目经理 — 他们不会主动识别出来是技术问题所以应该找某某工程师。

于是,我就经常在上述渠道听到那些公司高管和总监的声音,不论是在平常工作日,还是在周末。

他们经常第一句话是:现在项目状况怎么样?

然后我会答:现在情况还不错,基本的功能我看过了都可以前后台连起来了,大家也很努力地在修复缺陷……

然后我就会被打断,高管他们会换种说法问:现在过的需求有多少个?还有多少Open的bug?上次交付邮件里面提到的已知项目缺陷的18个Bug现在还剩多少个?……

我管这样的电话叫夺命追魂Call。因为他可以发生在任何地方任何时间,可以在周末你抽出闲暇约会的时候,可以在平常吃晚饭正香的时候。让我印象最深的一次是当时我和同事在公司对门小街上的一个台湾卤肉店里面吃卤肉饭,说是台湾,其实也就是本地周边的人小本经营的店子,小店面,环境不太好。我和同事边吃边聊,突然手机响了,拿起一看,未显号码。一接听,”Hello, Kenny, how many bugs now?”……当时我听出来了是我们的副总裁,美国高级总监,USP团队老大打过来的。我连忙放下碗筷,”Sorry, please give me seconds.”走出小店。恰巧当时老板和老板娘在吵架,用本地方言很大声地互相对骂,我从他们的战火中穿过,一头钻进街对面的黑暗,用英文和他聊起来了。各种状态更新,打完电话一看,接近14分钟。

后来我悟道了,高管他们对这个项目的状况很担忧,估计在美国那边应该很多人找了他们不少的麻烦。他们会抽空大老远跑到武汉来坐镇项目组,但毕竟是少数时候,于是经常问项目状况是让他们安心。

软件开发总监也是说,其实有些时候项目经理就是个算账的,估计进度,算现在的需求数,算现在的缺陷数,配比人员后算现在的缺陷什么时候可以改完等等等等。我被总监批评,不太理性地去描述问题。就像上面那段对话,我讲的话里面有内容吗?有,就是现在项目状态总的来说是积极的;也算没有,积极到什么程度?离结束还有多久?再加上不同的人对待感性描述的理解不同,于是都要求将一切用数字描述,只有数字才能让世界各地的人知道现在具体发生了什么。

了解到这一点之后,我开始有意识地要求自己,一旦自己空下来,就去统计现在的项目状态,简单地说就是统计各种数字。比如现在的过的需求数,过的需求数除以总需求数的百分比,现在的缺陷数,有多少个P1的缺陷,有多少个P2的缺陷,这么些缺陷都什么时候才能改完等等。然后将其记下来并随身带,这样就不再惧怕任何夺命追魂Call。同时,如果预测到每天某个时间高管总会电话来,干脆就提前给他发个邮件并简明扼要的说明项目状态,这样夺命追魂Call也少了很多。

更值得一提的是,当你很清楚地并迅速地将理性的数字表达出来,这个时候感性就不知不觉地释放出来给对方信心了。