Главная » Хабрахабр » [Перевод] Монорепозитории: пожалуйста не надо

[Перевод] Монорепозитории: пожалуйста не надо

Да, это очередная статья о преимуществах и недостатках монорепозиториев. От переводчика: Привет, Хабр! Но пока собирался с мыслями, вышла отличная статья от разработчика из Lyft, которую я и решил для вас перевести. Собирался написать свою статью о том, как мы используем монорепозиторий, как мы переходили с maven на bazel и что из этого получилось. Обещаю опубликовать свои дополнения к статье, а также опыт с bazel в виде продолжения.

Мы в Новом 2019 году, и я настроен на еще одну дискуссию о преимуществах (или отсутствии таковых) в хранении всего исходного кода организации в «Монорепозитории». Для тех из вас, кто не знаком с этим подходом, идея состоит в том, чтобы хранить весь исходный код в едином репозитории системы контроля версий. Альтернатива, конечно, заключается в том, чтобы хранить исходный код в нескольких независимых репозиториях, разделяя их обычно по границе сервисов/приложений/библиотек.
В данном посте я буду называть такой подход «полирепозиторий».
Некоторые из ИТ-гигантов используют монорепозитории, включая Google, Facebook, Twitter и других. Конечно, если такие уважаемые компании используют монорепозитории, то преимущества такого подхода должны быть огромны, и мы все должны делать так же, верно? Нет! Как сказано в заголовке статьи: «Пожалуйста, не используйте монорепозиторий!» Почему? Потому что, на большом масштабе монорепозиторий будет решать все те же самые проблемы, которые решает и полирепозиторий, но при этом провоцируя вас к сильной связанности вашего кода и требуя невероятных усилий по увеличению масштабируемости вашей системы контроля версий . Таким образом, в среднесрочной и долгосрочной перспективе монорепозиторий не дает никаких организационных преимуществ, в то время как оставляет лучших инженеров компании с пост-травматическим синдромом (проявляется в виде пускания слюней и бессвязного бормотания о производительности git).

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

Теоретические преимущества монорепозитория и почему они не могут быть достигнуты без инструментов, которые используются для полирерозиториев (или ложны)

Теоретическое преимущество 1: Более легкая коллаборация и совместное владение кодом

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

Это может быть достигнуто с помощью проприетарной файловой системы как Perforce, которая поддерживает такой режим нативно, с помощью внутреннего инструмента G3 от Google или GVFS от Microsoft. 1) нечто вроде виртуальной файловой системы, которая позволяет хранить локально только часть кода.

Т.к. 2) сложные инструменты как сервис (as a service) для индексирования/поиска/просмотра исходного кода. никто из разработчиков не собирается хранить весь исходный код на своей рабочей станции в состоянии, пригодном для поиска, становится критичным иметь возможность проводить такой поиск по всей кодовой базе.

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

Фактически именно так работает поиск на GitHub, так же как и более сложные инструменты для поиска и индексирования, такие как Sourcegraph. В контексте индексирования/поиска/просмотра и сходного кода такой гипотетический инструмент с легкостью может осуществлять поиск и по нескольким репозиториям и объединять результат.

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

Теоретическое преимущество 2: Одна сборка / нет управления зависимостями

Следующий аргумент, приводимый обычно сторонниками монорепозиториев, заключается в том, что хранение всего кода в одном монорепозитории лишает вас необходимости управлять зависимостями, т.к. весь код собирается в одно и то же время. Это ложь! На большом масштабе просто нет возможности пересобирать весь исходный код и прогонять все автоматизированные тесты каждый раз, когда кто-то коммитит изменения в систему контроля версий (или что более важно и чаще встречается, на сервере CI когда создается новая ветка или пулл-реквест). Чтобы решить эту проблему все большие монорепозитории используют свою сложную систему сборки (например Bazel/Blaze от Google или Buck от Facebook), которая спроектирована так, что следит за изменениями и их зависимыми блоками и строит граф зависимостей исходного кода. Этот граф позволяет организовать эффективное кэширование результатов сборки и тестов, так что только изменения и их зависимости нуждаются в пересборке и тестировании.

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

одиночный коммит описывает полное состояние всего мира. Сторонники монорепозиториев также будут утверждать, что даже с учетом необходимости отслеживания сборок/зависимостей это все равно дает неоспоримое преимущество, т.к. Более того, легко можно реализовать такие средства автоматизированного рефакторинга, которые автоматически обновляют версии зависимых библиотек в нескольких независимых репозиториях сразу, нивелируя разницу между монорепозиторием и полирепозиторием в этой части (более подробно об этом дальше). Я бы сказал, что это преимущество довольно спорное, учитывая, что граф зависимостей уже существует, и это выглядит довольно тривиальной задачей включить идентификатор коммита для каждого независимого репозитория как часть этого графа, и фактически Bazel может легко работать с несколькими независимыми репозиториями как и одним монорепозиторием, абстрагируя нижележащий уровень от разработчика.

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

Теоретическое преимущество 3: Рефакторинг кода — это простой атомарный коммит

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

Таким образом, идея о том, что каждый может легко склонировать себе весь репозиторий и просто выполнить grep/replace, не так легко осуществима на практике. 1) как было описано выше, на большом масштабе разработчик не будет способен редактировать или осуществлять поиск по всей кодовой базе на своей локальной машине.

Я не говорю про исправление бага в имплементации общей библиотеки, т. 2) Даже если мы предположим, что с помощью сложной виртуальной файловой системы разработчик может клонировать и редактировать всю кодовую базу, то как часто это будет происходить? такая ситуация одинаково обрабатывается и в случае монорепозитория, и в случае полирепозитория (предполагая похожую систему сборки/деплоя, как описана выше). к. В очень большой кодовой базе почти невозможно сделать изменение базового API, которое будет проревьюено всеми задействованными командами до того, как мердж конфликты заставят вас начать процесс сначала. Я говорю об изменении API библиотеки, за которым последуют множество ошибок компиляции в тех местах, где эта библиотека вызывается. В любом случае это абсолютно такой же процесс, как и при полирепозитории. У разработчика есть 2 реальные возможности: он может сдаться и придумать обходной путь для проблемы с API (на практике это случается чаще, чем нам всем этого бы хотелось), или он может задепрекейтить существующий API, написать новый API и затем вступить на тропу долгого и мучительного обновления всех вызовов старого API по всей кодовой базе.

Большие организации рано или поздно переходят на использование IDL (язык описания интерфейсов), таких как Thrift или Protobuf, которые позволяют делать типо-безопасные API и производить обратно-совместимые изменения. 3) В сервис-ориентированном мире приложения состоят из множества слабо связанных компонентов, которые взаимодействуют между собой, используя некоторый тип хорошо описанного API. Он может деплоиться на протяжении некоторого периода времени: часов, дней или даже месяцев. Как было описано в предыдущем разделе о сборке/деплое, код не может быть задеплоен одномоментно. Такова реальность современной разработки ПО, которую многие хотели бы игнорировать, но не могут. Поэтому разработчики обязаны думать об обратной совместимости своих изменений. Поэтому, когда это касается сервисов (в противовес API библиотек) разработчики должны использовать один из двух подходов, описанных выше (не менять API или пройти через цикл депрекации) и это абсолютно одинаково и для монорепозитория, и для полирепозитория.

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

Уникальные недостатки монорепозиториев

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

Недостаток 1: сильная связанность и ПО с открытым исходным кодом

Организационно, монорепозиторий провоцирует к созданию сильно связанного и хрупкого ПО. Он дает разработчикам ощущение, что они легко могут исправить ошибки в абстракциях, хотя на самом деле они не могут из-за нестабильного процесса сборки/развертывания и человеческих/организационных/культурных факторов, возникающих при попытке внести изменения сразу по всей кодовой базе.

Это малозаметное, но очень важное преимущество: это заставляет разработчиков думать более масштабно и в более длительной перспективе. Структура кода в полирепозиториях олицетворяет четкие и прозрачные границы между командами/проектами/абстракциями/владельцами кода и заставляет разработчика тщательно продумать интерфейс взаимодействия. Происходит это или нет, зависит только от разработческой культуры, а не от того, используется монорепозиторий или полирепозиторий. Более того, использование полирепозиториев не значит, что разработчики не могут выходить за пределы границ репозитория.

Если компания хочет создавать или потреблять ПО с открытым кодом, использование полирепозиториев просто необходимо. Сильное связывание также имеет серьезные последствия относительно открытия своих исходных кодов. Искажения, которые происходят, когда компания пытается выложить свой проект о open source из своего монорепозитория (импорт/экспорт исходных кодов, публичный/приватый баг трекер, дополнительные слои для абстрагирования разницы в стандартных библиотеках и т.д.) не приводят к продуктивной коллаборации и построению сообщества, а также создают существенные накладные расходы.

Недостаток 2: масштабируемость системы контроля версий

Масштабирование системы контроля версий для сотен разработчиков, сотен миллионов строк кода, и огромного потока коммитов — монументальная задача. Монорепозиторий Twitter, созданный 5 лет назад (на основе git), был одним из самых бесполезных проектов, которые я наблюдал за свою карьеру. Выполнение простейшей команды как git status занимало минуты. Если локальная копия репозитория слишком устаревала, обновление могло занять часы (в то время даже была практика отправлять жесткие диски с копией репозитория удаленным сотрудникам со свежей версией кода). Я вспоминаю об этом не для того, чтобы поиздеваться над разработчиками Twitter, а чтобы проиллюстрировать, как сложна эта проблема. Я могу сказать, что 5 лет спустя, производительность монорепозитория Twitter все еще далека от той, которую хотели бы видеть разработчики Туллинг команды, и это не потому, что они плохо старались.

Git VFS от Microsoft, которая используется для разработки Windows, привела к тому, что появилась настоящая виртуальная файловая система для git, которую я описывал выше как необходимое условие для масштабирования системы контроля версий (и с покупкой Microsoft Github похоже, что этот уровень масштабирования найдет свое применение в фичах, которые GiHub предлагает своим корпоративным клиентам). Конечно, за эти 5 лет в этой области происходило некоторое развитие. И конечно, Google и Facebook продолжают вкладывать огромные ресурсы в свои внутренние системы, чтобы они продолжали функционировать, хотя почти ничего из этого не доступно публично.

Так почему нужно вообще решать эти проблемы с масштабированием системы контроля версий, если как описано в предыдущем разделе, инструментарий требуется ровно тот же самый, что и для полирепозитория? Для этого нет разумной причины.

Заключение

Как часто бывает в разработке ПО, мы смотрим на наиболее успешные софтверные компании как на пример и пытаемся заимствовать их лучшие практики без понимания того, что же именно привело эти компании к успеху. Монорепозитории, по моему мнению, это характерный пример такого случая. Google, Facebook и Twitter инвестировали огромное количество ресурсов в свои системы хранения кода только для того, чтобы прийти к решению, которое по сути не отличается от того, которе требуется и для полирепозитория, но провоцирует сильное связывание и требует огромных инвестиций в масштабирование системы контроля версий<i/>.

напрямую зависит от инженерной культуры и лидерства, и не имеет отношения к тому, используется ли монорепозиторий или полиропозиторий. По сути, на большом масштабе то как компания действует с совместной работой с кодом, коллаборацией, сильным связыванием и т.д. Так зачем использовать монорепозиторий? Оба решения выглядят одинаково для разработчика. Пожалуйста, не надо!


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Перевод] CSTroN — самодельный монитор на винтажной CSTN-матрице с VGA-входом и платой управления на ПЛИС

ЖК-монитор с CSTN-матрицей Что если бы TFT никогда не изобрели? Когда ЭЛТ-мониторы преобладали, в их пользу выдвигали следующий аргумент: несмотря на все усовершенствования, ЖК-дисплеи никогда не превзойдут по качеству изображения трубочные. Они, как и прежде, будут находить применение лишь там, ...

Многомировая интерпретация квантовой механики

Наверняка большинство из вас нет-нет да и встречало в научно-популярной литературе упоминания о «многомировой интерпретации» квантовой механики (ММИ). Ее любят помянуть и в комментариях на Хабре, однако зачастую в неверном ключе или с серьезными неточностями. Попробуем разобраться, что же к ...