Делай как вGoogle
Скачать 5.77 Mb.
|
ЧАСТЬ IV Инструменты ГЛАВА 16 Управление версиями и ветвями Автор: Титус Винтерс Редактор: Лиза Кэри Пожалуй, ни один инструмент программной инженерии не получил такого широко- го распространения, как системы управления версиями (VCS). Трудно представить софт верную компанию, которая официально не использовала бы VCS для управления исходным кодом и координации работы инженеров. В этой главе мы поговорим о том, почему управление версиями стало нормой в про- граммной инженерии, и рассмотрим плюсы и минусы разных подходов к организации VCS. Мы уверены, что управление версиями должны использовать все инженеры без исключения, но дополнительно рекомендуем выбирать только те правила и процес- сы, которые подходят вашей организации. В частности, мы считаем, что «разработка в главной ветви», популяризированная ассоциацией DevOps 1 (подразумевающая наличие одного репозитория без отдельных веток для разрабатываемых версий), является наиболее легко масштабируемым политическим подходом, и мы постара- емся объяснить, почему это так. Что такое управление версиями? Многим читателям этот раздел может показаться скучным: в конце концов, управ- ление версиями достаточно распространено. Если хотите, можете пропустить этот раздел и сразу перейти к разделу «Источник истины». VCS — это система, которая отслеживает изменения (версии) в файлах. Она поддер- живает метаданные с информацией о наборе управляемых файлов, а совокупность 1 Ассоциация DevOps Research Association, которую приобрела компания Google в период между созданием рукописи этой главы и ее публикацией, подробно рассказывала об этом в ежегодном отчете «State of DevOps Report» и книге Николь Форсгрен и др. «Ускоряйся! Наука DevOps. Как создавать и масштабировать высокопроизводительные цифровые ор- ганизации» (Интеллектуальная литература, 2020). — Примеч. пер. Насколько мы можем судить, именно она популяризировала терминологию разработки в главной ветви. Что такое управление версиями? 323 копий файлов и метаданных называется репозиторием 1 . VCS помогает координи- ровать деятельность команд, позволяя нескольким разработчикам одновременно работать с одним и тем же набором файлов. Ранние VCS разрешали редактировать файл только одному человеку в каждый конкретный момент — такая блокировка позволяла установить очередность (согласовать понимание, «что новее»). Совре- менные системы гарантируют, что изменения в коллекции файлов, отправленных вместе, будут обрабатываться как единое целое (атомарно, то есть логическое изменение затронет все файлы в наборе). Такие системы, как CVS (популярная в 1990-х), в которых процедура фиксации не поддерживает атомарности, подвержены искажениям и потерям изменений. Атомарность устраняет вероятность непредна- меренного затирания предыдущих изменений, но требует отслеживания времени синхронизации последней версии — попытка сохранить изменения отклоняется, если какой-либо из отправляемых файлов изменен раньше момента последней син- хронизации локального разработчика. Поэтому в VCS рабочая копия управляемых файлов разработчика снабжается своими метаданными. В зависимости от архи- тектуры VCS копия репозитория может быть полной или содержать уменьшенное количество метаданных. Уменьшенная копия репозитория называется «клиентом» или «рабочей областью». Все это выглядит пугающе сложным. Так зачем нужна VCS? Какая особенность по- могла ей стать одним из немногих почти универсальных инструментов в разработке ПО и программной инженерии? Представьте работу без VCS. Небольшая распределенная группа разработчиков, работающих над небольшим проектом, чтобы скоординировать свои действия, может пересылать версии проекта друг другу. Этот подход лучше всего работает, когда редактирование выполняется не одновременно (инженеры работают в разных часовых поясах или, по крайней мере, в разное рабочее время). Если же сотрудники не знают, какая версия самая последняя, они должны как-то ее отследить. Любой, кто пытался сотрудничать с коллегами в несетевой среде, вероятно, вспомнит ужасы копирования файлов с именами вроде Presentation v5 - final - redlines - Josh’s version v2 И как мы увидим, когда нет единого согласованного источника истины, сотрудни- чество вызывает большие сложности и возрастает вероятность появления ошибок. Организация общего хранилища требует чуть больше инфраструктуры (для доступа к нему), но обеспечивает простую и очевидную координацию. Для начала можно организовать работу на общем диске, но со временем возникнет угроза перезаписи работы коллеги. Кроме того, непосредственная работа с общим хранилищем означа- ет, что любая задача, которая не поддерживает непрерывную сборку, начнет мешать всем в команде — если я внесу изменения в какую-то часть системы одновременно с вами и вы начнете сборку, то вы потерпите неудачу. Очевидно, что такой подход плохо масштабируется. 1 Формальное представление о том, что является репозиторием, почти не зависит от выбора VCS, но терминология может существенно отличаться в разных источниках. 324 Глава 16. Управление версиями и ветвями На практике невозможность блокировать файлы от записи и организовать слияние изменений, внесенных разными людьми, неизбежно приведет к конфликтам и переза- писи работы коллеги. Такая система, скорее всего, потребует внешней координации, помогающей решить, кто будет работать с тем или иным файлом. Если вы захотите предусмотреть блокировку файлов в ПО, то заново изобретете раннюю VCS, такую как RCS. Когда вы поймете, что предоставление разрешения на запись в файл кому- то одному — слишком грубое решение, и захотите организовать отслеживание на уровне строк, то снова подойдете к изобретению VCS. Если необходимость в каком- то структурированном механизме для управления сотрудничеством выглядит почти неизбежной, то почему бы не использовать готовый инструмент. Почему важно управлять версиями? В настоящее время управление версиями используется практически повсеместно, но так было не всегда. Самые первые VCS появились в 1970-х (SCCS) и 1980-х го- дах (RCS) — много лет спустя после первых упоминаний программной инженерии как отдельной дисциплины. Команды участвовали в «разработке многопользовательского многоверсионного ПО» ( https://arxiv.org/pdf/1805.02742.pdf ) еще до того, как в от- расли появилось формальное понятие управления версиями. Управление версиями возникло как ответ на новые проблемы цифрового сотрудничества. Потребовались десятилетия эволюции и популяризации, чтобы надежное и последовательное ис- пользование VCS превратилось в норму 1 . Итак, почему это стало настолько важным и почему кто-то еще может противиться идее применения VCS, несмотря на то что она выглядит очевидным решением? Напомню, что программная инженерия — это программирование во времени. Мы различаем (по числу усилий) непосредственное создание исходного кода и поддержку программного продукта с течением времени. Это базовое различие объясняет смысл внедрения VCS: на самом фундаментальном уровне VCS — это основной инструмент управления взаимосвязью между исходным кодом и временем. Управление версиями можно представить как расширение стандартной файловой системы. Если файло- вая система отображает имена файлов в их содержимое, то VCS отображает пары имя файла — время в содержимое и метаданные, необходимые для отслеживания последних точек синхронизации и истории версий. Управление версиями застав- ляет явно учитывать время. В большинстве случаев VCS также позволяет вводить 1 Я провел несколько публичных выступлений, в которых использовал «внедрение управления версиями» как канонический пример развития норм программной инженерии с течением времени. В 1990-х годах управление версиями считалось передовой практикой, но применя- лось не повсеместно. В начале 2000-х еще часто можно было встретить профессиональные группы, не использующие VCS. В настоящее время применение таких инструментов, как Git, стало обычным явлением даже среди студентов колледжей, работающих над личными проектами. Отчасти такой рост популярности управления версиями, вероятно, связан с со- вершенствованием инструментов (едва ли кто-то захочет вернуться к RCS), но в гораздо большей степени он обусловлен накопленным опытом и изменением норм. Что такое управление версиями? 325 дополнительную переменную в это отображение (имя ветви), разрешая тем самым существование параллельных отображений: VCS(имя_файла, время, имя ветви) => содержимое файла По умолчанию в переменной «имя ветви» передается общепринятое и стандартное имя, соответствующее главной ветви, такое как head , default или trunk Остающиеся (незначительные) сомнения в отношении неуклонного использова- ния VCS обусловлены объединением понятий программирования и программной инженерии. Мы обучаем программированию, учим программистов, проводим со- беседования при приеме на работу, уделяя основное внимание проблемам и методам программирования. Даже в такой компании, как Google, привыкли не требовать от новых сотрудников опыта работы с кодом дольше пары недель или навыков работы в команде. Учитывая такую практику, управление версиями не выглядит чем-то важным, поскольку оно решает проблемы, с которыми новый сотрудник может и не столкнуться (например, «отмена» не для отдельного файла, а для всего проекта), что усложняет распространение неочевидных преимуществ VCS. Тот же результат можно наблюдать в других софтверных компаниях, руководство ко- торых рассматривает работу технических специалистов как «разработку ПО» (сесть и написать код), а не как «программную инженерию» (создать код и поддерживать его работоспособность и ценность в течение долгого времени). Из-за восприятия программирования как основной задачи и слабого понимания взаимосвязи между кодом и временем легко посчитать чрезмерной роскошью «возврат к предыдущей версии, чтобы исправить ошибку». Помимо раздельного хранения версий и доступа к ним VCS позволяет преодолеть разрыв между процессами, выполняемыми в одиночку и в команде. С практической точки зрения именно по этой причине так важно использовать VCS в программной инженерии — она позволяет увеличивать масштабы команд и организаций, даже если кнопка «отмена» используется нечасто. Разработка, по своей сути, — это процесс ветвления и слияния, целью которого является координация усилий не только не- скольких разработчиков, но и одного разработчика в разные моменты. VCS снимает вопрос «какая версия более свежая?» Современные VCS автоматизируют операции, в которых легко допустить ошибку, например определение набора изменений, ко- торый был применен. VCS — это инструмент координации действий нескольких разработчиков или одного разработчика в разные моменты. Управление версиями настолько глубоко проникло в программную инженерию, что даже правовая и нормативная практики стали ему соответствовать. VCS позволяет официально регистрировать каждое изменение в каждой строке кода, что становит- ся все более востребованным для аудита. При совмещении внутренней разработки и использования стороннего исходного кода VCS помогает отследить происхождение каждой строки кода. 326 Глава 16. Управление версиями и ветвями Помимо технических и нормативных аспектов отслеживания действий во вре- мени и обработки операций синхронизации/ветвления/слияния управление версиями способствует появлению некоторых нетехнических черт поведения. Процедура фиксации изменений в VCS и получение журнала фиксаций застав- ляет инженеров остановиться и подумать: что изменилось с момента последней фиксации? Довольны ли они состоянием исходного кода? Момент размышлений, связанных с фиксацией, подведением итогов и отметкой задачи как выполненной, для многих может иметь свою ценность. Начало процесса фиксации изменения — идеальное время для выполнения операций из контрольного списка: статического анализа (глава 20), проверки охвата тестирования, выполнения тестов, анализа их результатов и т. д. Подобно любым другим процессам, управление версиями имеет свои издержки: кто- то должен настраивать, сопровождать и использовать VCS. Но не пугайтесь: почти всегда эти издержки невелики. Как ни странно, опытные инженеры-программисты инстинктивно используют управление версиями для любых проектов, которые про- существуют дольше одного-двух дней, даже когда работают в одиночку. Это доказы- вает, что ценность управления версиями (включая снижение риска возникновения ошибок) перевешивает издержки. Но мы признаем, что контекст имеет значение, и призываем руководителей самостоятельно принимать решения о внедрении VCS. Всегда стоит рассматривать альтернативы, даже в таком фундаментальном вопросе, как управление версиями. Честно говоря, в современной программной инженерии трудно представить задачу, решаемую без немедленного внедрения VCS. Понимая ценность и необходимость управления версиями, вы, вероятно, теперь задаетесь вопросом: какой тип управле- ния версиями предпочтительнее для вас? Централизованные и распределенные VCS На самом упрощенном уровне все современные VCS эквивалентны: если система поддерживает атомарную фиксацию изменений в пакете файлов, то остальная часть системы является просто пользовательским интерфейсом. Написав груду простых сценариев командной оболочки, можно реализовать общую семантику (не рабочий процесс) любой современной VCS. Поэтому решение, какая VCS «лучше», в первую очередь зависит от пользовательского опыта — основные возможности разных VCS одинаковы, но у каждой системы свои пользовательский опыт, именование, погра- ничные особенности и производительность. Выбор VCS похож на выбор формата файловой системы: если форматы достаточно современные, то различия между ними не имеют особого значения, гораздо важнее, каким содержимым вы наполните эту систему и как будете его использовать. Однако архитектурные отличия VCS могут упростить или усложнить принятие решений о конфигурации, политике использо- вания и масштабировании кода. С учетом этих различий VCS делятся на два типа: централизованные и децентрализованные. Что такое управление версиями? 327 Централизованные VCS В централизованных VCS используется модель с единым центральным репози- торием (вероятно, хранящимся на общем вычислительном ресурсе организации). Разработчик может хранить на своей локальной машине файлы, извлеченные из репозитория, но операции (добавление файлов, синхронизация, обновление существующих файлов и т. д.), влияющие на состояние этих файлов, должны выполняться на центральном сервере. Любой код, фиксируемый разработчиком, передается в центральный репозиторий. Первые реализации VCS были центра- лизованными. Самые ранние реализации VCS, появившиеся в 1970-х — начале 1980-х годов, такие как RCS, были ориентированы на блокировки и предотвращение возможности из- менения файлов несколькими пользователями. Вы могли скопировать содержимое репозитория к себе, но для редактирования файла требовалось установить блоки- ровку в VCS, чтобы гарантировать, что правки сможете внести только вы. По окон- чании редактирования необходимо было снять блокировку. Эта модель работала нормально, когда любое изменение происходило быстро и блоки на конкретный код ставил только один разработчик. Модель позволяла с легкостью вносить небольшие правки, например в файлах конфигурации, и сотрудничать в небольшой команде, члены которой работали в разные часы или с разными файлами. Однако в больших командах блокировка может стать предметом конкуренции 1 В ответ на проблему масштабирования появились VCS, ставшие популярными в 1990-х — начале 2000-х годов. Они не использовали вышеописанные блокировки, а отслеживали синхронно добавленные изменения, требуя, чтобы новые правки основывались на самой последней версии каждого зафиксированного файла. CVS, которую можно считать усовершенствованной версией RCS, работала сразу с паке- тами файлов и позволяла нескольким разработчикам посылать измененные файлы одновременно: если изменения были выполнены на основе базовой версии, хра- нящейся в репозитории, CVS разрешала автору изменений выполнить фиксацию. Система Subversion продвинулась еще дальше и обеспечила истинную атомарность фиксаций, отслеживание версий и лучшее отслеживание редких операций (таких, как переименование, использование символических ссылок и т. д.). Модель централизо- ванного репозитория и клиента до сих пор продолжает использоваться в Subversion и в большинстве коммерческих VCS. 1 Забавно: чтобы проиллюстрировать это, я посмотрел, какие изменения (ожидающие/не- отправленные) внесены гуглерами в один из самых популярных файлов в моем последнем проекте. На момент написания этой главы в состоянии ожидания находились 27 изменений, 12 — от членов моей команды, 5 — от членов соседних команд и 10 — от инженеров, с ко- торыми я никогда не встречался. Блокировки работают, как ожидалось. Из этого следует, что технические системы или политики, требующие непосредственной координации, не подходят для круглосуточной и распределенной разработки ПО. 328 Глава 16. Управление версиями и ветвями Распределенные VCS Начиная с середины 2000-х годов, многие популярные VCS превратились в распре- деленные системы управления версиями (DVCS, distributed version control system). Примерами таких систем могут служить Git и Mercurial. Основное концептуальное отличие DVCS от более традиционных централизованных VCS (Subversion, CVS) за- ключено в ответах на вопрос: «Где фиксировать изменения?» или, возможно, «Какие копии этих файлов считаются репозиторием?» В DVCS нет ограничений центрального репозитория: если у вас есть копия (клон) репозитория, то у вас есть репозиторий, в котором можно фиксировать изменения, а также все метаданные, необходимые для получения разнообразной информации, например истории изменений. Стандартный рабочий процесс с использованием такой системы включает клонирование существующего репозитория, внесение изменений, их локальную фиксацию, а затем передачу набора фиксаций в другой репозиторий, который может быть или не быть источником копии. Наличие цен- трального репозитория является чисто концептуальным вопросом политики, а не фундаментальным условием технологии VCS или лежащих в ее основе протоколов. Не объявляя один конкретный репозиторий источником истины, модель DVCS позволяет улучшить автономную работу и сотрудничество. Ни один из репозито- риев не может быть «впереди» или «позади», потому что изменения фактически не проецируются на линейную шкалу времени. Однако, учитывая типичные сценарии использования, централизованная и распределенная модели в значительной степе- ни взаимозаменяемы: если централизованная VCS четко определяет центральный репозиторий с помощью технологии, то большинство экосистем DVCS точно так же определяют центральный репозиторий, но уже политическими методами. То есть большинство проектов DVCS построено на одном концептуальном источни- ке истины (например, на конкретном репозитории в GitHub). Модели DVCS, как правило, предполагают более распределенный сценарий использования и широко распространены в проектах с открытым исходным кодом. В настоящее время доминирующей VCS является Git, которая реализует модель DVCS 1 . Если вы затрудняетесь в выборе VCS, используйте ее — поступая так же, как другие, вы найдете определенные преимущества. Если вы ожидаете необычные сценарии использования, соберите информацию о нескольких системах и сопоставьте их достоинства и недостатки. В Google сложилось неоднозначное отношение к DVCS: наш основной репозиторий основан на собственной (массивной) централизованной VCS. Периодически предпри- нимаются попытки интегрировать в нее дополнительные стандартные возможности, чтобы соответствовать рабочему процессу, к которому наши инженеры (особенно ну- глеры) привыкли, работая во внешних проектах. К сожалению, все попытки перейти на использование более распространенных инструментов, таких как Git, оказались невозможными из-за огромного размера кодовой базы и большого числа пользова- 1 См. результаты опроса разработчиков на сайте Stack Overflow ( https://oreil.ly/D173D ), 2018 г. |