结对编程(Pair Programming)是一种由两名开发者共同完成同一项开发任务的软件工程实践。它不仅能提升代码质量,还能促进知识共享、团队协作和新成员入职。本文将系统介绍结对编程是什么、如何开展结对编程、常见模式、优势、挑战,以及团队在实际落地时可以采用的实践建议。
如今,许多软件开发从业者都听说过结对编程,但它在行业中的普及程度依然参差不齐。原因之一在于,结对编程的收益往往不会立刻显现,而是在中长期的团队协作和软件演进中逐渐释放。另一个原因是,它并不只是“两个人共用一台电脑”那么简单;如果没有掌握正确的方法,很多人初次尝试时一旦感到不适,便很容易放弃。

然而,根据我们的经验,结对编程对团队协作和高质量软件开发都至关重要。
从一开始,我和贝蒂·斯奈德就是搭档。我相信,最好的程序和设计都是由两个人合作完成的,因为你们可以互相批评,发现彼此的错误,并借鉴对方最好的想法。
——让·巴蒂克,最早的程序员之一
所有生产代码都应该由两个人坐在同一台机器前共同编写。
——肯特·贝克
让·巴蒂克是早期计算机项目女性团队成员之一,她们被许多人视为最早的程序员。当时,“程序”这一概念尚未完全成形,也没有榜样或书籍告诉她们该如何编程,但她们已经开始着手编程工作,并选择了结对协作。大约 50 年后,结对编程才成为一个广为流传的概念。直到 20 世纪 90 年代末,肯特·贝克在《极限编程》一书中系统阐述了这一实践。正是这本书将敏捷软件开发实践介绍给了更广泛的读者,而结对编程正是其中之一。
结对编程本质上是指两个人共用一台机器编写代码。这是一种高度协作的工作方式,需要大量沟通。两位开发者在共同完成一项任务时,不仅会编写代码,还会一起规划、讨论和调整工作内容。他们会不断澄清思路,探索不同方案,并最终找到更优的解决路径。
本文第一部分“如何开展结对编程”概述了几种实用的结对方式,适合想要开始结对编程,或希望提升结对编程能力的读者。
第二部分和第三部分“结对编程的优势”与“结对编程的挑战”将深入探讨结对编程的目标,以及如何应对那些可能阻碍目标达成的问题。如果你想更好地理解为什么结对编程对软件质量和团队协作有益,或者想获得一些改进建议,这两部分会很有帮助。
第四部分和第五部分“结对,还是不结对?”和“说到底,为什么要这样做?”将总结我们对结对编程在团队流程和协作大局中所扮演角色的看法。
如何开展结对编程
常见结对编程模式
驾驶员与导航员
“驾驶员”和“导航员”是经典的结对编程角色划分,也可以灵活应用到许多结对编程方法中。
驾驶员是坐在“方向盘”后的人,也就是操作键盘的人。TA 专注于完成当前的小目标,暂时不去处理更宏观的问题。驾驶员在操作过程中应尽量边做边说,让搭档了解自己的思路。
导航员则处于观察者的位置,在驾驶员编写代码时持续审视代码,提供指导并分享想法。导航员还会关注更大的问题、潜在漏洞,以及后续可能需要处理的事项或障碍。

这种角色划分的目的,是让驾驶员和导航员从不同角度审视代码。驾驶员的思维更偏向战术层面,关注细节和眼前的代码;导航员则可以从战略层面观察,把握整体方向。
常见流程如下:
首先,设定一个相对明确的任务。
每次只设定一个小目标。这个目标可以通过单元测试、提交信息,或写在便签上的方式来定义。
定期轮换键盘和角色。积极参与的互动可以保持学习热情,也能帮助双方更好地理解和掌握知识。
作为导航员,要避免陷入“战术”思维,把具体编码细节留给驾驶员。你的任务是退后一步,用中期视角补充搭档的战术思维。可以把下一步计划、潜在障碍和想法记录在便签上,等小目标完成后再讨论,以免打断驾驶员的思路。
乒乓式结对
这种方法结合了测试驱动开发(TDD),非常适合边界清晰、可以通过测试驱动实现的任务。

“Ping”:开发者 A 编写一个失败的测试。
“Pong”:开发者 B 编写实现代码,让测试通过。
随后,开发者 B 开始下一个“Ping”,也就是编写下一个失败的测试。
每次“Pong”完成后,可以一起重构代码,然后再进入下一个失败测试。这样就遵循了“红—绿—重构”的流程:先编写一个失败测试(红),再用最少的必要代码让它通过(绿),最后进行重构。
强风格结对
这种方法对于知识传递尤其有用。相关实践者曾对它进行过更详细的介绍。
它的规则是:“一个想法要从你的脑海进入电脑,必须经过别人的手。”在这种模式下,导航员通常是经验更丰富的人,更熟悉当前环境或任务;驾驶员则通常是新手,比如不熟悉编程语言、工具、代码库或业务背景。经验丰富的人主要扮演导航员的角色,引导新手完成实现。
其中一个重要前提是,驾驶员要充分信任导航员,并且能够接受信息不完整的状态。实现过程结束后,再一起讨论“为什么要这样做”以及对方案的疑问。当一方完全是新手时,这种方式可以显著提高结对效率。
虽然这种方法近似于微观指导,但它可以作为一种有效的入职培训工具,鼓励新人主动“边做边学”,而不是被动“边看边学”。它非常适合初始知识传递,但不应过度使用。请记住,最终目标是在一段时间后能够自然切换角色,并逐步退出这种细粒度指导模式。能够做到这一点,才意味着知识传递取得了成功。
从结对编程到结对开发
“结对开发”与其说是一种具体的结对编程技巧,不如说是一种结对编程思维。开发一个用户故事或功能,通常不仅需要编码,还包含许多其他工作。作为结对伙伴,你们要共同负责这些工作。
为了帮助你进入这种思维,下面列出了一些用户故事生命周期中的非编码活动,它们同样可以从结对协作中受益。
规划:我们的目标是什么?
当你们刚开始合作开发某个功能时,不要急于写代码。功能生命周期的早期阶段,是避免浪费资源的绝佳机会。在这个阶段,双方一起审视问题,能够及时发现误解或遗漏的前提,从而节省后续大量时间。
理解问题。 通读问题描述,并互相复述自己的理解。与产品负责人澄清所有疑问或潜在误解。如果团队有“就绪定义”(Definition of Ready),请再次确认启动工作所需的条件和资源是否已经准备齐全。
提出解决方案。 集思广益,探讨解决问题的潜在方案。你们可以一起讨论,也可以先分开思考,再互相展示各自的想法。这取决于解决方案本身的清晰度,也取决于你们各自的思考风格。有些人喜欢独自思考,有些人则喜欢边说边想。如果你们中有人对相关领域或技术不太熟悉,请花些时间互相介绍必要的背景知识。
规划方案。 对于你们选择的方案,需要采取哪些步骤才能达成目标?是否有特定的执行顺序?你们将如何测试?理想情况下,把这些步骤记录下来,可以写在共享文档中,也可以写在便签上。这有助于跟踪进度,也方便在需要他人接手或协助时使用。写下来还有助于记住待办事项——我们常常低估自己会忘记多少事情,有时甚至第二天就忘了。
如果团队希望把结对过程中产生的目标、需求、评审、排期、开发、测试、发布和知识沉淀串联起来,也可以借助 PingCode 这样的智能化研发管理工具,让研发流程中的信息更容易被记录、追踪和复用,从而减少结对协作中的信息断层。
研究与探索
当某个功能需要使用双方都不熟悉的技术来实现时,通常需要先进行研究和探索。这类工作并不适合简单套用“驾驶员—导航员”或“乒乓式”协作模式。例如,两个人盯着同一个屏幕一起浏览搜索结果,通常效率并不高。
在结对开发思维下,可以采用以下方式:
先列出需要回答的问题清单,以便找到合适的解决方案。
分工合作。你们可以分别研究不同问题,也可以分别尝试寻找同一个问题的答案。可以上网搜索,也可以利用公司内部资源,或者阅读双方都不熟悉的新概念资料。
在事先约定的时间段结束后重新聚到一起,讨论并分享各自的发现。
文档
除了代码之外,文档也是需要共同完成的重要工作。你们可以一起思考当前工作是否需要文档。同样,根据具体情况和个人偏好,你们可以共同撰写文档,也可以由一人先写,另一人审核和润色。
文档编写是一个很好的例子,说明两人合作如何相互督促。文档常常被留到最后;当它成为完成项目、获得“完成感”之前的最后一道关卡时,我们很容易选择忽略它,或者草草了事。而两人协作能够让我们正视这些有价值却容易令人厌烦的事情——未来的我们往往会因此感激现在的认真。
结对编程中的时间管理
除了常见的结对方式,还有一些小工具和技巧可以让结对编程更加顺畅。
番茄工作法就是其中之一。它是一种时间管理方法,把工作分解成若干时间段,通常每段 25 分钟,并在时间段之间穿插短暂休息。这种方法几乎适用于前面介绍过的所有结对编程方式,并能帮助你保持专注。结对编程可能很消耗精力,因此设置提醒、定期休息并定期更换键盘会很有帮助。

以下是番茄工作法的实际应用示例:
决定接下来要做什么。
设置一个 25 分钟的计时器,例如使用番茄钟浏览器扩展,或者真的拿一个番茄形状的厨房计时器。
在这段时间内不受干扰地工作。
计时器响起时暂停工作,先进行一次短暂休息,比如 5 到 10 分钟。
完成 3 到 4 个这样的“番茄钟”后,进行一次较长休息,比如 15 到 30 分钟。
请真正利用短暂休息放松身心、补充能量、喝点水或咖啡、上个厕所,或者呼吸一下新鲜空气。避免把这些短暂休息用来处理其他工作,比如回复邮件。
结对轮换
结对轮换是指两位搭档合作一段时间后,其中一人离开当前用户故事,另一人则邀请新成员加入,继续推进工作。留下来的人通常被称为这个用户故事的“锚点”。
轮换的原因之一是现实安排。你的搭档可能生病或休假。或者你们其中一人某天远程办公,但当前工作需要现场完成,例如涉及硬件调试。
另一个原因是让工作内容更加多样化。也许你们两人已经合作了一段时间,因为相处太久而开始出现“幽闭感”。又或者你们正在处理一些枯燥、耗费精力的工作——轮换可以让其中一人休息一下,也让新加入的人带来新的视角和活力。
最后,结对轮换最常见的原因是避免知识孤岛、增强代码集体所有权,并实现更及时的代码审查。结对编程本身已经有助于实现这些目标,但轮换可以进一步提高每一行上线代码平均被审阅的人数。
关于理想的轮换频率,各方意见并不一致。有些人认为每 2 到 3 天轮换一次至关重要,因为这样才能充分传播知识并提升质量。然而,每次轮换都会带来成本。一方面,新加入的人需要时间熟悉工作;另一方面,轮换者本身也需要承担上下文切换成本。如果没有一个稳定的锚点来保证工作的连续性,那么关于问题和解决方案的隐性知识就容易丢失,从而导致返工。对于初级开发者来说,有时让他们在某个主题上停留更久反而更有益,因为这样他们有足够时间深入理解,并让新知识沉淀下来。
在敏捷团队中,“展示与分享”这个说法有不同用法。这里指的是定期举行的开发者例会,例如每周一次的开发者聚会,用于讨论技术债务、经验教训,以及互相介绍重要的新代码等。
因此,需要权衡轮换的成本和收益。假设你们已经拥有高质量的知识共享机制,包括团队“展示与分享”、易读的代码和良好的文档。在这种情况下,坚持高频轮换可能只会略微提升集体代码所有权,却会带来大量摩擦和额外开销。
规划一天
结对编程需要一定的时间安排和日程协调。如果你不花时间考虑和安排这些,之后很可能会遇到麻烦。
每天开始时,先一起查看日程安排。与你的结对伙伴商定当天要合作多少小时,并看看是否需要预留时间参加会议,或处理其他与结对任务无关的事情。如果你们中有人需要独自工作一段时间,请务必保证另一人在对方不在时也能继续推进工作。例如,不要依赖对方的电脑来编程。
如果你白天有会议或其他安排,请设置一个容易注意到的提醒,尤其是在和结对伙伴一起工作时。如果你们团队默认采用结对编程,建议约定固定的“核心编码时间”。这样可以大大简化日程安排。
物理环境
结对编程意味着你们需要在同一张办公桌前共享物理空间、近距离协作。这与各自拥有独立办公桌截然不同。如此近距离的相处需要彼此尊重,并关注对方的需求。因此,花些时间为双方找到一个舒适的工作环境是值得的。
确保你们都有足够空间,必要时清理桌面。
桌前是否能放下两把椅子?把垃圾桶和背包移开。
你们想使用两套键盘,还是一套键盘?鼠标也是一样,一套还是两套?这没有绝对规则,我们建议根据具体情况尝试最合适的方案。影响因素包括卫生习惯、键盘共享的配合程度,以及可用空间大小。
你们是否有外接显示器可用?一台还是两台?如果没有,也可以考虑像远程结对一样设置屏幕共享。在这种设置下,你们每个人都可以使用自己的笔记本电脑键盘。
询问你的搭档是否有任何特殊偏好或需求,例如更大的字体、更高的对比度等。
如果你的键盘或 IDE 设置比较特殊,请先和搭档确认他们是否能适应。也可以看看是否能设置一个简单机制,在需要时快速切换回更标准的配置。
如果团队能够就默认设置达成一致,将会很有帮助。这样你们就不必一次又一次讨论这些细节。
远程结对编程
你的团队是远程办公,还是有成员偶尔在家办公?只要双方都有比较稳定的网络连接,仍然可以进行远程结对编程。
准备工作
远程结对需要一个屏幕共享方案,它不仅要允许你看到对方的屏幕,还要支持控制对方的电脑,以便切换键盘。如今,许多视频会议工具都支持这一功能。如果你的公司已经购买了商业视频会议工具授权,可以先尝试这些工具。此外,也有一些开源的远程控制和视频通话工具。对于带宽较低的场景,可以尝试通过 SSH 使用终端复用工具,或者使用某些主流代码编辑器提供的实时协作扩展。

对于远程团队来说,结对编程之外的任务、文档、日历和日常沟通同样需要清晰承接。如果团队需要一个更通用的项目协作系统,可以使用 Worktile 统一管理任务、项目、文档、IM、目标、日历、甘特图和工时等内容,帮助远程成员减少信息分散带来的协作成本。
实用建议
使用视频。 人们经常通过手势和面部表情交流,因此在共享屏幕的同时看到结对伙伴的视频会很有帮助。一些视频会议方案自带该功能;如果你的工具不支持,可以考虑额外开启一次通话,以便彼此看到对方。
规划和设计。 使用协作式在线可视化工具,尽量还原用纸笔或白板画草图的体验。
改善音频体验。 找一个安静的地方,佩戴质量较好的耳机,最好是带有定向麦克风的耳机。如果确实无法避开噪音,“按键说话”功能也能帮上忙。为了减少外界干扰,降噪耳机也是很好的选择。
应对网络延迟。 长时间操作远程计算机,尤其是在网络延迟明显时,会让人非常疲惫。因此,务必定期更换主控机器,确保每个人都有机会在自己本地、没有延迟的电脑上工作。网络延迟也会影响滚动浏览文件,因为搭档可能难以跟上进度。建议避免在长文件中频繁滚动,可以尝试使用键盘快捷键跳转到文件的不同位置,或利用代码折叠与展开功能。
人的因素
如果你的团队并非全员远程,而只是有一两位成员远程办公,请尽量让远程同事参与办公室里的所有讨论。我们很容易忘记,即使只是坐在同一个房间里,人们也会无意间共享大量信息。
与素未谋面、彼此不熟悉的人远程协作会带来额外挑战。一方面,结对编程是远程团队增进了解的好机会;另一方面,人们也很容易忽略协作中的这一层关系建设。如果确实没有机会见面,可以考虑其他增进了解的方式,比如尝试远程一起喝咖啡。
最后,虽然远程结对可能带来一些挑战,但它也比现场结对更容易保持专注,因为戴着耳机往往更容易排除外界干扰。
一起吃甜甜圈
共同完成任务后,一定要庆祝!击掌庆祝听起来也许有些老套,但它其实是一种可以共同完成的“能量姿势”,能让你精神振奋,为下一个任务做好准备。或者,你们也可以创造自己的庆祝方式,例如用甜甜圈来庆祝职业上的成就。
结对编程中应避免的情况
不同的方法和技巧可以帮助你获得更好的结对体验。下面是一些常见误区,请尽量避免。
走神
结对编程时,请避免阅读邮件或使用手机。这些行为可能会让搭档感到不被尊重,也会分散你们对当前任务的注意力。如果确实需要查看某些内容,请清楚说明你在做什么以及原因。通过安排充足休息时间,并每天预留一些个人时间,确保每个人都有足够时间处理邮件等事务。
微观管理模式
警惕微观管理模式。它不给对方留下思考空间。如果有人不停地给你下达类似下面这样的指令,就可能已经进入了这种模式:
“现在输入 System,点,print……”
“现在我们需要创建一个名为……的新类。”
“按 Command + Shift + O……”
不耐烦
遵循“5 秒规则”:当导航员看到驾驶员做错事、想要发表评论时,至少先等待 5 秒。驾驶员也许已经意识到了问题,如果你立刻出声,可能只是在不必要地打断对方思路。
作为导航员,不要立即指出每一个错误或即将出现的障碍。稍等片刻,让驾驶员自行纠正,或者先把信息记下来稍后再讨论。如果你立刻介入,可能会干扰驾驶员的思考过程。
霸占键盘
注意不要“霸占键盘”:你是否一直控制着键盘,不让搭档也有机会输入代码?
这可能会让双方都感到恼火,也会因为搭档缺少“主动参与”而难以集中注意力。试试前面提到的方法,确保你们经常轮换键盘。

每天结对 8 小时
真正致力于结对编程的团队,有时会每天结对 8 小时。根据我们的经验,这种做法不可持续。首先,它会让人精疲力竭。其次,在实践中也并不现实,因为除了编码之外,还有许多其他事情要做,例如查看邮件、一对一沟通、参加会议、研究与学习等。因此,在规划一天工作时请记住这一点,不要期待一天中 100% 的时间都能一起编码。
没有所谓“唯一正确”的方法
结对编程有很多种方式,并不存在所谓“唯一正确”的方法。它取决于你的编程风格、性格、经验、具体情境、任务类型以及其他诸多因素。最终,最重要的问题是:你是否从中获得了预期收益?如果没有,那就尝试其他方法,反思、讨论并调整,直到获得预期效果。
结对编程的优势
结对编程有什么好处?理解它的潜在优势非常重要,这能帮助你决定何时进行结对编程、如何做好结对编程,以及如何在遇到挑战时激励自己坚持下去。结对编程可以帮助你实现软件质量和团队协作方面的主要目标。

那么,结对编程究竟如何帮助你实现这些目标呢?
知识共享
让我们先从结对编程最显而易见、也最没有争议的优势说起:知识共享。两个人共同编写同一段代码,有助于团队在日常工作中交流技术知识和领域知识,避免知识孤岛形成。此外,当两个人共同理解和讨论问题时,找到理想解决方案的概率也会大大提高。不同的经验和视角能够帮助我们考虑更多可能方案。
实用建议
即使你对相关技术或领域一无所知,也不要回避结对编程。如果你一直停留在自己最熟悉的领域,就会错过学习新知识的机会,也无法把知识传播给团队。
如果你发现某个团队成员总是专注于相同主题,不妨鼓励他们尝试不同主题,以拓展专业能力。此外,还可以创建一个技能矩阵,列出团队中的技术主题和业务主题,以及每个人在各个领域的优势与不足。把矩阵贴在团队区域的墙上,大家就可以一起努力,让知识分布更加均衡。
反思
结对编程迫使我们讨论方法和解决方案,而不是只在脑海中思考。把想法说出来并解释清楚,能促使我们反思自己是否真正理解了问题,或者是否真的找到了好的解决方案。这不仅适用于代码和技术设计,也适用于用户故事及其所带来的价值。
实用建议
结对编程需要彼此信任,才能营造一种双方都能自由提问、坦诚表达不理解之处的氛围。因此,在结对编程中,建立团队内部关系非常重要。务必安排时间进行定期一对一交流和反馈。
保持专注
两个人一起工作时,更容易采用结构化的方法:你们都必须明确表达自己为什么要做某件事,以及目标是什么。独自工作时,人更容易分心。例如,你可能会不经思考地“快速”尝试不同方法,然后几个小时后才发现自己陷入了无意义的探索。搭档可以防止你陷入这种状态,帮助你聚焦于当前任务或用户故事真正关键的部分。你们可以相互提醒,保持方向。
实用建议
一起制定计划。讨论手头任务,思考为了达成目标需要采取哪些步骤。把每个步骤写在便签上;如果是远程办公,可以在工单管理系统中创建子任务。按顺序整理好,然后逐一完成。也可以尝试结合番茄工作法,争取在一个番茄钟内完成一个目标。
永远不要忘记:沟通是关键。要坦诚交流你们正在做什么,并要求对方解释自己的思路。
随时随地进行代码审查
当我们结对工作时,有四只眼睛同时关注细节和整体,这样就能在过程中发现更多错误,而不是等工作完成后才发现。
重构始终是编码过程的一部分,因此也是结对编程的一部分。当身边有人时,改进代码会更容易,因为你们可以讨论实现方法、命名以及设计选择。
事后代码审查存在一些缺点。我们将在后面的“结对,还是不结对?”部分中更深入地探讨这一点。
实用建议
互相提问。提问是理解当前工作并找到更好解决方案的最有力工具之一。如果代码对你们中某个人来说难以阅读或理解,那就尝试用更容易理解的方式表达。
如果你觉得已经结对编写过的代码还需要更多审查,不妨反思一下你们是否可以改进结对方式。你是否在结对过程中没有提出所有问题和疑虑?为什么会这样?你们需要做出哪些改变?
结合两种思维模式
正如前面在描述经典“驾驶员/导航员”模式时提到的,结对编程允许你从不同角度审视代码。驾驶员通常处于更“战术”的模式,关注细节,也就是当前这一行代码。导航员则更具战略视角,着眼于整体方向,并把后续步骤和想法记录在便签上。一个人能同时兼顾这两种思维模式吗?恐怕很难。将战术视角和战略视角结合起来,能够提高代码质量,因为它既能让你关注细节,又能让你把握全局。
实用建议
记得定期轮换键盘,从而切换角色。这有助于你放松身心,避免厌倦,并练习两种不同的思维方式。
作为导航员,要避免陷入“战术”思维,把具体编码细节留给驾驶员。你的任务是退后一步,用中期视角补充搭档的战术模式。
集体代码所有权
集体代码所有权摒弃了模块个人所有权的概念。代码库归整个团队所有,任何人都可以修改任何部分。
——马丁·福勒
结对编程确保每一行代码至少被两个人看过。这提高了团队中任何成员都能放心修改代码的可能性。与单人编程相比,结对编程还能让代码库更加一致。
实用建议
单靠结对编程并不能保证实现代码的集体所有权。你还需要确保成员会轮换到不同的搭档和代码区域,以防止知识孤岛形成。
降低团队在制品数量
限制在制品数量是看板的核心原则之一,旨在提升团队协作效率。设定在制品数量上限有助于团队专注于最重要的任务。如果团队设置了在制品数量限制,整体生产力通常会提高,因为多任务处理不仅会降低个人效率,也会降低团队效率。尤其是在大型团队中,结对编程可以限制团队并行处理的任务数量,从而提高整体专注度。这有助于确保工作持续推进,并及时解决遇到的障碍。
实用建议
将团队在制品数量限制在团队中可形成的开发者结对数量之内,并在团队空间中公开展示;如果远程办公,则可以在在线项目管理工具中展示。在接受新任务之前,请务必留意这一限制。在制品数量限制所带来的约束,可能会自然推动你们养成结对编程的习惯。
快速完成新成员入职
由于结对编程有利于知识共享,因此可以帮助新团队成员快速融入团队。新成员可以在搭档帮助下了解项目、业务和组织。团队人员变动会影响团队运作,人们也需要时间彼此熟悉。结对编程可以最大限度减少这种影响,因为它迫使人们进行比单独工作时更多的沟通。
实用建议
仅仅把新员工安排进结对编程,然后期待他们“神奇地”融入团队并完成入职,是不够的。务必在他们第一次结对编程之前,向他们介绍整体框架和更广泛的背景信息,并预留额外的入职时间。这能让他们更容易跟上进度,并在结对过程中做出贡献,从而获得最大收益。结对编程时,请尽量使用新成员自己的电脑,以确保他们之后也能独立完成编程工作。
制定一份包含待讲主题的入职计划。对于某些主题,可以安排专门培训;对于其他主题,新团队成员可以带着这份计划在结对编程中学习。如果某个主题已经在结对过程中讲解过,就可以在清单中勾选。这样,团队中的每个人都能清楚看到入职进度。
结对编程的挑战
结对编程虽然有很多好处,但也需要练习,而且一开始未必顺利。下面列出了一些团队常遇到的挑战,以及相应的应对建议。遇到这些挑战时,请牢记结对编程的好处,并记住你为什么要进行结对编程。明确你希望通过这一实践达成什么目标非常重要,只有这样,你才能据此调整实践方式。
结对可能令人疲惫
独自工作时,你可以随时休息,需要时也可以让思绪放松片刻。而结对工作会迫使你长时间保持专注,并寻找与对方节奏和思维方式的共同点。专注力的提升是结对工作的优势之一,但它也可能让结对过程变得紧张而疲惫。
应对方法
充足休息是应对这一挑战的关键。如果你发现自己经常忘记定期休息,可以尝试设置闹钟,例如每小时休息 10 分钟。也可以使用番茄工作法等时间管理技巧。不要错过午休时间:离开电脑屏幕,好好休息。无论是否结对编程,休息都至关重要,而且能够提高工作效率。
防止疲劳的另一个重要方法是不要每天结对 8 小时,最好将结对时间限制在每天最多 6 小时。定期轮换驾驶员和导航员角色也有助于保持精力。

密切合作可能很困难
长时间与他人密切合作会带来压力。你需要持续沟通,而这需要同理心和人际交往能力。
你们在技巧、知识、技能、性格、外向程度或解决问题方式上可能存在差异。某些组合可能不太契合,导致合作初期并不顺畅。在这种情况下,你们需要投入一些时间改善合作,让它成为一次互惠互利的学习经历,而不是一场争执。
应对方法
在结对编程开始前进行一次简短对话,可以帮助你们了解彼此的风格差异,并制定相应的调整方式。第一次结对可以从这样的问题开始:“我们希望如何合作?”“你更喜欢哪种结对方式?”了解自己的工作方式和高效状态固然重要,但也不要排斥其他方法——你也许会发现一些新的可能。
一天的结对结束后,可以互相进行一轮反馈。如果你觉得给对方反馈很困难,不妨把它看作一次小型回顾。反思你们在结对过程中的感受:你们是否保持专注?是否感到疲惫?哪些方面让你们觉得舒适,哪些方面让你们不适?你们是否经常轮换键盘?是否达成了目标?下次有没有什么想尝试的做法?最好尽早养成这种习惯,这样当问题出现时,你们已经熟悉如何给出反馈。
有许多优秀的培训课程和书籍可以帮助你处理人际冲突和困难,例如如何进行艰难对话。
团队应当共同面对挑战,而不是把冲突留给个人解决。例如,你可以组织一次关于结对编程的研讨会,讨论如何共同应对困难。研讨会开始时,先收集大家眼中结对编程的益处,以便了解彼此的期待。随后,收集每个人在结对编程中遇到的挑战。接下来,团队可以一起思考哪些措施有助于改进。你还可以收集团队成员的敏感点:在结对编程中,什么事情会让你立刻感到不舒服?
会议打断工作
你是否经历过连续几天开会,却感觉什么也没完成?这种情况几乎每个交付团队都会遇到。会议对于讨论、计划和确定开发任务固然必要,但另一方面,它们也会打断工作流。当团队采用结对编程时,过多会议会造成更严重的后果。如果每位结对成员的会议时间各不相同,干扰就会成倍增加。
应对方法
一种方法是限制会议发生的时间段。例如,定义核心结对时间,在这个时间段内不安排会议;或者制定类似“中午以后不再开会”的规则,为非会议工作留出完整时间。
此外,也值得审视会议时长和会议总数。你们真正需要哪些会议?这些会议的目标是什么?如何提高会议质量,例如通过充分准备、有效引导和清晰议程?
但有一点可以肯定:会议总会存在。那么,如何在结对编程中应对它们?在结对开始前,一起查看日程安排,确保有足够时间开始工作。如果有会议,可以考虑结对参加。也可以依靠产品负责人或其他非结对成员,帮助团队在核心结对时间段内减少干扰。
技能水平不同
当两个经验水平不同的人围绕某个主题合作时,往往会导致对彼此贡献程度的错误假设,或者因节奏不同而产生挫败感。
应对方法
如果你的搭档在这个领域更有经验,不要想当然地认为他们一定最了解情况。也许在解释做事方式的原因时,他们也会获得新的启发。询问“如何做”和“为什么这样做”可以引发富有成效的讨论,并找到更好的解决方案。
如果你的搭档在这个领域经验较少,也不要以为他们无法为解决方案做出贡献。你可能正受限于自己的惯性思维,而不同视角或许能帮助你找到更好的方案。此外,记住,解释一个概念本身就是绝佳机会,可以检验你是否真正理解并深入思考过它。
了解不同学习阶段,有助于理解人们从新手到专家的成长过程。相关实践者在一次关于高效团队模式的演讲中,对这一点做过精彩阐述。他引入了德雷福斯技能习得模型,用以理解不同学习阶段,以及这些阶段在结对学习背景下如何组合。
权力关系
处理权力关系可能是这份清单中最困难的挑战之一。结对编程不可能发生在完全没有层级结构的环境中。这种层级结构既可能是正式的,例如经理与下属之间的关系;也可能是非正式的。非正式层级结构包括但不限于:
初级开发者与资深开发者。
非男性与男性。
职业转型者与计算机科学专业背景者。
有色人种与白人。
以上只是部分例子。权力关系是流动且相互交织的。当两个人建立关系时,多种权力关系可能同时发挥作用并相互重叠。为了更好理解权力失衡如何影响结对关系,下面列出一些示例:
在结对编程中,一个人霸占键盘,不给搭档留下空间,完全主导了编程过程。
一个人始终保持教学姿态和教学语气。
一方不听另一方意见,并轻易否定对方建议。
有时,将这些情况与层级结构联系起来并不容易,你可能只会觉得彼此“不合拍”。但问题根源往往在于双方之间的不平衡。
有实践者曾围绕这一主题进行过系统分享,并更广泛地探讨了敏捷开发中的权力关系。
应对方法
解决这一问题的第一步,是处于权力优势一方的人承认并正视自己的位置。只有这样,你才能诚实反思自己与搭档的互动,以及权力关系如何影响这些互动。试着思考自己的立场和处境:你可以采取哪些积极措施来减少权力失衡?
认识这些差异,并调整自身行为以改善协作,并不容易。这需要大量自我反思。一些培训可以帮助个人或团队做到这一点,例如反偏见培训或盟友技能培训。
在大量未知中结对
当你们共同研究一个庞大课题,而双方都不知道如何解决问题时,传统结对编程模式往往不再奏效。例如,你们第一次使用某项技术,或者尝试一种新的方法或模式。在某些情况下,共同研究和实验确实有效;但有时也会令人沮丧,因为每个人理解事物运行机制的方式不同,阅读和学习速度也不同。
应对方法
当存在大量未知因素时,例如你正在使用一项新技术,不妨先进行一次探索性验证(Spike),在正式开始实现之前,先了解相关主题和技术。别忘了与团队分享你的发现,可以组织一次知识交流会,绘制一些图表,并发布到团队空间中。
在这种情况下,请记住采用结对开发思维,而不是狭义的结对编程。分开研究是可以的,前提是你们先商定好需要共同回答的问题。
没有独处时间
前面我们提到,持续不断的交流非常消耗精力。大多数人一天中也需要一些独处时间,对于性格内向的人来说尤其如此。
独自工作时,我们通常会自然地抽出时间深入研究某个主题,或在需要时进行学习。但在结对编程中,这可能会感觉像是对工作流的打断。那么,如何在需要时抽出时间独自学习呢?
应对方法
再次强调,不要每天结对 8 小时。和团队商定核心编码时间,并将结对时间控制在每天最多 6 小时。你可能还需要安排几个小时的自主学习时间。
当两个人都感觉自己没有足够的共同知识来解决某个问题时,可以先分开阅读资料,然后分享结果,再继续实现。
轮换导致上下文切换
知识共享是结对编程的优势之一,前面也提到,轮换可以进一步增强这种优势。但另一方面,过多轮换会导致频繁的上下文切换。
应对方法
在轮换频率与新搭档充分理解用户故事背景、有效做出贡献之间找到平衡。不要为了轮换而轮换,而是思考共享特定背景信息是否重要,以及为什么重要,并给予它足够时间发挥作用。
结对需要脆弱性
结对编程需要坦诚相待。这意味着分享你知道的一切,也分享你不知道的一切。这对我们来说很难。程序员应该很聪明,非常非常聪明。大多数人看到我们做的事情都会说:“我永远也做不到。”这让我们觉得自己有点特别,也给了我们一种自豪感,而自豪感会让我们变得刀枪不入。
——汤姆·豪利特
结对编程时,很难坦然承认自己不懂某些东西,或者对某个决定并不确定。尤其是在“10 倍工程师”这类神话层出不穷的行业里,我们往往会根据彼此使用的编程语言,或五年前做出的设计决策来评判对方。
脆弱性常常被等同于软弱。在大多数现代文化中,展现强大才是常态。但正如研究者布琳·布朗在多次演讲和著作中阐述的那样,脆弱性实际上是创新和变革的重要因素。
脆弱性是创新、创造力和变革的源泉。
——布琳·布朗
应对方法
展现脆弱需要勇气,也需要创造一个让人们感到更安全、更愿意表达脆弱的环境。归根结底,这关乎建立彼此信任的团队,包括定期一对一沟通、反馈机制,以及鼓励提问的文化等。
对于团队中拥有更大权威的人来说,展现脆弱往往更容易,风险也更小。这种权威可能来自个人影响力,例如他们本身就备受尊敬;也可能来自制度性位置,例如他们拥有“技术负责人”这样的头衔。因此,这些人率先示范、树立榜样,使脆弱性表达成为一种正常行为,对于让其他人也能更安全地展现脆弱至关重要。
说服经理和同事
结对编程倡导者经常很难说服经理或同事,将结对编程作为团队日常工作的一部分。
应对方法
说服别人相信结对编程有效,并没有简单秘诀。关键在于先花时间讨论,确保每个人对它有一致理解,例如共同阅读这篇文章。然后找到尝试的方法:可以先从一对结对程序员开始,让他们分享经验;也可以提出一次团队实验,例如“接下来的两个迭代默认采用结对编程”。务必安排反馈和回顾机会,分享哪些方面进展顺利,哪些方面遇到了困难。
归根结底,你不能强迫别人接受某种实践,而且这种实践也并非对每个人都有效。你最终可能只能和团队中的一部分成员进行结对编程,至少初期如此。根据我们的经验,让人们接受这种实践的最好方式,是让他们经常接触它,亲身体验团队成员在结对编程中获得的收益和乐趣。
在这种情况下,最常被问到的问题是经济效益:结对编程是不是只是让成本翻倍?它是否真的物有所值,因为它能提升质量并带来团队收益?确实有一些研究探讨过这个问题,其中有些研究经常被引用来证明结对编程的价值。然而,我们对试图“科学证明”结对编程有效的做法持谨慎态度。软件开发是一个充满变化和不确定性的过程,除了代码行数之外,还有许多难以比较和衡量的成果,例如分析、测试和质量。坚定反对结对编程的人,总能找到方式质疑任何旨在证明开发效率的“科学”实验的可复现性。归根结底,你需要证明它对你有效——而唯一方法,就是在你自己的环境中进行尝试。
结对,还是不结对?
我们的经验清楚表明,结对编程是可持续地创建高质量、可维护软件的关键实践。参见前文“结对编程的优势”部分。然而,我们也不认为教条地、始终采用结对编程一定有益。结对编程对你究竟有多有效,应该采用多少,以及适用于哪些任务,都可能因人而异。我们发现,将结对编程设为团队的“合理默认”做法很有帮助,然后在需要例外时再进行讨论。
下面来看几个例子,在这些情境中,平衡结对的方式和时机很有帮助。
枯燥乏味的任务
有些编码任务很“枯燥”,例如它们只是按照定义明确的样板方法完成一些重复工作。那么,也许不需要结对编程?如果整个团队都熟悉这种方法,或者这种方法很容易掌握,知识共享似乎就没那么重要。并且,由于这种成熟模式过去已经成功应用,实时审查的作用似乎也更小。所以,是的,也许你确实不需要结对编程。
然而,请务必记住,重复性工作可能是糟糕设计的信号。结对编程可以帮助你找到处理枯燥代码的合适抽象方式。此外,当你的大脑进入“这很简单”的自动模式时,也更容易遗漏关键信息或犯粗心错误。
“我真的可以独自完成这件事吗?”
对于刚入门的程序员来说,结对编程有很多好处,因为它提供了一个相对快速地向经验丰富团队成员学习的机会。然而,初级程序员在结对编程时也可能会怀疑自己的能力:“我真的能独立完成吗?”他们也可能因此错过学习如何独立解决问题的机会。我们都会经历挫折,也都会在调试和错误分析过程中进行一些无人指导的尝试,而这些最终都会让我们成为更优秀的程序员。亲身经历问题,往往比别人提前告诉我们会遇到什么问题更有效。
有几种方法可以应对这种情况。一种方法是让初级程序员时不时独立工作,并安排一位导师定期检查和进行代码审查。另一种方法是让团队中经验较少的程序员彼此结对。他们可以一起寻找解决方案,并且比独自编写代码更快摆脱困境。最后,如果你是结对中经验更丰富的程序员,请确保大部分时间扮演导航员角色。给经验较少的程序员一些空间,让他们解决问题。有时候,遇到难题需要耐心等待,而不是提前指出答案。
代码审查 vs. 结对编程
结对编程的优势在于它的即时性:当审阅者就坐在你旁边时,你不可能忽视他或她。
——杰夫·阿特伍德
许多人认为,只要存在代码审查流程,就足以作为不进行结对编程的理由。我们并不认同代码审查是结对编程的理想替代方案。
首先,通常存在一些因素会导致代码审查草率或流于表面。例如,当程序员和审查者在没有明确说明的情况下过度依赖彼此:程序员可能会推迟一些小决策和改进,认为问题会在审查中被发现;而审查者则依赖程序员的勤勉,信任他们的工作,而不再仔细检查代码。另一个因素是沉没成本谬误:我们通常不愿意对团队已经投入大量时间完成的成果进行返工。

其次,代码审查流程可能会打断团队工作流。审查任务需要有人切换上下文。因此,代码审查越频繁,对审查者的干扰就越大。然而,为了确保小变更能够持续集成,代码审查又应当频繁进行。这样一来,审查者可能成为集成和部署的瓶颈,从而增加时间压力;而时间压力又会降低审查效果。
通过持续集成和持续交付,我们希望通过频繁交付小块变更来降低风险。最初,这意味着采用主干开发模式。在主干开发模式下,延迟代码审查的效果更差,因为代码变更无论如何都会立即合并到主分支。因此,结对编程和持续集成是相辅相成的实践。
我们看到一些团队行之有效的做法是:默认结对编程,但在必须不结对修改生产代码的特殊情况下,使用拉取请求和代码审查。在这种模式下,团队应密切监控拉取请求的生命周期,确保其不会持续过久,从而保证持续集成的有效性。
说到底,为什么要做结对编程?
我们讨论了很多结对编程的好处,但也花了更多篇幅讨论它的挑战。结对编程需要掌握许多不同技能才能做好,甚至可能影响团队中的其他流程。那么,为什么还要费这个劲?真的值得吗?
要让团队能够轻松驾驭并成功运用结对编程,他们必须培养所有有助于克服挑战的技能:专注力、任务组织能力、时间管理能力、沟通能力、给予和接受反馈的能力、同理心,以及坦诚面对自身不足的能力。而这些技能对于打造一个高效协作的团队至关重要。结对编程让团队中的每个人都有机会共同提升这些技能。
如今,多元化被广泛认为是高效团队成功的关键因素之一。多元化的视角、性别、背景和技能已被证明能够提升团队表现,但它往往也会首先增加摩擦。它甚至会加剧我们前面讨论过的一些结对编程挑战。例如,我们提出的一个关键要素是展现脆弱性,而这对于来自弱势群体的团队成员来说尤其困难。
请看海外某知名商业评论媒体的一篇文章标题:“多元化团队感觉更不自在——而这正是他们表现更佳的原因。”作者指出:“同质化团队让人感觉更轻松——但轻松并不利于绩效。……这一观点与许多人的直觉相悖。”为了解释这一点,他们提到了一种名为“流畅性启发式”的认知偏差:我们更喜欢容易理解的信息,并认为它更真实或更美好。
这种偏好让我们追求简洁,而这在软件开发的许多情境中都非常有效。但我们认为,在结对编程中,这种偏好并不适用。结对编程一开始会让人感到困难,但这并不意味着它对团队不好。更重要的是,它并非注定一直如此困难。有实践者曾介绍过自己所在的海外某大型互联网团队如何克服最初引入结对编程等实践时产生的不适感,其中提到了反馈文化、非暴力沟通、心理安全感、谦逊以及使命感等因素。
结对编程、极限编程以及敏捷软件开发的核心理念,都是拥抱变化。敏捷软件实践者认识到变化不可避免,因此他们希望为变化做好准备。
我们建议,团队也应该积极应对并准备好面对摩擦,因为在打造高效多元化团队的道路上,摩擦同样不可避免。我们所说的积极应对摩擦,并不是“制造大量冲突,然后我们就会变得更好”。我们的意思是,团队应该配备应对摩擦所需的工具,并将这些工具纳入日常工具箱,而不是只在问题出现时才想起它们。要重视反馈机制,改善团队沟通,并采取措施营造心理安全的环境。
我们认为,结对编程常常被人们回避,是因为它可能带来摩擦。但我们仍然诚恳地建议你尝试它。如果你把结对编程视为一项可以提升的技能,并努力精进,最终你将打造出一支更具韧性的团队。
关于结对编程的常见问题
结对编程是什么意思?
结对编程是指两名开发者共同完成同一项开发任务。通常一人负责操作键盘,另一人负责观察、思考和提出建议。两人会定期交换角色,共同推进代码实现、问题分析和方案设计。
结对编程适合所有开发任务吗?
并不一定。结对编程非常适合复杂功能、关键代码、新成员入职、知识传递和高风险变更。对于一些非常简单、重复性强且团队已经非常熟悉的任务,可以根据实际情况决定是否结对。
结对编程会不会让成本翻倍?
表面上看,两个人完成同一项任务似乎会增加成本。但在实际团队协作中,结对编程可以减少返工、提升代码质量、加快知识传播,并降低知识孤岛风险。因此,是否“划算”不能只看短期编码人数,而要结合长期维护成本和团队协作效率来判断。
如何开始实践结对编程?
可以先从小范围实验开始,例如选择一个适合结对的用户故事,由两名开发者共同完成。实践过程中要定期轮换角色、安排休息时间,并在结束后进行简短回顾。团队可以根据反馈逐步调整结对频率、结对方式和适用场景。
文章包含AI辅助创作,作者:liu,如若转载,请注明出处:https://docs.pingcode.com/baike/5243119