В декабре Яндекс Практикум провёл открытый вебинар о том, как устроен процесс код-ревью в коммерческой разработке и образовании. Руководитель отдела разработки поисковых интерфейсов в Яндексе Сергей Бережной и старший код-ревьюер на курсе «Веб-разработчик» Айгуль Маликова рассказали о полезных инструментах для ревью кода и поделились кейсами из своей практики.  Видеозапись вебинара доступна по ссылке. Для тех, кому удобнее воспринимать информацию в текстовом формате, мы сделали конспект. Руководитель отдела разработки поисковых интерфейсов в Яндексе В первую очередь код-ревью позволяет новичкам легко войти в ваш проект. Когда новый разработчик попадает в команду, он ещё не знает, как у вас всё устроено. В процессе код-ревью он получает предметный фидбек, ориентированный на конкретную работу и собственное присутствие в ней.  Второй важный момент связан с построением команды. Этот процесс можно сравнить со сборкой трансформера из нескольких роботов поменьше. Объединившись, команда работает эффективнее, чем каждый отдельный разработчик, даже очень опытный. Благодаря хорошему код-ревью на этапе вливания feature branch в основную ветку мы стабилизируем def, и это позволяет разным членам команды быть уверенными в том, что там не будет никаких проблем и ошибок, потому что за каждым разработчиком провели ревью.  Кроме того, постоянный просмотр кода друг друга увеличивает важную характеристику в разработке — коллективное владение кодом. То есть каждый его участок перестаёт быть отдельной «комнатой в общежитии», в которой царят свои порядки и никто кроме хозяина не может в них разобраться. Другими словами, кодом полноценно владеют все участники процесса, будто каждый из них его писал. Следовательно, каждый может продолжить писать любую зону кода, исправлять баги и делать доработки. Ещё одно ценное свойство код-ревью перекликается с тем, о чём я говорил в первом пункте. Когда есть процесс, который позволяет легко вливаться в команду новым людям, то и перестановка между командами внутри больших проектов происходит проще: разработчики из разных команд делают код-ревью между собой и видят, что происходит в других частях кода. И последнее по этой теме. Есть расхожее выражение про «фактор автобуса», которое я хочу перефразировать и назвать «фактор отпуска»: как много человек может уйти в отпуск, чтобы ничего не сломалось? Если в команде развито коллективное владение кодом, то вы больше не зависите от того, что конкретный разработчик куда-то делся, а вам нужно что-то подправить в его коде.  При написании кода мы часто работаем в разных модальностях. В фокусе внимания — конкретные строчки кода, локальные задачи и проблемы. Но иногда нужно посмотреть на проект целиком и комплексно оценить его состояние. Это перемещение между Zoom In — Zoom Out зачастую даётся тяжело. Процесс код-ревью позволяет его триггерить за счёт внешних причин: появляется естественная потребность посмотреть и на свой, и на чужой код.  Есть такая поговорка: одна голова хорошо, а две лучше. Два даже очень крутых разработчика вместе могут додуматься до большего, чем каждый из них по отдельности. И даже если их обоих посадить писать код параллельно, то это не сравнится с той степенью креативности и взаимопомощи, как в процессе ревью. На моей памяти самые сложные в хорошем смысле этого слова куски кода были созданы в режиме парного, а иногда и тернарного программирования.  Код-ревью — это один из способов привнести две точки зрения на одну и ту же проблему. Оно позволяет выводить качество решений на совершенно новый уровень. При выборе код-ревьюеров нужно соблюсти два фактора. С одной стороны, важно использовать рандомизацию — как раз для коллективного владения кодом, чтобы разные люди успевали посмотреть на него. С другой стороны, в любом проекте есть значимые куски кода, за которые отвечает какая-то одна команда. И хорошо, чтобы на начальном этапе, пока ревьюеры не выбраны, эта команда или отдельный человек из неё визировали все пул-реквесты в эту часть кода. В Яндексе мы применяем разные стратегии назначения ревьюеров: например, выбираем ответственных на отдельный фрагмент кода или типа файлов. К нему рандомно добавляем кого-то ещё. Но назначение ревьюеров должно быть балансным между рандомизацией и точечным выбором тех, кто отвечает за конкретный фрагмент кода. Количество ревьюеров зависит от того, насколько сложна фича, но в среднем это два человека. Многие разработчики жалуются, что ревьюеры недостаточно глубоко погружаются в код — и зачастую это справедливое замечание. Когда вы делаете код-ревью, хорошо бы посмотреть на код подробно. Но, как правило, перед ревьюером не стоит задача докопаться до мелочей.  Такое противоречие связано с тем, что точки зрения ревьюера и автора по определению отличаются, и степень погружения можно варьировать. Не надо пытаться полностью запустить проект на код-ревью. Нужно привнести в него то, что упустил автор, и предложить новый ракурс.  Самый распространённый вариант — короткие текстовые комментарии внутри кода. Но на практике это не всегда удобно, поэтому для сложных вещей лучше проводить рабочие встречи.  С комментариями часто возникает такая проблема: количество экранной площади, которую занимает текст, непропорционально значимости самого текста. Целая страница несущественной и непринципиальной информации оттягивает на себя внимание, в то время как одно изменённое в строчке слово может оказаться самой важной деталью. Для больших пул-реквестов полезно собраться в комнате, где автор кода возьмёт указку и пальчиком покажет: вот тут читаем, а тут не читаем, вот это неважно, а вот здесь есть ключевые моменты. И дальше вся команда может оперативно обсудить увиденное и вынести вердикт.  В Яндексе есть собственная система контроля — GitLab Enterprise Edition. Но многие команды используют дополнительные утилиты по типу тех скриптов, которые назначают ответственных, или на основе функции перекидывания части код-ревью на кого-то другого. Важно быть готовыми к тому, что придётся самостоятельно реализовывать какие-то небольшие дотюнивания процессов на своих проектах.  Если коротко, моё мнение: да. Когда вы делаете код-ревью необязательным, то потом психологически очень сложно возвращаться к закрытой задаче.  Предположим, вы автор пул-реквеста. Вы его уже успешно влили, задачу закрыли и забыли. Тут к вам приходит ревьюер и говорит: «Ты знаешь, вот тут вот что-то неправильно, давай поправим». А ты уже давно занимаешься новой задачей. В итоге эффективность падает. Пул-реквесты копятся, нагнетают атмосферу, хочется махнуть рукой: «Мы уже никогда это не доревьюируем. Давайте даже начинать не будем». Сгорел сарай — гори и хата.  Но иногда код-ревью может быть необязательным. Например, если вы занимаетесь тривиальным кейсом: правите документацию, конфликт сборки или что-то подобное. У нас для этого существуют специальные теги в коммит-месседжах, которые опускают назначения код-ревьюеров в нашем ревьюшном инструменте. Вы тоже можете использовать такую практику: маркировать тривиальное изменение и проводить его без код-ревью, потому что бывают ситуации, когда расходы на ревью оказываются выше, чем потенциальная польза от результата.  Исключение — парное программирование. Если вы делали пул-реквест вдвоём, то второй человек автоматически становится код-ревьюером. Первое, что кричат противники код-ревью: «Вы ставите нам палки в колёса. Мы двигаемся быстро и готовы на ошибки, а ревью замедляет процесс разработки». Здесь можно вспомнить мем «я печатаю со скоростью 500 символов в минуту, правда, получается фигня какая-то». Скорость не всегда означает качество. Вы можете очень быстро сделать пул-реквест, но если архитектура в целом не очень, то через какое-то время проекту станет плохо.  Второй аргумент противников код-ревью: большинство замечаний примитивны. Это часто действительно так. Например, ревьюеры придираются к литерам. Очевидно, что система автотестов и линтинга кода должна постоянно совершенствоваться — вопросы запятых должны решаться автоматически за счёт роботов. На ревьюеров нужно составлять более сложные вещи.  А ещё есть мнение, что хорошие разработчики не ошибаются. Я тоже большой сторонник такого подхода и считаю, что очень невыгодно допускать ошибки в коде. Ведь их потом нужно исправлять и тратить время. Но, к сожалению, даже самые лучшие разработчики иногда ошибаются, а средние — вообще часто. Поэтому аргумент в духе «давайте мы лучше будем повышать планку разработчиков, а не код-ревьюить» разбивается о суровую реальность. Даже в Яндексе, где очень серьёзный и тщательный отбор, не получается создать команду, где все писали бы с первого раза и без ошибок.  Многие говорят, что раз уж код-ревью выполняется плохо, то лучше вообще никакого не делать. Но я считаю, что даже поверхностное ревью может выявить что-то важное. Вероятность обнаружить проблему, если кто-то лишний раз посмотрит на код, выше, чем если ревью вообще не проводить.  Приходилось ли вам объяснять заказчикам, что нужно дать денег на код-ревью и PR Programming. Если да, то чем мотивировали? В Яндексе нет заказной разработки, но часто приходится объяснять такие вещи менеджерам. И не только про код-ревью, но и, например, про автотесты. Никакой заказчик не заплатит за автотесты, если есть возможность не платить за автотесты. Никакой заказчик не заплатит за парное программирование. Но мы-то знаем, что это меняет всю структуру и формат работы — и в конечном счёте повышает качество проекта.  Выгоднее всего строить с заказчиками рамочные договоры и брать более масштабные задачи. Тогда все затраты будут заложены как свойство качественной работы, а не как отдельный элемент прайса. Вы не должны погружать заказчика в эти детали. Это не опция, которую он выбирает или не выбирает.  Иду стажёром в Яндекс. Какой степени погружённости в код от меня ждут на код-ревью? Должен ли я досконально понимать, как он работает, или достаточно просто обратить внимание на общие паттерны, чтобы использовать их позже в своём коде? Хорошо бы чекнуть это именно с вашей командой, потому что у всех разные внутренние культуры. Яндекс такой большой, поэтому когда вы говорите, что идёте в Яндекс, это может означать очень многое. Из моей практики скажу, что никто не ожидает досконального погружения, но лучше запомнить, как принято, и обращать внимание на архитектуру. Как понять, что разработчик способен проводить код-ревью? Есть какие-то важные качества для этого или минимальный порог опыта? Я думаю, что основные качества лежат в области софт-скилов. Важно, как разработчик доносит фидбек, не использует ли формулировки типа «Какой криворукий дебил мог это написать?» Почитайте в интернете про концепцию ненасильственного общения. Комментарии ревьюера должны нести конструктивный смысл, а не эмоциональный. Любой автор пул-реквеста находится в защитной позиции, потому что ему делают замечания и указывают на проблемные места. Ревьюер должен помочь своему товарищу не чувствовать нападки.  А хард-скилы и внимательность можно натренировать: чем больше вы будете проводить код-ревью, тем чаще будете что-то замечать. Начинать можно с минимального технического уровня: даже если вы вообще ещё ничего не понимаете в кодовой базе, вы можете ревьюировать все пул-реквесты, чтобы проследить, как идёт ход мыслей у более старших и опытных товарищей на проекте. Насколько хорошей считается практика давать подробные комментарии в коде, в том числе для потенциального ревьюера? Или же хороший код — самодокументированный код?  Я рекомендую обсуждать это непосредственно с вашими тиммейтами. Ответ будет зависеть от среднего технического уровня команды, от того, как много приходит новичков. У меня есть персональные предпочтения относительно того, как читать свой код и с какими людьми взаимодействовать. Но жизнь и коммуникация — это процесс, который нужно настраивать.  Старший код-ревьюер на курсе «Веб-разработчик» Всё обучение поделено на двух-трёхнедельные спринты. В начале студенты изучают теорию и отрабатывают практику в тренажёре. После этого они выполняют проектное задание и отправляют его на проверку, а код-ревьюеры дают обратную связь, анализируют работу на наличие критических ошибок. Перед ревьюерами стоит важная задача: зачесть задание студента и допустить его к дальнейшему обучению или нет. Кто же такой код-ревьюер на веб-факультете? Как правило, это веб-разработчик с опытом от полутора–двух лет, который хорошо владеет одной из технологий: HTML, CSS, JavaScript, React или Node.js. В случае с международными направлениями он должен знать английский язык на уровне Upper Intermediate и выше. Ревьюер выделяет от восьми часов в неделю на проверку работ студентов. Платформа Практикума. Это сервис, который похож на с Гитхаб или Гитлаб. Туда студенты загружают свой код, а ревьюеры, соответственно, его просматривают и оставляют комментарии.  Но всё же у нас есть ряд различий по отношению к платформам с git. Например, разделение на типы комментариев. Критический комментарий означает, что ошибку необходимо исправить, иначе работа не будет зачтена. Комментарии рекомендательного характера не требуют обязательного исправления, но предлагают познакомиться с другими хорошими практиками. А комментарии типа «отлично» ревьюеры ставят, когда хотят выделить сильные стороны студента.  Notion. Мы составили множество документов в Notion, где описали флоу, как проводить код-ревью. Там есть, например, конструкторы комментариев, описаны типичные ошибки, которые допускают и студенты, и ревьюеры.  Чек-листы. Это критерии, по которым проверяются работы. Так же, как и типы комментариев, они делятся на три вида: критический, «можно лучше» и «отлично». У каждого из них есть список подпунктов. Когда ревьюер проверяет работу, он проходится по этому чек-листу.  Код-сниппеты. В пределах одного спринта у всех студентов одинаковые требования к заданию. Мы примерно знаем, какой код они будут отсылать, и знаем, какие типичные ошибки могут допустить. Эти ошибки проходят обработку, и на их основе собираются код-сниппеты. Ревьюеры могут брать эти комментарии, использовать их при проверке и адаптировать под себя.  Каноничные работы. Как я уже говорила, мы примерно знаем, какой код ожидаем от студента. И как раз этот ожидаемый код и описан в канонических работах со всеми комментариями. Это бывает полезно для ревьюеров-стажёров, когда им нужно, например, сравнить эталонный код и код студента.  В первую очередь — друг с другом. Все ревьюеры делятся на несколько грейдов, начиная с ревьюера-стажёра и заканчивая старшим ревьюером. Стажёру и ревьюеру помогают мидл-ревьюеры: они перепроверяют работы на качество, а также на наличие пропущенных ошибок. В спорных моментах они помогают решать вопросы.  Старший ревьюер занимается чек-листами, код-сниппетами, каноничными работами и другими инструментами, которые помогают в проверках.  Лид и менеджер команды сопровождения — это люди, которые помогают построить взаимосвязь между студентами и командой сопровождения, то есть соединяют студентов с код-ревьюерами.  Принципы, а не мнение. Мы стараемся не использовать выражения «я думаю», «мне кажется», потому что это создаёт ощущение, что вы просто выражаете своё мнение. Комментарии стоит по возможности обосновать и сопроводить полезными ссылками.  Избегать прямого обращения. Помните, что вы комментируете не самого автора, а его код. Когда критикуете, не используйте личные обращения — это может отвлечь внимание автора от кода и переключить на самого себя. Искренне хвалить. Во время ревью очень редко хвалят. Начинающие разработчики и студенты ещё не имеют достаточно опыта, чтобы определить, хорош ли их код. Как ревьюер вы можете подсветить удачные и оптимальные решения и тем самым мотивировать человека. Комментарии, а не команды, нотации и упрёки. Мы не используем эмоциональные выражения и оценочные суждения: «Это плохо. Никуда не годится». Стараемся не читать нотаций. Код-ревью требует большого такта и осторожности. Вот фразы, которые следует использовать: «Стоит…», «Целесообразно…», «Имеет смысл…», «Лучше…», «Оптимальный…» Использовать примеры кода, но не переписывать код за студента. Вы можете показать альтернативное решение, но не стоит давать примеры кода, которые, на ваш взгляд, будут лучше. Помним правило №1: оперируем не мнением, а принципами.  В первую очередь отличаются процессы. Как я уже говорила, у нас есть определённый список критериев для проверки. Возможно, ещё в каких-то компаниях или командах тоже есть чек-листы, но в целом это не особо распространённая практика.  У нас есть особенности в дедлайнах. Нам нужно уложиться в конкретные сроки — 24 часа с того момента, как студент загрузил работу. На практике, как правило, таких дедлайнов нет, поэтому пул-реквесты могут висеть неделями. Ещё мы заранее примерно знаем, сколько кода напишет студент и какие файлы в нём будут использованы. На практике ревьюеру может прилететь как сто строк кода, так и тысяча.  Наша главная задача — грамотно и структурированно дать бережную и развивающую обратную связь. Мне кажется, это тоже отличает код-ревью в образовании. В коммерческой разработке часто бывают такие комментарии: «Это совсем плохо, исправь». Мы избегаем таких формулировок и придерживаемся своих правил. Главная сложность — это тайм-менеджмент. Как правило, код-ревью — это подработка, а на основной работе то и дело возникают дедлайны и завалы. Тогда на проверку студенческих работ просто не остаётся времени. Мы устанавливаем минимальный объём, который необходимо проверять в месяц.  Другая сложность — первоначальный объём информации. Все инструкции у нас лежат в Notion, и по их количеству может показаться, что не ревьюер пришёл обучать студента, а наоборот, ревьюера сейчас будут обучать. Но со временем объём не будет казаться таким страшным. Ревьюеру нужно относиться с пониманием к тому, что студент не сразу сможет исправить ошибку. Все мы когда-то учились в школе, в универе и испытывали трудности в изучении чего-то нового — совершенно нормально, что у студентов не всё получается с первого раза.  Во-первых, это обучение качественному код-ревью и принципам бережной и развивающей обратной связи. Мы учим правильно структурировать комментарии и излагать свои мысли.  Во-вторых, это возможность дополнительного заработка и обмен опытом с разработчиками внутри сообщества.  В-третьих, это благодарность от студентов. Мне кажется, очень важно не только выполнять свои обязанности, но и видеть, какую пользу ты приносишь для  профессионального становления студентов. Если вы готовы присоединиться к команде Яндекс Практикума в качестве наставника, посмотрите наши открытые вакансии.  Коты опять все уронили, а поднимать мне