如何建设全功能团队

简介

团队的开发人员撇开需求沉浸在想象中的“完美”程序中;测试人员迷茫的点击着按钮试图搞明白这到底是个什么功能;设计师造出了没有尽头的楼梯,更糟的是,客户爱上了这个设计;团队领导四处救火,力有不逮。种种迹象表明,我们得打破分工带来的壁垒,建设全功能团队——大多数人能完成大多数种类工作的团队。

在一次闲聊中,女友的母亲说起实习大夫必须轮岗一年才会进行分科学习,我质疑道:“对于致力于心脏病治疗的医生来说,他岂不是在不相干的学习上浪费了一年时间么?”,她母亲笑着说:“不这么作,你怎么确信病人的确患有心脏病呢?”。不知道为什么,我眼前突然浮现出这样的场景?测试人员在怯生生的询问:“这是一个缺陷么(而不是操作系统/浏览器的限制)?”。

亚当与大头针工厂

亚当·斯密于1973年在描述大头针工厂的专业化生产时提出了社会分工的好处:提高熟练程度、减少任务切换时的开销、便于机器的应用。我们似乎可以非常自然得推导出重复设计、重复编码、重复测试可以增加相应岗位员工技术熟练度,提升效率,并由此提升企业的盈利能力。

 然而市场的不断变化让重复生产的美梦不在,切换任务变得越来越频繁。IT公司不是大头针工厂,知识工作者毕竟有别与体力劳动者,在劳动主体发生变化的过程中有两件事情的差异被放大了:一是局部优化与整体优化的差异,二是正确的做事与做作正确的事情的差异。

有一道数学题,假设每个开发人员每天可以完成一个功能,测试人员每天可以测试2个功能,团队由3名开发人员和1名测试人员组成,那么一周内通过测试的功能最多为多少个?

大多数人的第一反应是5(天)x2(功能/天)=10功能,下面的表格会告诉你,由于负载不均衡,测试人员在周一没有功能可测,团队其实无法在一周内交付10个功能。

周一 周二 周三 周四 周五 总计
开发人员 3功能 3功能 3功能 3功能 3功能 15个功能
测试人员 0功能 2功能 2功能 2功能 2功能 8个功能

(表一)

那么我们改变一下条件,假设团队中有4个开发人员,并且开发人员可以参与测试,结果会怎样呢?

周一 周二 周三 周四 周五 总计
开发人员 4功能 4功能 3功能 2功能 0功能 13个功能
测试人员 0功能 0功能 2功能 4功能 8功能 14个功能

(表二)

我们最终能够交付13点,产量提高了60%, 如果我们只留下三名全能人员:

周一 周二 周三 周四 周五 总计
开发人员 3功能 3功能 3功能 1功能 0功能 10个功能
测试人员 0功能 0功能 0功能 4功能 6功能 10个功能

(表三)

居然比3个开发人员和1个测试的人员组合还多交付两个功能!

我们当然有理由质疑第二题的假设:“开发人员可以胜任测试人员的职位”。又或者继续讨论迭代二的数据变化。我对此的的回答是:

第一,以我的观察来看开发人员之所以不进行测试工作,不是能力不允许,而是主观上认为测试工作是简单、重复而枯燥的,不愿意作。客观上开发人员们比较贵也更难于培养,组织层面不允许这样的“浪费”。

对测试工作的偏见客观上促成了大量不具备技术能力的人选择测试工程师作为职业,而技能不足则一步导致了测试工作倾向于简单重复。测试人员在很大程度上无法判断什么是正确的事情(作正确的事),从而更倾向于熟练的按照脚本进行操作(正确的做事)。

第二,我的关注点不在交付8点还是10点,我希望这个例子能够引发大家对于均衡生产的思考。

软件的需求和实现可以被细化,但它毕竟不是大头针,需求和实现间往往呈现出关联与依赖,换言之,局部效率的增加无法直接转换为整体效率的增加。而整体效率的优化往往依赖于均衡生产(参考表三),即消除生产的波峰(过度生产)和波谷(生产不足),避免任务时松时紧,松时生产力浪费(周一时专职测试人员),紧时加班加点,粗制滥造。

我倾向于认为亚当·斯密对劳动分工论述的假设是:需求稳定,简单生产。对于IT领域来讲,这些假设还成立么?

拧螺丝的卓别林

不难发现,对分工以及个体效率的迷信已经深刻的影响着IT领域。分工的端倪在招聘时就已经显现,即便对于差异不大的毕业生们,雇主也会根据其极有限的技能,用不同的标准进行测试(Java, .Net, PHP等),并在入职后将其冠以前端工程师,后端工程师,测试工程师,支持工程师等不同的头衔,甚至可能在其可见的职业生涯中专门负责某个文件的维护。

整体效率的优化要求IT团队消除技能壁垒,培养多面手,根据计划的的变动,弹性地调整任务,达到各角色和流程之间的平衡。对于IT企业来说,变化从招聘时就必须开始。找到拥有学习热情、学习能力、学习习惯的人变成了当务之急,员工是否掌握了某种算法、语言或者工具应当从准入条件降格为对于其学习能力和热情的一种(不是唯一一种)证明。

整体效率的优化要求员工必须持续学习、成长,兴趣无疑是成长的催化剂,然而丧失意义的工作却在不断扼杀人的兴趣。丹?艾瑞里在怪诞行为学里著述到:

劳动者与他自己的生产活动、劳动目标以及生产过程相分离。这就使工作成为非自发性的活动,因此劳动者就无法对劳动产生认同或者领略到劳动的意义,而缺少了意义,专业人员可能觉得自己好像电影《摩登时代》中查理·卓别林扮演的角色,一切都由工厂的齿轮控制,他们根本不会有全心全意工作的愿望 。

如果员工成长是必须的,那么,帮助员工认识到工作的全貌也是必须的。角色轮换是一个很好的解决方案。在项目内部通过角色互换,不限角色的结对工作,加强不同角色,不同模块间的知识传递,打破技术壁垒,帮助员工从不同视角理解项目,锻炼技能,进而增加团队均衡生产的能力。

在我看来,进行角色轮换的最大阻碍在于编程能力的普遍缺乏,大多数的测试、需求分析工作(鉴于大多数团队所处的地位,需求分析师实在言过其实,更精确的名字是需求整理师),迭代管理,简单的客户交流,学习曲线都非常低,任何成员都可以在师傅的带领下迅速掌握工作要点,然而编写程序却是个例外,即便对于基础良好的新人,在经验丰富的导师带领下,也需要2个月左右才可能写出比较体面的单元测试、较为面向对象的程序。在分工的体制下,用别的角色轮换开发人员几乎是个死局。

非常奇怪,IT领域如此的看重抽象能力和逻辑分析能力,可为佐证的是层出不穷的建模语言,模式,领域模型,架构。然而最能训练抽象能力和分析能力的一项活动,却仅仅有选择性的开展,这是不是意味着我们认为IT项目可以在大多数人无法(也没有能力)达成共识的情况下顺利展开并成功交付呢?在我看来,编写程序不仅仅是一项技能,一种思考方式,还承担着构造IT团队成员间共同经验区,提高交流效率的目的。

一个值得从其它行业借鉴的经验是首先展开基础素质培养,再进入领域培养专业素养,换言之,避免过早的分工,所有新人从编程开始职业生涯,在公司的体制层面促成每个新人都能经历力所能及的所有角色。在具有了一定的基本素质后,在员工对工作内容和自身兴趣有了充分的了解后,根据个人意愿进入领域发展专业技能,兴趣将成为员工成长的内在动力,而良好的基本素质将使员工有能力在专业岗位上施展自己的想法。

同时公司应当鼓励员工跨界工作,《应用Selenium和Ruby进行面向领域的Web测试》的作者是拥有卓越能力的开发人员,他曾经进行了相当长时间的测试工作,在其它人抱怨自动化界面测试难于维护时,他优秀的抽象能力、分析能力已经帮他提炼出测试模式,识别出缺陷,找到了优雅高效的工作方式并诞生了这篇优秀的文章。

丹·艾瑞所言于我心有戚戚焉。

知行合一

在过去9个月间我们在团队中进行了建设全功能团队的初步实践,在分享具体实践前,我希望下面的总结性数据能帮助你获得一些背景知识。

项目处理的是期货交易领域,使用的技术栈是C#, ASP.NET MVC。团队主要由八名开发人员以及两名测试人员组成(其中一名测试人员在项目中期加入),其中4位是毕业生,3位具备工作经验,但刚刚加入Thoughtworks,只有一位开发人员具备.Net开发经验。

下面是全部35周的燃尽图,黑色实线代表项目的范围,绿色实线代表开发完成的速度,蓝色实线代表测试完成的速度,每周为一个迭代。

image0

在这张图的大部分区域内蓝色和绿色是重叠或者非常接近的,这意味着团队每迭代开发完成的功能恰好与测试人员的处理能力对齐。一方面,这归功于测试人员自行实现的自动化测试框架对效率的提升,另一方面,开发人员参与测试也起到了平衡开发和测试速度的作用。

让我们截取开发过程的一部分,观察每个迭代的速度,在下面这样图中,横轴代表第几个迭代,纵轴代表每迭代完成的功能点数。

image1

从项目经理的角度看,团队的交付速度很稳定,从15周开始直到项目的结束,我们都可以放心的使用12点每周的经验数据进行估算、计划工作。事实上团队在后期所处理的工作种类越来越多,包括了正常的开发任务、公式转换、性能调优、验收测试、支持等。在这种情况下,每个人都具备跨角色,跨模块工作的能力才保证了可持续的交付节奏。

在这篇文章中我们一起回顾了分工历史,对于技术团队影响以及建设全功能团队的必要性 ,在下一篇文章中我将详细分享一些实践以及经验数据。

Share

在团队中如何带领新手

目标

通过引导、任务分配和沟通反馈等方式,让他逐步适应团队正常工作面临的压力、节奏和不确定性。对于一些心理预期过高的领导者,在此阶段应该明白,对于一个新手,还暂时谈不上能力判断和机会给予。

方式

创造良好的工作气氛:信任是第一位的。只有相互信任,才能把工作放手交给新手去做;另一方面,在他们失败的时候依然要给予信任,否则,所有的事情结束点就是“失败”。一个人所取得经验,最大的来源就是失败。良好的工作气氛,也包括各种非正式的交流与沟通,比如聚餐、聚会等等。

定期反馈:可以在每日、每周对新手的工作进行反馈,同时也让新手有一个渠道发出自己的声音。反馈应包括:做得好的地方,以及需要改进的地方。反馈中需要注意的是,虽然是新手,但已经是成年人,思维、行为模式大部分已定型;我们需要去识别对方的性格特点,合适的沟通方式,以及他们的动力来源,尽可能做到:了解他们的愿景,帮助他们做成他们想做的事,帮助他们成为他们想成为的人;切忌让他们被迫成为“我们”想要的人。

制定学习计划或任务:针对新手已有的知识体系制定短周期的学习计划,分配适当的任务给他们完成。在这个过程中,需要去检查并督促对方完成计划或任务。能够完成简单任务之后,逐步让对方感受到工作中的压力和需要随机应变的场景,给予指导,让他们逐步能独立适应工作。

障碍

带新人的过程中,往往会遇到不少的阻力,最终他们无法达到早期的期望。分几个方面来解读:

两只手表:在公司里非常影响工作的是权职受到牵制,带新人这种小事也不例外。如何新人失去了对你的信任或他更倾向于另一个人的反馈,那么你对他的指导是无法成功的,遇到这种情况,可以和另外的人,也许这个人就是你的上司,谈谈如何更好地带领这个人,或者放弃对他的培养。

沟通失败:部分虽然工作多年,但沟通经验不够丰富的人,可能无法在双方沟通中明白对方表达的真实意图,并无法识别对方性格上的偏好,导致沟通上的失败最后无法达成目标。有效的沟通,是需要双方都明白对方的意图,作为优秀的沟通者,更需要清楚地知晓在沟通之中,哪些“需求”是可以让步、放弃但又不影响全局的,这就是妥协:我们应当明确,当一方作出让步时,又需要对方相同地作出哪些方面的让步,以达到对目标的共识。在与成年人的沟通中,可能会出现多次的妥协,因为每个人有独特的背景和知识,这都导致了不同的认知和行动方式。

纠正行为模式:这种情况对双方都是痛苦的过程。并不是每个人都出生在良好的家庭,一开始就有优秀的父母指导如何做事。比如隋性、注意力分散、害怕挑战、防备心理等等。在这方面我也有不少失败的经验;所以我认为“改变”一个人几乎是不可能的,但我们可以采取一定的手段,将负面行为的影响力降低到最小。比如之前和其它人沟通如何让90后新人对自己的工作任务负责,不是在他们彻底忘记任务后批评责备,而是将他们的任务期限、状态醒目地展示在工作区域,多次提醒的结果明显大于事后究责。另外在需要一个人做出改变的,应当与他明确,他做出的改变是为了满足团队的共同目标,而非个别领导人的偏好;他做的改变是为了解决自身面临的障碍,而不是变成所谓的“完美之人”。

最后如果让我用较少的几句话来总结“带人”的经验,我会说:第一,带人时你有权力,但不可利用权力,你要明白权力“该”做的部分,而不是沉浸在“可”做的部分;第二,带人时对方会做一些你让他做的事,但不可把他当成你,甚至当成你可以去塑造的人物,他需要在这个过程中成为他的更好,你也需要在这个过程中成为你的更好,否则,你只是这事的附属品,你会费力不讨好,会委屈难受;第三,世上没有完美的人,你也不是爱因斯坦,调子放低点,会有更多人主动向你学习。

Share

我和敏捷团队的五个约定

我——作为一名测试人员——有一个与众不同的习惯:每当要加入一个新项目的时候,我总会找到项目中的同伴,真诚而亲切地说:“为了更好地合作,我有5个约定,希望大家能尽量遵守”。

约定1. 业务分析师们,我们其实是同一个角色的两种面孔,请叫上我们参加客户需求会议

我们的团队需要让客户频繁的得到可用的软件,客户的不断反馈会给软件的未来做出最正确的方向指引。

如果我们交付的软件有很多质量的问题,存在大量的缺陷,客户会被这些缺陷的奇怪行为干扰,没有办法把注意力放在软件本身的价值是否符合他们的真正需求上, 不能给出最有价值的反馈。所以,我们只有频繁的做测试,在每次交付之前都把质量问题找出来告诉我们的团队,问题才能及时的得到改正。

而我坚信“prevention is better than cure”(预防胜于治疗),我会要把工作的重点放在预防缺陷上,这样可以节省Dev们很多修复缺陷的时间与精力。

为了达到这个目的,我需要跟你一起参加客户需求会议,尽早的了解客户需求与使用软件的惯常行为。那么在你完成需求的验收条件的定义的时候,我也基本完成了测试用例的准备。

我们可以赶在开发人员们写代码之前就告诉他们我要测什么,让他们减少因为过于乐观而漏掉的一些重要的有破坏性的情况,减少缺陷的发生。这是我测试的一项重要任务。

如果你们在大部分需求都整理好了再交给我们,我会浪费掉等待的时间。更重要的是,开发好的软件里面已经有很多本来可以不存在的缺陷在里面了,开发人员们可能需要加班加点来保证在项目最终交付时间之前把它们改好。这样很容易产生新的缺陷的。

所以,请让我尽早了解需求,请不要让我到项目后期才能开始测试。

约定2. 开发人员们,虽然你们是编写自动化测试的专家,但请听听我们意见

我知道,对于你们,自动化测试不过是利用junit, rspec, selenium,watir,uiautomation等等写出的“另一段程序”而已。而对于80%的QA来说,编写自动化测试并不是一件简单的事情。

不过我仍然相信,有测试人员介入的自动化测试更有价值。

你们用单元测试,集成测试来保证代码的质量。然而你们的这些日常测试离代码更近,离最终用户还点远。很多测试都不是在测软件功能。

你们可以把功能测试写的又快又多,而我们可以指出什么功能测试最有必要加到自动化测试中。

你们平时大部分精力都在编码上,没有太多时间去查都有什么缺陷。而我们可以指出什么地方缺陷可能会出现的比较频繁,建议在这些脆弱的地方加自动化测试。

所以请听听我们的意见,我们可以给你们提供这些信息。

约定3. 项目经理们,请不要要求我们测试软件的所有路径

软件测试是一个永无止尽的任务。基本上没有什么软件简单到我们能够尝试完它的每一个可能的路径的。就连一个看似简单的微软计算器都有无穷尽的路径,无止尽的输入,更何况比这个更复杂的商用软件。

如果你们担心没有尝试过全部的路径不可靠,疑惑我们怎么敢说这个软件质量是好的还是坏,都有什么风险。请你们先注意,我们是跟业务分析师一样,都了解软件的价值的。价值可以帮我们做出判断,什么时候可以停止测试并对客户说我们的软件已经满足您的要求了,请放心使用。

因为我们了解价值,我们可以肯定的说哪些软件的使用方式是至关重要的,哪些是不太可能出现的。我们会在全面测试了软件以后,把主要精力放在价值高的功能点上。合理的利用项目有限的时间。

因为我们了解价值,我们可以正确的把发现的问题分类。我们可以帮助dev们把精力放在重要的缺陷上,避免把时间放在对于客户微不足道却不得不花费大量精力才能修正的问题上。

所以,请不要要求我们无止尽的测试一个软件。我们了解价值,请相信我们的判断。

约定4. 迭代经理们,如果对于交付风险有任何疑问,请来询问我

BA和Dev们都是关注一个软件在什么情况是可以良好的工作。而我们除了验证这些情况以外,大量的时候都用在寻找什么样的情况软件不能正常的运行。所以除 了针对定义好的软件行为进行测试,我们还会做很多探索性测试。我们通常可以通过这样的测试发现一些没有定义的、不曾预期的行为。这些行为往往将会构成软件 交付的风险。

我们会告诉你们现在都发生了什么问题,分别分布在哪里。

我们会告诉你们,在什么情况下软件可能会有异常行为,是不是会牵连到其他的部分,是否可以绕过去。

我们会告诉你们,哪些部分功能比较不稳定,需要更多的留意。

约定5. 测试人员们,那些敏捷实践对于我们也是有用的。

结对不是dev们的专利。我不希望总见到你们独自坐在自己的位置上冥思苦想。走出去,跟其他队友多多交流!

多跟测试队友交流,pair看看设计的测试用例是不是够全面,独自一个人想到的未必足够好。他们会给你诚恳的意见的。对他们,也请一样认真对待。

如果你发现开发人员们做出的架构决定使测试工作变得更困难。那么请大声地告诉他们,design for testability(提高你们设计的可测性)。

如果你发现业务分析师写的需求无法验证,定义的客户行为不够具体,一个用户故事中包含太多了功能点,等等,那么也请大声地告诉他,INVEST(独立,可协商,价值,可估算,短小,可测)。

也请你们多跟开发人员结对写自动化测试,既可以帮助你们学习怎样更好的编写自动化测试,也能帮助开发人员们结对更多的了解用户行为。

这就是我的五个约定,它们是我在团队中顺利展开工作的基础。


作者:覃其慧,ThoughtWorks敏捷咨询师。她参与了大量的敏捷软件开发的实践和敏捷咨询。目前主要关注以价值为驱动的敏捷测试。


本文原文发表于InfoQ:http://www.infoq.com/cn/articles/thoughtworks-practice-parti

Share