14.6开发阶段的日常管理
14.6.1闭门造车(leave me alone)
荔荔:我今天真失败!在办公室里坐了10个小时,但是真正能花在开发工作上的可能只有3个小时,然后我的工作进展大概只有两个小时!
阿超:那你的时间都花到哪里去了?
荔荔:就是我们以前说的“我没看见你在写软件,你到底在忙什么”上面列出来的破事儿。每一件随机事情看起来都是挺重要的,我就放下手里的开发工作。但是好不容易做完了,刚想进入状态,又一件随机事情来了……
阿超:你要厚着脸皮,说“不”。
当场景、功能都计划好的时候,要给员工足够多的时间,让他们投入到工作中去,而不要经常打断他们。
要尽量减少非开发时间,不要动不动就开“全体会议”。团队成员们自我时间管理也很重要。由于MSF鼓励沟通,TFS也设置了不少提示(Alert)自动报告全体成员项目个方面的情况,因此团队的E-mail会特别多。在这种情况下不要整天被E-mail牵着鼻子走。在Outlook上设置好邮件规则,按下面的规则把邮件自动分类到不同的邮件夹中:
(1)从直接老板来的,发给你一个人的——马上处理。
(2)从团队成员来的、和项目有关的事情,自动分配到一个叫“Team”的邮件夹中。
(3)从TFS来的状态信息,如团队的check-in email,自动分配到一个叫“Check-In”的邮件夹中。
(4)从其公司他同事来的与工作无关的消息(如笑话,大减价的消息等),自动分配到一个叫“Other”的邮件夹中。
最好每隔两三小时集中阅读和回复一下E-mail。
荔荔:河对岸的河曲数码经常把所有人都拉去做“封闭开发”,这样是否就能避免干扰?
阿超:我们做开发软件,并不是让团队像被关在监狱里一样。要有大家自由交流的时间,团队成员们在无拘束的环境中,会更乐意提问和分享,这会比召开正式会议,强迫每个人分享好得多。在“封闭开发”的情形下,领导也更有可能每天、每小时来询问项目的进度,这种团队内部的干扰源,并不会因为团队搬到一个监狱里而消失。大家还记得MSF的“充分的授权和信任”?
果冻:我这里还有笔记。
小飞:另外,我经常去看测试人员又发现了什么bug,有时就花时间研究和修复它们。
阿超:可以等第二天会诊之后再看看是否值得马上修复。
果冻:这样新建的bug 要等到第二天门诊之后才能给开发人员处理,是不是影响进度?
阿超:不一定。
提示:
(1)开发人员在开发阶段最重要的任务是把规定的功能完成!
(2)在项目初期,可以不用集体会诊,开发/测试人员可以直接处理“缺陷”,不必等待。
(3)在任何时候,测试人员都可以把“缺陷”交给开发人员,但是只有会诊的人员才能改变会诊决定。
14.6.2每日构建
阿超:我好像有几天没有受到每日构建(Daily Build)的报告了。
小飞:已经有一阵子 Daily Build 没成功了。
阿超:哦?我们上课的时候不是说过“每日构建”的重要性么?
小飞:我同意在我们有时间的情况下,我们要做每日构建,但是当我们忙的时候,我们的确实没有时间去管构建的问题。
阿超:这么说还是应了那句话——在理论上,理论和实践是一回事,而在实践上,理论和实践是两回事。
阿超指着窗外,河对面的工地。
阿超:他们在建楼房吧。
小飞:对,据说是软件学院的新大楼。
阿超:那,他们的脚手架自从搭好了之后,就没有垮下来过吧。
小飞:那当然不会,俺爹是干这一行的,所有的工人和材料都得运上运下,脚手架要搭得特别结实。
阿超:那你爹他们有没有因为工期紧,就凑合着搭个架子,就往上盖楼?或者脚手架倒了也不管?
小飞:那哪成!要倒下了,就要出人命了,哪还能盖楼?!
阿超:对呀,我们的软件构建,就和脚手架一样,每天都要立着,倒下来就麻烦了。
小飞:不过,我们搞开发的都有点不屑搞构建,没有写程序来劲。
阿超:不会建脚手架的小工,你爹会要么?
小飞:不会。
阿超:不会做构建的程序员,就像不会搭脚手架的小工,运球不熟练的球员。这样的程序员,我们也不要。
小飞:我明白了。
下午,阿超在喝水的时候碰到小飞来报告说Daily Build正在运行中。发现的几个错误都改正了。估计晚上就可以产生一个新的构建了。
阿超:了不起,这么快就做好了。
小飞:超总,我想提一个和我职业发展有关的问题。我们接受的可都是本科软件工程教育,我们当时的院领导说我们毕业后都是要朝CTO发展的,至少是软件金领,我当然知道这是遥远的将来的事,但是我总觉得我可以做一个软件白领吧,这些构建之类的事情,嘿嘿,是不是要由所谓软件蓝领来做?
阿超:问题提得好……
他望着这位将来的CTO、软件金领,突然想抄起身边的塑料水桶,把水都从他的白领里灌进去。他喝了一大口水,退到窗边,勉强把这个念头压了下去。阿超看着窗外的操场——
阿超:听说你篮球打得不错?
小飞:还行,常和二柱几个玩。
阿超:你提到大学的课程,让我想起大学的篮球课。我们当时考试的科目之一是定点投篮。老师叫每个要考试的同学站在罚球线上,别的同学负责捡球,考生就站着不动,一个一个地瞄准了投,如果进了一个球,老师才开始算分。平时玩球的同学都是十个进七八,连运动细胞不多的同学都是十个球中五个以上,皆大欢喜,好像大鲨鱼奥尼尔罚球也不过50%上下,大家都有NBA球星的感觉。另一个考试科目是两人配合上篮,当然这是在球场空荡荡的时候进行的,大家接/传/投一气呵成,颇有马龙和斯多克顿的风范,觉得篮球“技止此耳”!考试后,我们意犹未尽,和在一边玩球的同学打球赛,尽管我们“定点投篮”和“二人配合”的分数都很高,但是我们都输得很惨……
小飞:为啥?
阿超:因为我们运球、传球都不熟。这都是我们平时不屑练习的东西,即使勉强到了篮下,投篮都是在踉跄之中完成,当然没有考试时候的准星。
小飞:超总,您把我绕远了,您的意思是?
阿超:我觉得大学的软件工程课,本来要教全面的技术,但是考试往往只考定点投篮和无防守情况下的配合。所以有些大学的高材生到了实际工作中,很多“蓝领”的基本功,比如实战中的运球、传球都不灵,他们津津乐道的定点投篮十中八九的功夫也没有发挥的机会了。我还没有见过从天而降的白领或者金领。所谓的大拿们都是从蓝领摸爬滚打出来的。换句话说,我眼里没有白领或蓝领,只有“汗领”——就是大家都得出汗干活。
小飞:你是说构建就像运球、传球……好,我明白了。超总,下班后我们球场见!
14.6.3构建大师
头碰头会上,大家发现,最近连续几个构建都不成功,测试组都拿不到新的版本,没法进行测试。
阿超手里拿了小飞整理的“导致构建失败的失误列表”分送到每人手里,表上列举了错误的类型和导致错误的签入,以及牵涉的成员。
大拴: 看来拿不到新的构建版本的原因有这些——
(1)构建在开发人员本地机器上就不成功。
(2)构建在本地成功,在服务器上失败。
(3)构建在本地及服务器上成功,但是基本功能不能使用,导致无法进行测试。
阿超:试着对症下药,很多事情我们在培训时都讲过了——
(1)强调基本开发流程(注意编译要产生debug|release两个版本)。
(2)签入时,必须从TFS同步下所有最新的版本再编译,而且个人的签入要做成一个Shelveset,成为原子操作,而不能把一次修改中的所有文件分成几次签入。
(3)这时,我们以前做的单元测试和构建验证测试(BVT)就要发挥作用了,每一个开发人员在签入前都要运行所有的单元测试和构建验证测试,确保没有问题后,才能签入。
我们要让团队中做事不仔细的人慢下来,这样能减少他们的危害。
欲取之,必先予之。阿超进而建议——
对于下一个导致构建失败的成员,授予“构建大师”(Build Master)称号,构建大师做下面的事:
(1)负责管理构建服务器。
(2)调试构建,负责找错,并分析出错的原因。
(3)负责把“构建大师”称号和责任交给下一个导致构建失败的成员。
(4)“构建大师”同时向团队的“腐败基金”存入50元,以供大家将来“腐败”之用(此项可选)。
14.6.4宽严皆误
上次头碰头会议后,各个小组都进一步强化了单元测试和BVT。
下午,果冻发了一封E-mail,标题是“我受不了啦!”内容如下——
我的签入流程:
(1)代码写好,本地测试通过,代码复审通过。可以签入了。
(2)同步TFS上最近更新,编译debug |release,解决版本冲突(半小时)。
(3)安装最新版本,运行本地单元测试,BVT(一个小时)。
(4)提交到TFS上,发现有版本合并冲突,因为在2、3步的时候,有人签入了和我的代码有关的新修改。
(5)如果我简单地合并版本,并且签入,很有可能会导致TFS 上编译失败。但是如果我为了保证质量,在合并后,本地编译并运行各种测试,这相当于重复了2、3步。当我再次提交签入(重复第4步)时,有可能碰到新的版本冲突。这样循环往复以至无穷……
二柱发了E-mail,第一句话就是:
在理论上,理论和实践是一回事,而在实践上,理论和实践是两回事。
然后也抱怨了类似的问题,似乎大部分时间都花在了没有价值的“同步/编译/验证/再同步……”的循环中。
荔荔:似乎应该在签出一个文件的时候,加上一个“防止别人签出”的锁,这样就没有冲突了。
果冻:但是如果你锁住了file1,要签出file2;与此同时,我锁住了file2,要签出file1,这样我们都进入了死锁……
小飞:我刚刚同步TFS,然后编译就不成功了。我在一台全新的机器上重新试了一次,也不行。这至少证明不是我引起的问题。现在我已经没法工作,我只好到“顶球”喝两杯去了。谁把错误修好了,就给我发短信,我就回来上班。
阿超:除了构建大师,所有开发人员都可以到“顶球”去玩。
构建大师:我已经连续三天错过了午饭时间,谁能帮我从顶球带两个烧饼回来?另外,能不能不要在午饭前安排构建?要不然铁打的胃也受不了。
经过一个多小时的忙碌,构建终于好了,但是构建大师问阿超,现在构建成功了,明天呢?
阿超:让我想想……
阿超晚上把情况和同事们的意见报告了愚公,阿超在E-mail最后写到:
有两条路团队可以实行:
(1)很严的规则和流程控制,这样会保证很高的签入成功率,如果一个人根据流程来做,几乎肯定能成功。这样构建质量高,但是团队的进展会受到限制。极端情况下,整个团队的进展被序列化为一系列个人串行签入操作。
(2)宽松的规则和流程,每个人随时可以签出签入,签入时的成本很低,但是签入成功率不高,构建质量低,极端情况下,所有人都可以签入,同步,但是没有人能正常工作。
哪一种是最好的呢?
第二天一早,阿超就看到了愚公的回复:
不审势即宽严皆误,从来治蜀要深思。
阿超心想,那什么是我们这个团队目前的“势”呢?他列出了对每一个步骤,宽、严各是什么做法,当前团队的情况(势)是什么,这样就得出了一个用“宽”或者“严”的决定,如表14-7所示。
当行为只是影响到个人的时候,尽量放松,让个人根据自己情况处理;当行为影响到整个团队的时候,尽量严格,因为整个团队都有可能会受影响。同时,我们要提高可预见性——明确构建大师的职责,公开显示固定的构建时间。
表14-7宽严表
步骤 |
宽 |
严 |
势 |
签出 |
自由签出 |
签出时候,将文件上锁 |
很多人都会同时编辑同一文件 |
本地单元测试 |
不要求 |
要求 |
每个模块都要求写单元测试 |
本地check-in test(签入测试) |
不要求 |
要求 |
BVT还没有完成 |
签入时间 |
任何时候 |
每天固定时间开放 |
目前签入情况很混乱 |
签入冲突处理 |
合并后即可签入 |
合并后,再重新编译,测试,再提交 |
重新测试会花费比较多的时间 |
续表
步骤 |
宽 |
严 |
势 |
签入必须经过代码复审 |
随意 |
必须 |
开放人员有一半是新员工,必须通过代码复审建立良好的规范 |
签入时必须运行代码分析工具 |
不要求 |
要求 |
代码分析工具尚未配置好 |
签入时单元测试必须同时签入 |
不要求 |
要求 |
每个模块都要求写单元测试 |
签入必须是多个相关文件同时签入 |
不要求,可以签入单个文件 |
要求 |
保证每一个签入都不会导致构建失败 |
签入必须和一个工作项关联 |
不要求 |
要求 |
所有的工作必须有工作项跟踪 |
设定专用网络服务,自动处理提交的ShelveSet,构建,BVT,然后签入代码 |
不要求 |
设置 |
需要很多人力来设计并维护 |
签入必须经过代码复审 |
随意 |
必须 |
开放人员有一半是新员工,必须通过代码复审建立良好的规范 |
签入时必须运行代码分析工具 |
不要求 |
要求 |
代码分析工具尚未配置好 |
签入时单元测试必须同时签入 |
不要求 |
要求 |
每个模块都要求写单元测试 |
表14-8 具体流程
时间 |
总体 |
管理/程序 经 理 |
开发 |
构建 大师 |
测试 |
8am~10pm |
开发人员可以同步代码,这时只有非常要紧的签入才能经过批准,签入TFS |
9am—— 头碰头会议,bug会诊,分配bug |
同步代码,构建,根据自己的任务/bug情况决定今天的工作 |
测试新版本,新建bug |
|
10pm~12pm |
代码签入时间,经过正常代码复审及其他流程后,代码(连同单元测试)才能签入 |
程序经理组织必要的会议 |
单元测试 |
准备构建服务器 |
|
12pm~1pm |
午饭时间 |
续表
时间 |
总体 |
管理/程序 经理 |
开发 |
构建 大师 |
测试 |
1pm~3pm |
构建/安装/基本测试/宣布版本质量(见后) |
待命,随时准备攻克问题 |
全程监督执行,负责把导致构建失败的缺陷(找人)修复并签入 |
运行基本测试 |
|
3pm~6pm |
开发/测试人员继续工作 |
运行BVT后,宣布此次构建质量(失败/可测/可用) |
聪明的测试人员此时就开始测试并报告缺陷 |
||
6pm |
晚饭及机动时间 |
阿超:我特地把紧张的构建及待命阶段安排在午饭之后,这样大家至少可以安心吃饭了。
14.6.5 小强地狱(Bug Hell)
在这一次的头碰头会议上,平时不主动发言的阿亨也说话了。
阿亨:开发的同志们,你们手里有那么多小强,为什么都揣着掖着,不舍得修复,让测试人员有事情做?测试人员反映因为现有的小强没有被修复,有越来越多的小功能点不能进行测试,我们都要没事做了。
大拴:我们的开发任务很重,必须先把新功能全部实现后,再修复旧的小强。
阿亨:这是不对的,我们有些小强在你们手头很久了,看似举手之劳,为什么不尽快修复,让我们测试组能继续完成测试?
二柱:我们都是按优先级来进行,开发新功能的优先级远大于修复小强。
阿亨:但是有些开发人员手里头有二三十个小强,难道数量不是一个考虑因素?
阿超:我同意,随着项目的深入,每个人同时要开发新的功能,修复以前的缺陷。由于没有明确的优先次序,一般人都愿意把时间花在开发新功能上。但是我们的确需要平衡进度和质量。有这样的一种方法:
小强地狱(Bug Hell)
如果开发人员的小强(bug)数量超过一规定值,则此君被送入“小强地狱”,在地狱中,他能做的唯一一件事就是修复小强,直到小强数量数量低于此阈值。
这一阈值由团队根据实际情况来确定,要注意:开发人员同时“入狱”的人数应在全体成员的5%~30%之间,若比例太高,则要考虑阈值或者小强数量的计算方式是否合理(是否只包括某一严重程度以上的bug)。
在项目过程中,阈值不宜频繁调整,最好事先宣布阈值。
大拴:但是我们已经违反了“最好事先宣布阈值”这一规定。
阿超:如果我们现在要让20% 的同志入狱,我们马上运行一个TFS 查询看看这一个阈值是多少?是15?好,那我们现在宣布给大家三天时间,第三天后,小强数量达到或超过15 的开发人员请入狱,然后每天早上9点头碰头会议时统计并宣布入狱/出狱名单。
大牛: 其实先把所有的功能写完也不错,至少我可以告诉客户“功能写完了”,让他们高兴高兴。
大拴:大牛,这不就是咱们以前项目的情况么?你一直问“功能都写完了,为什么还不能用”? 我们一直说“还有一些小问题”,然后小问题总是不能解决,因为要真正解决这些“小问题”的话,我们还得重写一些功能。
阿超:对,很多问题,甚至是大问题,都隐藏在目前的小强后面,如果一味赶所谓的“进度”,到时候有些小强就变成了大怪物,因为我们已经在错误的基础上搭建了很多新的逻辑和功能,这时再来处理一些历久弥新的小强,就有投鼠忌器的麻烦。
阿亨:那怎么办?
阿超:我们要分析小强,看看这是一个小问题,解决了就万事大吉呢?还是冰山的一角,解决后也许会发现更多、更棘手的问题。或者看似不经意的一个小强会让很多人加班重新实现功能——这就成了设计变更需求——DCR。
14.6.6 DCR Tell mode v.s. Ask mode设计变更
在项目早期,如果大家觉得要做一个设计变更,可以用告知模式(Tell-mode)的形式,就是说,修改方必须通告所有关系人:“我在这里修改了某某界面。”但是修改方不必取得其他关系人(或者模块)的事先同意,就是说可以先行设计并编码。当然,如果其他关系人不同意,修改还是不能签入。
当项目进行到稳定阶段,Tell-mode 要改为请求模式(Ask-mode),这时,修改方必须先问“我是否可以在这里修改某某界面?”(当然还要有更详尽和充分的理由)得到肯定的答复后,才能进行修改。这时的缺省回答是“不”。
14.6.7 每周进度报告——还有多少事没做完
头碰头会议。
大拴:我有一点不太放心……
大牛:哦,为啥?我们大家都干得很欢。完成任务应该没问题吧。
大拴:我们每天都在签入新的代码,每人都很忙,但是我总觉得不太对劲。会不会越做事情越多呢?
阿超:这时我们可以看看各种报表,首要推荐的是“RemainingWork”。
请看下页的图14-2。
这个报表告诉我们究竟还剩下多少事情要做。我们要分析这么多签入到底是否解决(Resolve)了相应的任务,如果是,那么我们的任务数量应该逐渐下降,但是从图上我们看到红色的任务和缺陷还在缓慢增长。而绿色的“已完成任务”,却一动不动,这就要引起我们的注意了。
可以在报表设置控制板中,进一步选择你要报告的内容,如:Iteration,选择里程碑;Area,选择项目的不同部分,也可以修改报告的起始和终止日期等。
图14-2 还有多少事