当过技术经理的人可能都有感触,如何才能让团队的技术成果物质量更好?如何才能让团队成员之间更好地做好互备,避免出现人员一走无人能接盘的情况出现?对于这些相关问题,我今天想和大家聊聊结对编程,这是一种软件编程模式,使用这种方式有助于我们更好地做好技术团队的质量管理,也有助于提升团队的整体能力。
基本介绍
结对编程,英文是 Pair Programming,是一种编程模式,从字面上理解就是两个程序员并排坐在一台电脑前,面对同一台显示器,他们一起进行需求分析、设计、编码、编写测试用例、执行单元测试和集成测试,甚至一起写文档。这么说吧,基本上软件开发流程里的所有开发环节他们都需要一起肩并肩地、平等地、互补地完成工作。
结对编程概念最早出现在 1995 年,Larry Constantine 在他的专栏中第一次提到了他在 Plaugheris 软件公司观察到的一个现象,并将这个现象总结为 Collaborative Programming(协同编程)。他当时对现象的描述是这样的:“两个程序员一起工作,可以更快地完成并交付经过测试的代码,而且这些代码几乎是没有 Bug 的”。1996 年,Kent Beck、Ward Cunningham,以及 Ron Jeffries 一起提出了极限编程(Extreme Programming),他们吸收了协同编程思想,并将其正式定名为 Pair Programming。从极限编程来看,Pair Programming 是 XP 编程模式的一个关键实践,也是它成功的关键因素之一。
角色分配
按照极限编程定义,参与结对编程的结对角色通常分为两个角色,分别是“驾驶员”和“领航员”,两者的作用如下:
- 驾驶员控制鼠标和键盘的使用,即负责编码工作。
- 领航员坐在驾驶员一旁观察和思考,即负责检查错误、考虑解决方案。
注意,结对的角色是可以互换的。如果“驾驶员”在编码活动过程中出现了技术盲区(不精通的技术领域)或者方向性的错误,结对编程双方可以互相交换角色,让“领航员”转为“驾驶员”角色继续编码。一般情况下,应该鼓励这种互相交换角色的行为,理论上来说从几分钟到几小时不等,但是做过程序员的人知道,大家其实内心希望有连续型思维,即至少让我把这个模块都写完后再换,不然思路被打断了,所以最好是按照模块或者较长的固定时间作为切换点。一旦结对双方习惯了这种做法,并且适应了与自己结对的程序员,结对者会自动进入这种流程,很自然地来互换角色。
挑选人员
结对编程过程中,编码不再是私人的工作,而是一种公开的“表演”。程序员的代码、工作方式、技术水平都变得公开和透明。
结对编程不容易做好,需要明白哪些人适合,哪些人不适合。
什么样的人不适合作为 Pair Programming 成员?我列举了以下几点:
- 不能容忍别人的意见:既然不能容许别人提出意见,那么怎么共同工作呢?
- 我总是对的:没有人总是对的,结对就是为了互相纠正错误,共同进步。
- 我吃盐多过你吃米:这种心态要不得,谁都会有自己的弱项。
- 太过自卑:意味着不会提出自己的意见。
- 没主见:也会导致不善于提出自己的意见。
- 没责任心:即便懂,也会不提意见。
什么样的人适合作为 Pair Programming 成员?
结对编程对参与的程序员提出了更高的要求,这种要求不是技术水平,也不是学历水平也不是工作经验,这种要求是对一个人心智,道德,修养的更高要求。
结对编程人员应该具备这样的一些基本素质:诚实、公正、开明、勇敢和谦卑。在这些素质的基础之上,才是对技术水平、能力和天分的要求。具备这些素质才能克服“四怕(怕自己看上去傻、怕被认为没用、怕自己变得不重要、怕自己不够好)”,才能成为一名成熟和专业的程序员。
作用
结对编程主要对三个层面存在作用,包括企业管理、开发过程、开发人员自身。
企业管理:
- 结对编程有助于更为高效的交流,有利于程序员之间的相互学习和经验传递
- 结对编程性价比更高
- 结对编程能更好地解决开发人员流动问题
开发过程:
- 结对编程可以交付更好的设计质量和代码质量
- 结对编程具有更强的问题解决能力
开发人员自身:
- 结对编程让程序员一起工作,能够为他们提供更多的信心
- 结对编程时能带来更强烈的满足感
如何做好结对编程
前面说了很多结对编程的概念,那么怎么做好结对编程工作呢?我觉得主要有以下几点:
- “驾驶员”负责编写设计文档,进行编码以及执行单元测试等开发流程。
- “领航员”负责审阅“驾驶员”编写的文档,监督“驾驶员”编写代码,并且需要考虑单元测试用例的覆盖程度,帮助“驾驶员”解决具体的技术问题。
- “驾驶员”和“领航员”不断转换角色,不要连续工作超过一小时,每一小时休息 15 分钟。“领航员”负责控制开发时间。
- 主动参与:虽然每个任务都有具体的“驾驶员”,但是“领航员”不能以旁观者的心态工作,任何一个任务都是两个人的责任,也是所有人的责任,不存在“这是我的代码”、“那是你的代码”,只有“我们的代码”。
- 结对双方应该只存在水平上的差距,不存在级别上的差距,一组成员尽管可能大家的级别资历不同,但不管在分析,设计或编码,双方都拥有平等的决策权力。
- 多小组之间可以互换搭档,但是每个任务的负责人应该继续留在该任务的小组里。
- 如果小组中的一人请假,另一个人尽量不要写生产环境的代码。
- 对于加班这种事,结对成员应该一起加班。
其他注意事项
- 如果两个程序员不在同一个办公地点工作,可以通过共享桌面软件来实现结对编程。这种方法面临的问题主要是网络延迟和工作时间段不一致这两个差异。
- 结对编程是一个渐进的过程,不是很快就能做到的,实质上是一个相互学习、相互磨合的渐进过程。开发人员需要时间来适应全新的开发模式,刚开始的时候很可能效率不如单个人独自工作,但适应之后,开发质量、开发时间都应该比独自一人有大幅度的改善。
- 更好地做好结对编程:
对于团队来说这是个很大的变化
很少有工作能像结对编程这样对团队造成巨大影响。在传统的工作模式中,开发者会独自“进入状态”:带上耳机、打开音乐,手边就是咖啡和零食。大部分程序员都不会在工作中和同事进行大量沟通,他们需要一段时间来适应对话状态!
精神高度集中
这是结对编程有效的必备秘籍:专注、专注、专注!如果你正在结对编程,那就不可能一边还在看网页,或者回复邮件了,你身边还坐着一位呢。
疲惫
结对编程需要的专注和紧张程度高于大部分人的日常工作强度。结对编程会把员工从舒适区拽出来,并且进一步锻炼员工的专注能力。但是无论员工多么擅长结对编程,都可能会到达极限。Kent Beck 认为绝大多数程序员每天的结对时间不能超过五或者六个小时。
大部分成员都没有完全具备所需要的软技能
人类不是生来就有同理心和超强的社交技能的。如果你在工作中和同事交流很少,那么你在这方面的技能可能就会弱一些。想象一下,和一个缺乏社交技能的人紧密合作一整天是什么感觉。或者另一个场景,想象一下作为新手和一个不耐烦的老手一起编程的感觉。结对编程的两方都需要很好的耐心,要能够互相理解。
所有的改变都很困难
所有的变更管理专家都会告诉你,要求他人改变做事的方式会立刻激发恐惧反应,首先我们需要让他们理解为什么需要改变,以及改变只有所带来的好处。
结对编程实施步骤
< 阶段 1-Pair 形成 >
团队接到一个较大的需求后,经过讨论并分解任务成一个个粒度适中的任务。任务的粒度一般在几小时到一两天这种级别,涉及的代码规模大约是几行到几个类 / 函数。每个任务都需要安排一个 Owner 作为责任人,这和传统的单人开发模式相同。但是,Owner 的产生一般不是由 Scrum 教练分配指定的,而是团队成员自发地去协商选择适当的任务。Owner 拿到任务以后会从团队中找一个支持者,形成 Pair。这也是一个自发协商过程,没有强制指定,也没有固定的搭档,这样形成的 Pair 一般来说配合最默契,也最适合相应任务的执行。
< 阶段 2- 初始讨论 >
Pair 形成以后,一般是由 Owner 先分析需求、设计测试,并初步完成设计思路。这个阶段搭档可以暂时先不了解需求。然后 Owner 向搭档介绍需求和自己的设计思路,搭档需要帮助 Owner 理解需求、设计测试,对设计方案提出反馈意见,或者提出新的设计。讨论的理想结果是两人达成一致形成最终的设计方案,如果两个人分歧较为严重,不能达成一致的时候则需要更多的人参与,比如可以举行一个小型的技术讨论会议,把讨论范围扩大到整个团队。
< 阶段 3- 具体实现 >
这一阶段是根据讨论得出的设计方案开始编程实现。如果让两个人一直保持一起工作,特别容易让人疲倦,并且感觉不自在,进而抵触结对编程。所以建议实践过程中,除了少数情况,基本上不要采用全程结对工作,而是由 Owner 一个人完成。当然,如果 Owner 遇到了一些设计上考虑不完善的地方,他可以随时和搭档讨论。
< 阶段 4-Review>
具体实现完成以后,Owner 会邀请搭档检查自己的工作。这个过程一般是借助版本控制工具对比代码改动,搭档从实现的角度审查实现是否符合设计,有没有可以直接观察到的 bug 和潜在的问题。如果发现问题并讨论确认,Owner 再做相应的改动,再一次提交审查。只有当搭档提不出问题之后,Owner 才能提交代码。
使用案例
教育学
案例 1
2001 年,美国北卡州的 Laurie Williams 做了一个实验,该实验主要用来研究下面两个课题:
1)结对编程的作用。
2)积极协作学习的重要性。
Williams 及其助手调查了学生学习兴趣和学习成绩,结果发现按照传统教学模式(即编程是一个人的事情,如果和别人交流会被认为是作弊),很多学生在第二年就会选择别的专业,放弃计算机科学专业。同时还发现,运用结对编程学习的同学的成绩比独立学习的学生成绩好很多,而且学习兴趣更浓。2006 年美国科罗拉多州刘易斯堡学院 Brian Hanks 经过调查和实验得到大多数学生对结对编程持欢迎态度,他们认为结对编程可以很好的增进同学之间的关系,更好的加强同学之间的交流,有利于高效的解决难题。
案例 2
2005 年,美国乔治亚洲大学的 Lan Cao 和波士顿大学的 pengxu 在第 38 届 Annual HICSS 会议中发表“结对编程的组合方式”一文,该文中指出,通过对十对不同组合(两对能力强—能力强、两对普通—普通、五对能力强—新手和一对普通—新手),在教授指导下开发软件项目进行研究,用事先准备好的评价模型对时延结果进行分析。
实验结果显示,两对能力强—能力强组合顺利完成开发,并通过了大部分测试用例,录像显示在开发过程中彼此交流很多,通过问卷还了解到他们被认为搭档起很大作用,很享受这样的编程方式,组合双方的编程能力都得到提高。两对普通—普通组合得到了两种相反的结果,其中一组表达了对结对的喜欢,而且认为搭档起很大作用,同时对他们的代码很自信,最后通过 78% 的测试用例。但是另外一组则得到其中一个人喜欢结对编程,并且认为达到起作用很大,而另一个人则表示不喜欢结对编程这样的工作方式,同时认为搭档作用不大。
五对能力强—新手组合也得到不同的结果,有三组失败,没有结对完成所给的项目。而在完成项目的两组组合中发现:能力强的学生都反映他们不喜欢这样的方式,认为他的搭档基本上不起作用,反倒要他们不停的讲解代码给新手听,而新手则反映他们非常喜欢这样的工作方式,认为搭档作用非常大,同时新手的编程能力得到显著的提高。综合以上实验结果表明在工作中应该根据需求合理采用结对组合方式,尤其是普通—普通这个组合。
2008 年 lauriewilliams 经过实验研究又在第一届敏捷开发会议中发表“在课堂上实施结对编程的 11 个建议”一文,该文中作者通过实验对在课堂上实施结对编程出现的问题进行分析,然后对如何结对,结对的环境,学生在结对前应该如何培训,结对过程中教师应该扮演主要的角色等问题都给出了很好的建议。
软件工业界
案例 1
2002 年,美 Thoughtworks 公司的 Amrelsss Amadisy 通过在项目中实施结对编程对结对编程进行研究,通过对计划、提交周期、设计的简单性、测试和重构等方面和单独工作进行对比,验证了结对编程的效率不比单独编程低,而且通过一段时间的结对,程序员之间的交流更多,新员工能更快适应公司环境,对程序员个人提高也更快。同时他对结对编程的实施提出了一些重要意见。
案例 2
2003 年,Frank Padberg 和 Mathias M. 发表“分析结对编程成本和收益”一文。该文中介绍作者详细分析了结对编程的成本估算,通过和单独开发进行对比,得到结对编程具备比个人更高的效费比。
2008 年 Grant Braught 等在 ACM SIGCSEBulletin 上发表了“结对编程对个人编程能力作用”一文。Grant Braught 通过对团队实施结对编程研究结对编程在提高个人开发能力方面的作用。同时提高不仅结对编程不会因为两个人一起编程而浪费时间,而且会降低软件开发失败的风险。
我的理解
根据我的了解,国内企业采用极限编程的还很少。这是因为结对编程在实际开发过程中没有得到理想的应用。一方面是由于极限编程理论本身还不是很丰富,仍然处于完善和改进阶段,虽然一些国内软件企业开始尝试使用极限编程,也仅是使用其中他们认为比较重要的几个实践,抛弃了其他一些特性,其中就有结对编程。另一方面,有关结对编程的绝大多数实验都是在大学环境中进行的,在实际软件开发中真正实施和系统化的验证的实例较少,况且结对编程在表面上给人一种浪费一个开发人员的感觉,关于结对编程方法实施的具体效果进行研究和阐述的文章也很少,所以结对编程在国内外企业中没有得到普遍实施。
我认为如果想要全方面推广结对编程,首先需要通过大学校招解决人员素质问题,只有聚集一群优秀的学生,你才能够有机会从零开始给他们灌输极限编程、结对编程思想,因为软件工程本身就是具有可改变性的,所以如果你选择的是具有几年工作经验的员工,那么他内心本身会可能存在抵触,也可能会在工作压力情况下选择放弃结对编程,转为形式主义。此外,我觉得最好是由主管自己带头进行结对编程示范,这样才能够更有说服力,比较合适的做法是,主管带领一名刚大学毕业的学生,每天将任务进行拆解,讨论清楚后分头执行,每 1 个小时互相检查一下进展情况、互相提出问题,这样长久下去可能会建立比较完整的结对编程体系。
作者介绍
周明耀,2004 年毕业于浙江大学,工学硕士。13 年软件研发经验,近 10 年技术团队管理经验,4 年分布式计算、大数据技术经验。出版书籍包括《大话 Java 性能优化》、《深入理解 JVM&G1 GC》、《技术领导力 - 码农如何才能带团队》。个人微信号 michael_tec,个人公众号“麦克叔叔每晚 10 点说”。
感谢郭蕾对本文的策划和审校。
评论