После недавнего удаления модуля на 11 строк кода из npm, которое сломало всю Node.js инфраструктуру, я по-новому взглянул на то, как в проектах на Go реализованы зависимости от других пакетов.

Изначально, при знакомстве с go я был крайне недоволен отсутствием возможности задавать зависимости от конкретных версий (зависимость указывается только от репозитория, т.е. от master ветки) - ведь апстрим может ломать обратную совместимость, и твой проект просто не соберется. Причем я сам с этой проблемой столкнулся, и это было очень неприятно.

К счастью, не я один страдал от этой недоработки, и для решения этой проблемы в go1.5 добавили экспериментальный vendoring зависимостей, который в 1.6 включили по-умолчанию.

Теперь появилась возможность сложить все зависимости в директорию vendor/ внутри своего проекта, и все утилиты go будут с ними корректно работать.

Тут возникла дилемма - добавлять ли vendor/ в git вместе с проектом?

Glide, популярная утилита для работы с зависимостями в go, которой я пользуюсь, дает следующие рекомендации:

  • для библиотек не добавлять vendor/ в VCS;
  • для утилит добавлять vendor/ в VCS для обеспечения повторяемости билдов у пользователей.

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

Решение это не идеальное, но создание очередного навороченного менеджера пакетов тоже не подарок, и проблем (как мы видим на примере того-же Python) с ним хватает.

А тут мы застрахованы и от удаления самого репозитория с нашей зависимостью, и от поломанной обратной совместимости. Кстати, насколько мне известно, все большие проекты работают именно по такой схеме - хранят все зависимости у себя.

При этом радует то, что для установки утилит с зависимостями в vendor/ в VCS не нужен никакой менеджер зависимостей типа Glide/Godeps и т.п. - мухи отдельно, котлеты отдельно. Пользователь просто делает go get my_package и радуется. А мы используем менеджер зависимостей по вкусу и тоже радуемся - все довольны.

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

Лично для меня это скорее достоинство.


Comments

comments powered by Disqus