引 言
结 对 编 程 (pair programming) 是 极 限 编 程(XP,eXtreme Programming)和敏捷软件开发方法学的特色实践之一。对于我国学生,组织极限编程活动,采用结对编程方法,有助于沟通能力、口头表达能力的培养,有助于相互学习、相互支持,有助于团队协作能力的培养,有助于提高软件质量和开发效率。因此结对编程实践具有非常重要的意义。
笔者详细分析了结对编程中学生所表现出来的不良现象,并针对这些现象给出相应对策,以改进极限编程活动的效率。
1 结对编程的不良现象
一个项目团队成功或失败的关键原因往往不是技术因素,很多非技术的人为因素在起作用。极限编程活动中,如何组织结对编程就是非常突出的人为因素。笔者曾参与德国波恩大学 2届 XP 活动,在国内组织了 4 届 XP 活动。活动中发现传统软件工程中的一些习惯做法,以及学生的一些习性,导致活动中出现了一系列问题,在价值观、团队行为等多个方面都产生了明显冲突,导致结对编程在国内“水土不服”。
冲突1,传统软件工程中,往往先划分模块,然后个人对模块负责。这种做法看似责任明确,但实际上,项目依赖每个成员,当某个成员离职,该模块就无法维护,导致项目风险增大。此种做法与极限编程所倡导的“代码集体所有权”违背。
代码集体所有制,即每个人都是项目中所有代码的受益人,同时也是责任人。每个人对所有代码负责,而不是仅对自己编写的代码负责;每个人要对所有代码的将来的维护负责;而不是仅对当前运行负责;每个人提交的代码都属于团队,允许他人质疑、修正、重构,甚至抛弃重建。
国内学生大多过度关注个人能力和个人成绩,而往往忽略团队能力和团队成绩,他们往往倾向于独立研究解决问题。独立学习能力往往作为衡量学生个人能力的标尺,从小学到大学的教育都如此,根深蒂固,短时间内难以改变。
冲突 2,传统软件工程中,多人分别完成任务,看似并行工作,效率应该更高,但实际上返工较多。原因是个人独立完成一个模块的设计、编程和测试,实际上往往导致需求误解多、缺乏设计合理性、缺乏测试完备性,最后导致软件质量达不到要求,项目开发效率降低。国内学生常常质疑这样的问题,两个人用一台电脑编程,怎么可能比两人用两台电脑并行编程更有效?
结对 (pair) 是最小的团队。结对编程要求两人自由组成一个结对来完成一项任务,要求坐在一起用一台电脑。两人分别扮演两个角色:正驾 driver 和副驾 co-driver 或领航员,就像汽车拉力赛中两人共同驾驶一部汽车。正驾操键盘,负责编码,副驾掌鼠标,负责指导方向并做代码审查;正驾注意力往往集中在最邻近目标上,如前方 400 米之内的具体目标,而副驾能借助地图( 如模型或文档 ) 来指导更长远目标。两人不断沟通交流,密切协作,共同抵达目标。
两人每小时休息一次并更换角色,直到一项任务完成,任务完成之后,结对解散,对新的任务再组织新结对。一个项目完成后,每个人都应与其它成员至少结对一次。
对于一个项目团队来说,最理想情形是,一个人的成功经验就是整个团队的经验,一个人在某个地方失败或走弯路,整个团队都不会再出现。
冲突 3,传统软件工程教育中,指导教师或项目负责人往往要起过分重要的权威作用。因为学生往往只关注老师如何评价,而往往忽视团队其他成员的意见或建议。当团队成员之间出现错误或不一致,就难以协调自行解决问题,除非指导教师干预。极限编程中,尊重是极限编程核心价值观之一。要尊重每个人的意见,而不仅仅是教师或项目负责人。
2 不良现象分析及对策
文章就结对编程活动中成员所出现的 7 种不良现象进行分析,并给出相应对策。
1)高手单驾,副驾休闲。
编程能力强的学生往往倾向于单独行事,高手单独驾车,很忙很累,而副驾无事可做,导致人力资源浪费。解决对策是坚持每小时更换角色,共同驾驶,共同抵达目标。个人能力有高低差异,高手有责任主动介绍经验和技能,把更多机会给另一方,另一方应主动提出问题,寻求解决,主动驾驶。
2)事后证明。
副驾不同意正驾选择或未达成一致,正驾就独自到达目标,先造成即成事实,“一夜之间”独自解决难题,以此证明自己正确高明。这样对另一方可能造成潜在矛盾,并未达到结对编程之目的。解决对策,副驾作为领航,应先决定做什么,正驾再执行。
3)成功自尊。
很多学生只希望别人看到自己成功的结果,不希望别人看到过程中的多次失败。这种“要面子”心理和“结果证明成功”做法导致过程中交流被动,团队效率降低。解决对策,鼓励失败和失败共享。具体做法是,建立失败表彰机制,鼓励个人发布自己遇到的错误和失败,发布“有效失败”记录,说明发生时间、错误或失败现象以及原因和解决办法,标明撰写人、重写人。并将记录发布在团队网页上,使所有成员能及时看到。“有效失败”的每一个错误或失败都有特色、不重复,对所有成员都有参照价值。对于一个错误,如原因不明,相同错误可能再次发生,对于多次发生的错误需要团队格外重视,如果原因已清楚,相同错误就不应再犯。一名成员发现错误后,不鼓励私下自行解决,因为这样对其它成员并没有经验积累。在每个开发周期之后应累计错误记录次数。对累计次数最多的个人进行鼓励表彰。鼓励失败是极限编程最具颠覆性的特点之一,测试优先和测试驱动开发也有鼓励失败的动机。
4)情面阻碍。
学生在发现别人编码有错误时,不好意思指明,更不好意思修改或重构他人代码,导致错误和缺陷不能及时发现和处理,进一步可能导致项目延误或重大缺陷。解决对策,勇气是极限编程核心价值观之一,要求每个人共同担责,贯彻代码集体所有制,将所有共享代码都看作是自己的编码。项目负责人应明确当发生错误或缺陷时,不仅应追查谁做的编码,还应追查谁可能已经发现了错误而没有说明的责任人。
5)不熟悉难结对。
只与相熟的人结对,而对陌生人难以有效交流,难以组成结对。团队中可能有外国学生,也可能是本科生、研究生混搭,大部分相互间不熟悉,导致部分成员在执行任务时形成隔阂。解决对策,成员应明确与陌生人有效沟通是一种极其重要的能力,应格外重视这种能力的培养,一些集体配合游戏项目有助于成员之间增强交流和协作。
6)个人偏见。
对技术方案见解或意见不一致而产生个人偏见,进而导致对某成员“看不惯”“合不来”,从而采取不合作态度。如果团队中两个重要成员形成个人矛盾,那么整个团队就会受到影响。解决对策,编程是一种创作,创作都带有个人色彩,编程作为软件工程活动,个性发挥应受到限制。
让团队成员知道,可争论,但反对争吵;可公开争论,但反对私下言论和个人偏见。每个迭代周期结束后,成员都应回答“对你帮助最多的同学是谁?”,以促进相互学习,交流经验。
7)延误借口。
学生编程往往要使用别人已完成的编程,但发现别人编程有问题或缺陷,而没有及时地、明确地提出,并以此为借口,延误了自己的任务,并把延误责任推给别人。另一种情形为起初使用他人编程正确,后来他人出于纠错或重构目的而修改了编码,导致自己编码错误。以此为借口,延误了自己的任务。解决对策,项目负责人应明确指出这是不可容忍的行为,成员应明确每个人的编码都会被他人使用。
3 相关讨论
结对编程目前获得广泛关注并给予好评。文献 [3] 通过实践指出结对编程可减少 15% 的开发时间。文献 [4] 说明组织大学生结对编程,获得定性和定量的评价和度量,结果都是积极的。但软件业开发者则提出更多更尖锐问题来探讨。文献 [5] 指出结对编程对于软件工程的好处和缺点,其中大多缺点是针对中国软件开发团队。例如个人编程习惯不同可能导致难以协调;争论中各执己见,互不让步。应关注结对副作用,如谈论内容与工作无关,合伙应付敷衍等现象分析。文献 [6] 给出结对编程中的一些成型的模式,一个结对中的两个角色,正驾和副驾,对于不同人员的行为特征,给出解决办法。最主要的是,在一个结对中,当某人行为出现某种现象时,就应及时转换角色。文献 [7] 探讨了何时结对编程最有效的问题。
前提是具体考虑任务 ( 称为挑战 ) 难度和个人技能之间是否匹配。结对编程有流模式与指导两种成功模式,流模式就是两人技能与任务难度之间都匹配,分工协作完成任务;指导模式是针对新手完成较简单任务,需要老手指导,让新手有机会学到经验。结对编程还有两种不成功模式,“经验浪费”和“不知所错”。“经验浪费”模式是任务太简单,而无需老手指导,此时如果强行结对编程,就会导致浪费人力;“不知所措”模式是另一个极端,任务太复杂或需要太多新知识,最后无力完成。
4 结 语
结对编程在我国仍处于探索阶段。尽管目前存在种种不良现象,但也存在多种途径和方法。(1)活动组织者只要认识到这些不良现象背后的原因,就容易找到合理的解决办法。(2)在活动之初通过培训告知参与者注意事项。(3)在活动中各个迭代周期小结时组织者应及时指出所发现的不良现象。(4)对“失败”鼓励和奖励,这种观念转变也很重要。
参考文献:
[1] Beck K, Andres C. 解析极限编程: 拥抱变化[M]. 2版 雷剑文, 译. 北京: 机械工业出版社, 2011: 42-55.
[2] Martin R C. 敏捷软件开发—原则、模式与实践[M]. 邓辉, 译. 北京: 清华大学出版社, 2003: 9-20.
[3] Cokburn A. The costs and benefits of pair programming[J]. Extreme programming examined, 2000(8): 223-247.
[4] Williams L , Kessler R R, Cunningham W, et al. Strengthening the case for pair programming[J]. Software, IEEE, 2000, 17(4): 19-25.
[5] 陈皓. 结对编程的利与弊[EB/OL]. (2010-03-15) [2013-9-4].