Книга «Делай как в Google. Разработка программного обеспечения»

Основываясь на опыте Google, инженеры-программисты Титус Винтерс и Хайрам Райт вместе с Томом Маншреком делают откровенный и проницательный анализ того, как ведущие мировые практики создают и поддерживают ПО. Речь идет об уникальной инженерной культуре, процессах и инструментах Google, а также о том, как эти аспекты влияют на эффективность разработки.
Вы изучите фундаментальные принципы, которые компании разработчиков ПО должны учитывать при проектировании, разработке архитектуры, написании и сопровождении кода.

Системы и философия сборки

Если спросить инженеров в Google, что больше всего им нравится в компании (помимо бесплатной еды и первоклассного оборудования), то можно услышать удивительный ответ: им нравится система сборки. В Google было потрачено много сил и времени на создание собственной системы сборки с нуля. Усилия оказались настолько успешными, что Blaze — основной компонент системы сборки — несколько раз был повторно реализован экс-гуглерами в других компаниях2. В 2015 году Google наконец открыла исходный код Blaze под названием Bazel (https://bazel.build).

Назначение системы сборки

По сути, все системы сборки предназначены для преобразования исходного кода, написанного инженерами, в выполняемые двоичные файлы, понятные машинам. Хорошая система сборки обычно обладает двумя важными свойствами:

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

Безошибочность
Каждый раз, когда разработчик запускает сборку на любом компьютере, он должен получать один и тот же результат (при условии, что исходные файлы и другие входные данные совпадают).

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

Системы сборки предназначены не только для людей; их также могут использовать машины, чтобы автоматически создавать сборки для тестирования кода или выпуска продукта в продакшен. Фактически большинство сборок в Google запускаются автоматически, а не вручную. Почти все наши инструменты разработки так или иначе связаны с системой сборки, что дает огромную выгоду всем, кто работает с нашей базой кода. Вот небольшой пример использования нашей автоматизированной системы сборки:

  • Код автоматически собирается, тестируется и передается в продакшен без участия человека. Разные команды проводят сборки с разной скоростью: одни еженедельно, другие — ежедневно, а третьи — настолько быстро, насколько это возможно (глава 24).
  • Изменения, внесенные разработчиком, автоматически тестируются, когда он отправляет их для обзора (глава 19), благодаря чему автор изменений и рецензент могут сразу увидеть любые проблемы, возникшие из-за изменений на этапе сборки или тестирования.
  • Изменения повторно тестируются непосредственно перед включением их в главную ветвь репозитория, что значительно уменьшает вероятность сохранения неработоспособных изменений.
  • Авторы низкоуровневых библиотек могут тестировать свои изменения во всей базе кода и гарантировать, что эти изменения безопасны для миллионов тестов и двоичных файлов.
  • Инженеры могут вносить крупномасштабные изменения, затрагивающие десятки тысяч исходных файлов (например, переименовывать общий символ), и безопасно отправлять в репозиторий и тестировать эти изменения. Подробнее о крупномасштабных изменениях в главе 22.
  • Все это возможно только благодаря инвестициям Google в свою систему сборки. Конечно, Google уникальна с точки зрения масштаба, однако любая организация любого размера может получить аналогичные преимущества, включив в свой производственный процесс современную систему сборки. В этой главе мы выясним, какие системы сборки считаются в Google «современными» и как их использовать.

    Так ли необходимы системы сборки?

    Системы сборки позволяют масштабировать разработку. Как будет показано в следующем разделе, отсутствие надлежащей системы сборки порождает проблемы масштабирования.

    Мне достаточно компилятора!

    Потребность в системе сборки может быть неочевидна. В конце концов, едва ли кто-то из нас использовал систему сборки, когда учился программированию — почти все мы начинали с таких инструментов командной строки, как gcc или javac, или их эквивалентов в IDE. Пока весь исходный код располагается в одном каталоге, вполне можно использовать такую команду:

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

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

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

    Компилятор также не знает, как обрабатывать внешние зависимости, например сторонние файлы JAR в Java. Часто лучшее, что можно сделать в отсутствие системы сборки, — загрузить зависимость из интернета, поместить ее в папку lib на жестком диске и настроить компилятор для чтения библиотек из этой папки. Однако со временем легко забыть, какие библиотеки туда помещены, откуда они взялись и используются ли они до сих пор. И останется надеяться только на удачу при их обновлении по мере выхода новых версий.

    Сценарии командной оболочки спасут ситуацию?

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

  • Поддержка сборки становится все более утомительной. По мере усложнения системы работа со сценариями начинает отнимать столько же времени, сколько работа с фактическим кодом. Отладка сценариев командной оболочки — трудная задача, все больше и больше нестандартных случаев начинают наслаиваться друг на друга.
  • Сборка происходит медленно. Чтобы гарантировать актуальность всех зависимостей, вы запускаете сценарий, который собирает их по порядку при каждом запуске. Вы задумываетесь о добавлении логики для определения частей, которые действительно необходимо собрать повторно, но эта задача кажется ужасно сложной. Или, может быть, вы думаете о том, чтобы каждый раз указывать, какие части следует пересобрать, но это опять приводит вас в исходную точку.
  • Хорошая новость: пора выпускать новую версию! Вы вспоминаете, какие аргументы нужно передать команде jar, чтобы выполнить окончательную сборку (https://xkcd.com/1168), как выгрузить результат и отправить в центральный репозиторий, как создать и разместить обновления в документации, как отправить пользователям уведомления. Хм-м, пожалуй, для этого нужно написать еще один сценарий…
  • Катастрофа! Ваш жесткий диск выходит из строя, и теперь вам нужно воссоздать всю систему. Вы были достаточно предусмотрительны и хранили все файлы с исходным кодом в VCS, но как быть с библиотеками, загруженными из интернета? Сможете ли вы найти их снова и гарантировать соответствие версий? Ваши сценарии, вероятно, зависели от определенных инструментов, установленных в определенных местах, — сможете ли вы воссоздать идентичную среду, чтобы сценарии работали как раньше? А как быть с переменными окружения, которые вы настроили давным-давно, чтобы добиться правильной работы компилятора, а потом забыли о них?
  • Несмотря ни на что, ваш проект достаточно успешен, и вы можете нанять еще нескольких инженеров. Теперь вы понимаете, что предыдущие проблемы еще не были катастрофой — теперь вам нужно снова и снова проходить один и тот же болезненный процесс настройки окружения для каждого нового разработчика. И несмотря на прилагаемые усилия, все системы разработчиков будут немного отличаться друг от друга. Часто то, что работает на одном компьютере, не работает на другом, и каждый раз требуется несколько часов, чтобы правильно настроить пути к инструментам или проверить версии библиотек, чтобы выяснить, в чем разница.
  • Вы решаете автоматизировать систему сборки. Теоретически для этого достаточно поставить новый компьютер и настроить на нем запуск сценария сборки по ночам с помощью cron. Вам по-прежнему нужно пройти болезненный процесс настройки, но теперь у вас нет преимуществ человеческого мозга, способного обнаруживать и решать мелкие проблемы. Теперь, входя по утрам в систему, вы видите, что ночная сборка потерпела неудачу, потому что вчера разработчик внес изменение, которое работало в его системе, но не работает в системе автоматической сборки. Каждая такая проблема легко исправляется, но делать это приходится так часто, что каждый день вы тратите массу времени на поиск и применение простых исправлений.
  • По мере развития проекта сборки выполняются все медленнее и медленнее. Однажды, ожидая завершения сборки, вы с грустью смотрите на пустующий рабочий стол коллеги, который находится в отпуске, и задумываетесь о возможности задействовать простаивающие вычислительные мощности.
  • Это проблема масштабирования. Для одного разработчика, работающего над парой сотен строк кода в течение одной-двух недель (типичный опыт младшего разработчика, только что окончившего университет), компилятора более чем достаточно. Сценарии помогут вам продвинуться немного дальше. Но как только вам потребуется координировать действия нескольких разработчиков и работу их компьютеров, даже идеального сценария сборки будет недостаточно, потому что очень трудно учесть незначительные различия между системами. На этом этапе нужно начинать инвестировать в систему сборки.

    Современные системы сборки

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

    Все дело в зависимостях

    Рассматривая проблемы, описанные выше, мы снова и снова наблюдали одну и ту же закономерность: намного легче управлять своим кодом, чем его зависимостями (глава 21). Зависимости могут быть самыми разнообразными: от задачи (например, «отправить документацию, прежде чем отметить выпуск завершенным») или от артефакта (например, «для сборки кода нужна последняя версия библиотеки компьютерного зрения»). Иногда ваш код может иметь внутренние зависимости от других частей кодовой базы или внешние зависимости от кода или данных, принадлежащих другим командам (в вашей или сторонней организации). Но в любом случае идея «мне нужно это, чтобы получить то» постоянно повторяется в системах сборки, и управление зависимостями, возможно, является их самой фундаментальной задачей.

    С полным содержанием статьи можно ознакомиться на сайте “Хабрахабр”:

    https://habr.com/ru/company/piter/blog/573138/

    Источник



    Leave A Reply

    Your email address will not be published.