БЛОГIT17 МИНУТ ЧТЕНИЯ

Парное программирование

22 СЕН 2026СЕРГЕЙ БАРАНОВ

ИНЖЕНЕРНЫЕ ПРАКТИКИПАРНОЕ ПРОГРАММИРОВАНИЕУПРАВЛЕНИЕ КАЧЕСТВОМ

Парное программирование – одна из самых недопонятых практик экстремального программирования. Думаю, название сыграло в этом не последнюю роль. Парное программирование, ну что тут непонятного? Сели вместе и давай писать код. Но почему тогда вокруг этой практики столько мифов и легенд? Почему не у всех и не всегда работает, если все так просто? А вдруг парное программирование – это не просто программирование в паре? Чтобы разобраться в вопросе мы обратимся к первоисточнику, научным исследованиям, личному опыту и опыту коллег.

Если код-ревью — это хорошо, значит, мы будем ревьюить код постоянно (парная разработка)

Кент Бек, Экстремальное программирование, 1999

Это обновленная статья, оригинал был написан 2 июня 2021 года.

Что такое парное программирование?

Нам нужны общепринятые термины, нам нужен общий язык. Иначе индустрии сложно развиваться, а нам – понимать друг друга и эту самую индустрию развивать. Поэтому возьмем определение Кента Бека из книги «Экстремальное программирование».

Парное программирование (pair programming) — синхронная совместная разработка, при которой два участника работают над одной задачей, поддерживают общее понимание решения и регулярно переключают активную роль. Они могут использовать один компьютер, совместную IDE или удаленный инструмент для одновременной работы.

В паре две роли, назовем их «Штурман» и «Водитель». В руках «Водителя» клавиатура, он пишет код и его мышление сфокусировано на том, как здесь и сейчас написать некоторый код лучшим способом. Мышление «Штурмана», – стратегическое. Он думает о том, является ли оптимальным код «Водителя» для решения в целом, размышляет об альтернативах и способах упростить систему.

Основной контраргумент

«Как это, два человека выполняют одну задачу?, – простонал эффективный менеджер, – по-отдельности они же могут сделать за то же самое время в два раза больше!». Только есть один нюанс – задачи не похожи друг на друга, мы не знаем наперед, как продукт будет развиваться, а вариантов решения одной и той же задачи у нас примерно сколько угодно. Одних только алгоритмов сортировки чисел более тридцати, а мы не просто числа сортируем, а, например, сортируем продукты по цене с учетом скидок, пейджингов, рейтингов и еще десятка параметров.

Вообще, этот аргумент мне приходилось слышать сотни раз. Самое интересное, что с этим аргументом не поспорить, он железобетонный, если… вы продаете или покупаете «ресурсы» и «часы» на проект, а не прирост бизнес-возможностей (тот самый инкремент) в продукте. Именно поэтому в компаниях, в которых оплата/контроль работы разработчиков идет по отработанным по конкретным фичам часам, контракты с вендорами заключены с учетом количества доступных часов разработчиков, работать в паре – это как выстрелить себе в ногу, урезать прибыль, причем если все всё время работают в парах (как и описано в книге у Кента Бека), то ровно в два раза.

Первая страница статьи не закончена, а мы уже видим, что ограничением для парного программирования может быть такая штука, как контрактные отношения с вендором или индивидуальные KPI менеджмента, направленные на утилизацию «ресурсов»(разработчиков) или система учета/контроля за временем работы каждого разработчика в отдельности с соответствующими методами планирования, когда емкость команды == (количество разработчиков)x(длина спринта)x(8 часов).

Если закопаться, то и ежегодный пересмотр зарплаты может стать препятствием к парному программированию, если «заслуги» людей рассматриваются сугубо по результатам индивидуальной работы. Здесь есть свои лайфхаки, но для этой статьи это оффтопик.

Выгоды от парного программирования

Какие выгоды обычно перечисляются, когда упоминается парное программирование? Например, касающиеся кода:

  • Повышение качества кода
  • Соблюдение/передача стиля кодирования
  • Передача знаний о коде и коллективное владение кодом

Не реже встречаются преимущества, касающиеся передачи знаний:

  • Обучение менее опытных коллег
  • Повышение скорости погружения в новый проект (нет тупнякам и бездумному скроллингу исходников)
  • Эффективное решение интеграционных задач на стыке систем или библиотек

Но давайте отложим в сторону маркетинговые лозунги и посмотрим, что говорят контролируемые исследования.

Обратимся для начала к работе «The Costs and Benefits of Pair Programming» за авторством Alistair Cockburn и Laurie Williams. Рекомендую ознакомиться с работой, здесь же приведу лишь краткие выводы:

  • При парном программировании стоимость разработки, выраженная в часах, увеличивается на 15%, а не в два раза;
  • Код, разработанный в парах содержит в среднем на 15% меньше дефектов;
  • При парном программировании объем кода в среднем на 20% меньше.

При этом более поздние обзоры показали, что это не универсальные коэффициенты и результаты существенно зависят от сложности задачи, опыта участников, состава пары и способа измерения. Парную работу следует оценивать по совокупной стоимости поставки и сопровождения, а не только по часам написания кода.

Каждый баг – это оформление дефекта в багтрекинге, передача дефекта на исправление, переключение контекста разработчика, воспроизведение дефекта разработчиком, поиск дефекта в коде, исправление, мерж в нужную ветку и повторное тестирование. Но это только если дефект не пролез в прод. Иначе прибавим работу call-центров с недовольными клиентами, развертывание исправленной версии на проде, возможно – извинения перед клиентами, не исключено, что с подарками и скидками, коммуникация со СМИ. Ну и конечно, все перечисленное выше – это чистой воды потери (согласно Бережливому Производству), – могли сделать фичу, но потратили время на исправление бага.

А по поводу объема кода достаточно процитировать Роберта Мартина:

Соотношение времени чтения и написания кода превышает 10:1. Мы постоянно читаем свой старый код, поскольку это необходимо для написания нового кода.

Robert C. Martin (Uncle Bob), «Clean Code»

Становится очевидным, что экономически парное программирование является выгодным вложением. И если еще лет пять назад я бы не стал оспаривать этот вывод, то сейчас, учитывая стремительный рост зарплат разработчиков рекомендую провести предварительный расчет экономического эффекта для своей команды.

Остальные выгоды от парного программирования, перечисленные в статье, это:

  • Рост удовлетворенности от работы
  • Упрощение дизайна (Simple Design) (простой не равно примитивный)
  • Быстрее решаются «не решаемые» проблемы
  • Непрерывный код-ревью (меньше пропущенных дефектов)
  • Выстраивание коммуникаций в команде,  «дешевый» способ тимбилдинга
  • Кросс-обучение
  • Повышение bus factor

Из собственного опыта добавлю, что с помощью грамотно организованного парного программирования удавалось в разное время и в разных компаниях:

  • Сократить время на онбординг разработчиков в проект со сложной предметной областью в среднем с 2-3 месяцев до 1-3 недель. В этом проекте я выступал в роли архитектора и полностью выстраивал процесс разработки. Согласно процессу, один из старожил брал менторство над новичком и помогал ему адаптироваться и в коде и в архитектуре и в компании. Адаптация в компании тоже улучшилась. Когда этим занимались HR, они рассказывали как должно быть «по процессу» (что в целом, наверное, правильно). Ментор же делился житейской мудростью и полезными лайфхаками, например, как оформить овертаймы или записаться на корпоративный английский.
  • Сократить время разработки отменив обязательные Code Review. Code Review в этом проекте был такой штукой, на которую вечно не хватало времени и вместо того, чтобы насильно заставлять его проводить было предложено попробовать пару спринтов поработать в парах. Через полтора месяца в команде появилась общая договоренность: «разработчики сами решают, отправлять код на ревью или нет». Качество кода выросло (сильно упала цикломатическая сложность, например), время на ревью сократилось почти до нуля и теперь все понимали, что если кто-то отправил код на ревью, «значит это кому-нибудь нужно», а не просто по процессу и для галочки.
  • Повысить bus factor. В этом случае в пары объединялись разработчики разных компонентов, которым нужно было провести интеграцию между собой в рамках реализации общей фичи. Обычно такой способ парного программирования описывается как «запилить интеграцию в паре», но мы предложили в паре не только над интеграцией поработать, но разработать всё от начала и до конца. Интеграция заняла на порядок меньше времени, а знание особенностей тех с кем интегрируешься улучшило отношения и качество принимаемых решений. Как приятный бонус, оказалось, что «ТЗ на интеграцию» не так уж и нужны…
  • Сократить WIP. Это эффект второго порядка и происходит органически, так как в моменте в работе оказывается меньшее количество задач. И если само парное программирование сокращает время работы над отдельно взятой задачей, уменьшение WIP сокращает время прохождения задач через всю производственную систему (иными словами – позволяет снизить средний Lead Time и улучшить пропускную способность системы).

Еще пара свежих исследований на тему выгод от парного программирования:

Парное программирование как навык

Долгое время исследования касались парного программирования как такового. Берем задачу и даем ее выполнить разным программистам в парах и в одиночку (solo в англоязычной литературе). Повторяем много-много раз и смотрим на результат. Это упрощенное описание, но в целом оно верно. Такие исследования позволяли определить, есть ли польза (да, польза есть) от парного программирования прежде чем начать копать глубже. И вот пришло время более глубоких исследований, показывающих чем отличаются хорошие сессии парного программирования от плохих. Раз есть понятия «лучше» и «хуже», значит есть и навык парного программирования, который можно развить. Косвенно об этом упоминается в вышеупомянутой статье от Alistair Cockburn:

But about four months into the merge, I began to notice that things were changing. One pair in particular spent their whole day together, doing honest-to-goodness pair programming, and the other two pairs were getting much closer to that ideal. In discussions it was clear that they knew why the change was happening. It simply worked better!

The Costs and Benefits of Pair Programming

А вот явно об этом говорится в исследовании 2021-го года «Two Elements of Pair Programming Skill». Согласно этой статье, парное программирование – это навык, который складывается из:

  • Togetherness (единство, единение). Хорошим парам удается устанавливать и поддерживать общую ментальную модель на протяжении всего сеанса. Они выявляют и устраняют отличия в понимании задач, систем и разработки в целом.
  • Expediency (целесообразность). Хорошие пары уравновешивают краткосрочные цели, такие как выявление дефектов или реализация новой фичи и долгосрочные, например – устранение пробелов в знаниях партнеров, онбординг.

Исходя из этих характеристик, авторы статьи выделили три анти-паттерна парного программирования:

  • Lost in the Weeds (блуждание в трех соснах). Проявляется, когда участники начинают тратить время на исследование не относящихся к делу деталей и упускают из виду то, что является важным. Снижает expediency.
  • Losing the Partner (потеря партнера) происходит, когда один из участников сосредоточился на задаче и не обращает внимание на то, что второй участник выпал из контекста. Снижает togetherness.
  • Drowning the Partner. Один из участников крайне избыточно объясняет свои мысли и действия. Может снизить и expediency и togetherness.

Результаты исследований соответствуют и моим наблюдениям. Например, togetherness, единая ментальная модель. Без нее работа в паре может превратиться в спор, бесконечный и беспощадный. Именно поэтому само по себе парное программирование не позволит «соблюдать и передавать стиль кодирования», если вы в команде, вместе, заранее об этом стиле не договорились. Именно поэтому код не станет понятнее, если команда и бизнес вместе, заранее не определили Единый Язык (Ubiquitous Language) на основе модели предметной области, например, с помощью Event Storming и Domain Driven Design. 

Исследование предметной области с помощью Event Storming

А для expediency важным фактором является предварительная проработка решения, ведь известно, что задачу мы решаем до того, как приступаем к написанию кода. И для этого существует множество техник, например совместное создание компонентной структуры продукта.

Были и другие исследования парного программирования, например в работе «The effectiveness of pair programming: A meta-analysis» приведены выводы об эффективности парного программирования в зависимости от сложности задач и уровня разработчиков.

Влияние опыта программистов (a) — (d) и сложности системы (e) — (h) на продолжительность, усилия и корректность

Очевидно, что парное программирование – это навык, который можно прокачать. Оно несет серьезные выгоды во всех аспектах разработки и управления разработкой, но требует усилий на входе для того, чтобы практика заработала, а иногда и в принципе ее применение стало возможным.

Стили парного программирования

Так разве нельзя просто сесть и начать работать? Можно, но лучше заранее разобраться в проверенных временем стилях парного программирования.

«Штурман» и «Водитель»

Самый «старый» стиль.

  • Партнеры совместно прорабатывают решение на бумаге, доске, в miro; формируют общую ментальную модель. Еще не код, но уже не воздух.
  • «Водитель» пишет код и проговаривает свои действия, «Штурман» проверяет решение на прочность и смотрит на картину в целом
  • Через некоторое время, обычно 30 минут, партнеры меняются ролями

Водитель мыслит тактически – пишет код и проговаривает свои действия. «Штурман» мыслит стратегически – проверяет решения «Водителя» на прочность, смотрит на картину в целом (первичные исследования работы мозга во время парного программирования показали, что уровень концентрации у «Штурмана» значительно выше, чем у «Водителя», что само по себе – контринтуитивно).

Строгое парное программирование

Строгое парное программирование – более строгая версия стиля Штурман/Водитель, в которой «Штурман» говорит «Водителю» что делать, а «Водитель» только пишет то, что ему говорят. Если у «Водителя» появляется идея, он занимает место «Штурмана». Идея в том, что для «Штурмана» «Водитель» является своего рода «интеллектуальным интерфейсом ввода».

Ping Pong

Этот стиль идеально сочетается с TDD. Для старта парного программирования в удаленном режиме рекомендуется использовать именно этот стиль.

Алгоритм:

  • Боб пишет тест
  • Алиса пишет код так, чтобы тест успешно выполнился
  • Алиса пишет следующий тест
  • Боб пишет код под этот тест
  • И так далее

Смешанное парное программирование

Подходит для опытных, хорошо сработавшихся команд. Все работают по кругу со всеми, пока задача не будет выполнена.

Алгоритм:

  • A работает в паре с Б
  • Б работает в паре с В
  • В работает в паре с Г
  • Над одной и той же задачей, возможно в течение одного дня

Командное программирование (Mob Programming)

Вся команда работает над одной задачей в один момент времени, в одном месте за одним большим экраном. Устраняет любые очереди в разработке, так как по сути команда работает в режиме one-peace-flow Подробнее в выступлении Ивана Зимина «Командное программирование».

Варианты структур при организации пар

Существует несколько проверенных временем стилей парного программирования. Но ведь в парах работают люди, люди с различными навыками, есть ли тут какой-нибудь подвох? И да и нет.

Обычно рассматриваются три варианта структур:

  • Junior — Senior
  • Junior — Junior
  • Senior — Senior

Иногда еще добавляют middle. Не вижу в этом большой ценности, так что остановимся на Junior/Senior. Важно понимать, что сама оценка Junior/Senior — многомерная и, например, Junior может хорошо знать кодовую базу, но не знать предметную область или иметь слабый навык в использовании отдельных паттернов.

Для начала попробуем пойти от особенностей и потребностей Junior- и Senior-разработчиков, составим портреты.

Junior

Senior

Мало опыта

Эксперт

Чаще неуверенный

Уверен в себе и своих силах

Стесняется предлагать решения

Активно предлагает решения

Минимальные знания кода

Отлично знает код

Фокус обучения: код, терминология, архитектура, работа с IDE

Фокус обучения: лучшие практики, тренды, производительность, безопасность

Отличия достаточно серьезные и если у Senior еще и ментальность супергероя, он легко станет Keyboard Dominator pastedGraphic.png и у Junior не останется шансов на развитие, продуктивную работу и закрытие своих потребностей, а именно: 

  • Возможности пробовать новые для себя вещи, 
  • Допускать собственные ошибки, 
  • Экспериментировать, 
  • Получать конструктивную обратную связь и поддержку от партнера.

Многие Senior забывают со временем, что именно благодаря закрытию этих потребностей они и стали Senior’ами.

Иногда в паре Junior-Senior Senior воспринимает Junior как человека, который только замедляет разработку. К слову – это правда, но для успеха команды важно не это (еще Фредерик Брукс об этом писал), важно другое – сделали ли партнеры всё возможное, чтобы стать немного эффективнее, чем было к началу сессии. Постепенно, навык к навыку, Junior нарастит скорость. Небольшие улучшения капитализируются и из них складываются большие достижения.

Senior следует ответственно отнестись к парному программированию с Junior. Первым шагом будет признание самого факта, что сейчас вы в паре с джуном, а ему потребуется больше поддержки, внимания и направления действий. Учитывайте это еще при планировании, чтобы избежать давления сроков. Выбирайте подходящие (подходящие для Junior’а в данном случае) задачи, учитывая особенности и потребности, перечисленные выше. После сессии парного программирования обязательно проведите ретроспективу, пусть на пять минут, но хотя бы с одним улучшением, которое вы примените в следующую сессию. Развивайте не только код и навыки, но и сам процесс работы, именно это позволит качественнее и комфортнее разрабатывать продукт.

Динамика работы в паре

Движемся дальше. Существует несколько проверенных временем стилей парного программирования. Структурно в парах могут работать люди с различным уровнем знаний: Senior-Junior, Senior-Senior и Junior-Junior. Интуиция подсказывает, что в зависимости от структуры по-разному может проявляться и динамика. Так ли это?

В исследовании «Explaining pair programming session dynamics from knowledge gaps» (Freie Universität Berlin) авторы изучали поведение пар c позиции недостаточности знаний. Знания они разделили на специфичные для разрабатываемой системы и общие (как вообще разрабатывать, паттерны, знание языка программирования и так далее). Рассмотрим оптимальные модели поведения в зависимости от типа недостающих знаний и конфигурации пары.

Отсутствие пробелов в знаниях

Оба партнера обладают всеми необходимыми для разработки знаниями. Чаще всего это либо комбинация «Senior-Senior», либо greenfield-проект. К слову, пара Senior-Senior хорошо подходит и для срочного багфикса. Дефект будет закрыт быстрее, а код будет качественнее.

Недостаток специфичных знаний у одного из партнеров

Может произойти, если один из партнеров раньше начал работать над задачей. В статье на эту тему два примера:

  • Багфикс, при котором один из разработчиков знает код, в котором обнаружен дефект. Тогда все просто – он рассказывает второму разработчику как устроен код, после чего они вместе фиксят дефект.
  • Один из разработчиков начал разработку новой фичи раньше, чем к нему присоединился второй. Продуктивная работа началась только после того, как второй разработчик смог построить в голове всю логику уже реализованной части решения от начала и по текущий момент.

Важный вывод: во время сессии, перед тем, как начать разрабатывать новый функционал, убедитесь, что устранены односторонние пробелы в специфичных для системы знаниях, требуемых для реализации.

Недостаток специфичных знаний у обоих партнеров

Здесь не важно, это недостаток знаний об уже разработанной части системы или о том, что только предстоит разработать. Суть одна – знаний нет. 

Авторы статьи приводят стратегии:

  • Совместное создание знания. Формулируется гипотеза о системе, изучается код и само приложение, после чего инсайты интегрируются друг с другом.
  • Изучение в одиночку. Один из разработчиков изучает систему и затем рассказывает второму.

Недостаток общих знаний у одного из партнеров

Согласно результатам исследования, конструктивной стратегией в такой ситуации является pull-стратегия, при которой разработчик с недостатком общих знаний наблюдает и «вытягивает» (например — спрашивает, уточняет) знания о том, что ему не понятно в то время, как более опытный пишет код. Код становится примером, а вопросы раскрывают суть действий.

Недостаток общих знаний у обоих партнеров

Авторы собрали недостаточно данных для однозначных выводов. Их наблюдения такие: при недостатке общих, инженерных, знаний у обоих партнеров возможна ситуация, при которой задача вообще не будет решена.

К слову, наблюдал это на практике несколько раз. Есть различные крылатые выражения о том, что «Senior может выполнить задачу в 10 и 100 раз быстрее, чем Junior». Правда в том, что иногда Junior вообще не может выполнить задачу. И два таких Junior все равно не выполнят задачу. Они могут просто-напросто не знать какого-то алгоритма, библиотеки, особенности языка и не знать о том, что они пока еще этого не знают (те самые unknown unknowns).

Управление временем

Мы на финишной прямой. Существует несколько проверенных временем стилей парного программирования. Структурно в парах могут работать люди с различным уровнем знаний: Senior-Junior, Senior-Senior и Junior-Junior. В зависимости от структуры по-разному может проявляться и динамика работы в паре. Так сколько же нам вот так в паре работать времени, как часто?

Работать паре весь день и всю неделю – контрпродуктивно. Есть немало задач, которые лучше делать в одиночку, например – исследования, рутина. Планируйте заранее сколько времени вы будете работать в паре. Четверть дня три дня в неделю и пол дня два дня в неделю.

Для самих сессий отлично подходит техника Pomodoro. Хороший инструмент – приложение Flow, но подойдет любой таймер. Так как меняться ролями лучше не реже, чем каждые 30 минут, то подойдут 25 минутные рабочие интервалы с 5-минутным перерывом.

Удаленное парное программирование

Удаленное парное программирование уже стало вариантом нормы, хоть и не остается не столь эффективным, как совместное за одним компьютером, несмотря на все произошедшие за последние годы изменения.

Среди вариантов удаленного парного программирования стоит отметить:

  • Совместное редактирование в IDE
  • Управление удаленной сессией
  • Демонстрация экрана с передачей управления

Как вы уже, наверное, догадались, эффективность падает не только из-за того, что люди пространственно разделены, но и из-за физических задержек на переключение и проблемы со связью.

Для снижения негативного влияния необходимо настроить окружения в унифицированном виде, как минимум визуальное оформление, иначе мозгу придется каждый раз переключаться между различными видами отображения кода.

Генеративный ИИ и парное программирование

AI-ассистент не следует считать полноценной заменой второго человека. Он может:

  • предлагать варианты реализации,
  • объяснять незнакомый код,
  • генерировать заготовки тестов,
  • искать граничные случаи,
  • помогать с рефакторингом,
  • формировать черновики документации,
  • ускорять исследование API.

Но он не несет ответственности, может ошибаться, выдумывать API, воспроизводить небезопасные шаблоны и увеличивать объем кода без улучшения решения.

Модель «Пара разработчиков + AI»

  • Водитель управляет IDE и запросами к ассистенту
  • Штурман проверяет постановку задачи, предположения, безопасность, тесты и соответствие архитектуре
  • Оба участника проверяют сгенерированный код так, как если бы он пришел от неизвестного внешнего автора
  • Ни один участник не должен становиться пассивным наблюдателем «автопилота»

Обратите внимание, что в этой модели не пара «Один разработчик + AI», а «Два разработчика + AI». Все из-за того, что AI способен уменьшить механическую нагрузку, но одновременно повышает важность роли Штурмана – проверки намерения, фактов и последствий.

Шесть простых шагов для старта

И напоследок, список из шести простых шагов, чтобы начать. Надеюсь, что прочтение этой статьи и статей, на которые я ссылался, позволит вам понять, почему каждый из пунктов важен и что за ним скрывается.

  1. Договоритесь о высокоуровневой цели
  2. Разбейте работу на таски и проставьте им приоритеты
  3. Выберите подходящий стиль парного программирования
  4. Устраните отвлекающие факторы
  5. Работайте в выбранном стиле с перерывами
  6. Закончите с небольшой ретроспективой

ПОДЕЛИТЬСЯ:

АВТОРСергей Баранов