Как пишут код большие команды: код-ревью, тесты и страховка от хаоса
Один программист в гараже может писать как угодно. Но когда над продуктом работают сотни людей, нужны правила, иначе всё рухнет. Заглянем за кулисы: что такое код-ревью, зачем нужны автотесты и как из этого складывается дисциплина больших команд.
В крупной компании ни одна строчка кода не попадает в продукт, пока её не прочитает и не одобрит другой человек — и это не бюрократия, а здравый смысл.
Писать код в одиночку и писать его в команде из ста человек — это два разных навыка. Второй держится на ревью, тестах и общих договорённостях.
Почему «просто писать код» перестаёт работать
Пока вы один, код живёт у вас в голове целиком. Но представьте проект, где миллион строк и двести авторов. Никто не знает систему полностью. Любая правка может незаметно сломать что-то на другом конце. Чужой код приходится читать чаще, чем писать свой. В таких условиях нужна страховка от человеческих ошибок — и команды выработали для этого набор практик.
Код-ревью: четыре глаза вместо двух
Главный ритуал — код-ревью (code review). Прежде чем изменения попадут в общий проект, разработчик оформляет их как pull request — «запрос на слияние». Коллега открывает его, читает каждую изменённую строчку и задаёт вопросы: «А что будет, если сюда придёт пустое значение?», «Тут опечатка», «Можно проще». Только после одобрения код вливается в проект.
Ревью ловит не только баги. Оно держит код единообразным (чтобы вся кодовая база выглядела так, будто её писал один человек), распространяет знания (теперь о новом коде знают двое, а не один) и учит новичков на примерах. Да, это замедляет момент «прямо сейчас», но экономит недели на отладке потом.
Автотесты: код, который проверяет код
Второй столп — автоматические тесты. Это специальный код, который запускает основной код и проверяет, что тот ведёт себя правильно. Простейший пример:
def skidka(cena, procent):
return cena - cena * procent / 100
# тест: проверяем, что функция считает верно
assert skidka(1000, 20) == 800
assert skidka(500, 0) == 500
print("Все проверки прошли успешно")Тестов бывают тысячи. Их главная ценность — в защите от регрессий: ситуаций, когда новая правка случайно ломает то, что давно работало. Поменял одну функцию — запустил все тесты — и за минуту узнал, не задел ли что-то ещё. Без этого в большом проекте каждое изменение было бы прыжком в темноту.
Уровни тестов
Тесты бывают разной «глубины»:
| Юнит-тесты | Проверяют одну маленькую функцию в изоляции. Быстрые, их много. |
| Интеграционные | Проверяют, что несколько частей работают вместе. |
| End-to-end | Имитируют действия пользователя: нажал кнопку — получил результат. |
Конвейер, который проверяет всё сам
Чтобы тесты не забывали запускать, их доверяют машине. Как только разработчик отправляет код, автоматический сервер сам собирает проект и прогоняет все проверки — это называют непрерывной интеграцией. Если что-то сломалось, команда узнаёт об этом за минуты, а сломанный код просто не вливается в общий проект. Человеку не нужно помнить про рутину — за неё отвечает конвейер.
Общие правила игры
Кроме ревью и тестов командам нужны договорённости: единый стиль оформления кода (его часто проверяет автоматический «линтер»), понятная структура проекта, осмысленные сообщения к коммитам. Звучит как занудство, но именно эта дисциплина позволяет сотням людей менять один продукт каждый день и не превращать его в неуправляемый хаос. Хороший код в команде — это не самый умный код, а самый понятный для следующего человека, который откроет этот файл через год.