Что делают Bundler & Rubygems, Homebrew’s Mac, Linux Apt (Advanced Package Tool) и Debian Packages, JavaScript’s NPM & Yarn, Pyphon PIP и практически у любого другого установщика или менеджера зависимостей, кроме того факта, что они работают на зависимости? Ни один из них не может справиться со всеми краевыми случаями установки зависимостей, потому что они «наивно» управляют зависимостями.
Этот пост не стремится позорить или смягчить работу, которая вошла в эти невероятные фрагменты программного обеспечения (я внес свой вклад в Бундлер сам и продолжаю делать это! ). Менеджеры зависимостей, которые мы действительно предоставляют нам бесценным сервисом, и я очень благодарен за них. Этот пост, однако, стремится распаковывать это утверждение о правом управлении зависимостями, показывает вам альтернативу и изучить различия.
Этот пост предназначен для разработчиков, которые немного знают об управлении зависимостями, но все лучше, чтобы объяснить концепции на этом пути (пожалуйста, прокомментируйте, если вы ничего не поймете, и я сделаю все возможное, чтобы объяснить это). Этот пост, вероятно, не слишком упрощен для людей с более тщательным пониманием управления зависимостями. Итак, пост предназначен для разработчиков в целом. В то время как я склонен использовать больше примеров на основе рубины, концепция одинаково относится к другим языкам и программному обеспечению, таким как JavaScript, Java, Python, Linux и Mac.
Наслаждаться!
Как работают системы зависимости?
Во -первых, давайте начнем с того, как функционируют эти установщики/менеджеры зависимости. Все они работают примерно одинаково:
- Принесите некоторый индекс/список [зависимостей]
- Основываясь на некотором определении желаемых зависимостей, выполните алгоритм разрешения зависимостей, предназначенный для раздачивающихся подразделений и поиска версии, которая соответствует каждому требованию
- Список желаемых зависимостей может быть получен различными способами, такой файл (например,
package.json
,Требования.txt
,Brewfile
иGemfile
) или команда (например, я пряжа установка Foo,
Gem установить foo, или
apt-get Установите foo),
Установите список полученных зависимостей из (2)
- Список желаемых зависимостей может быть получен различными способами, такой файл (например,
Эти зависимости устанавливаются в глобальное или локальное пространство имен, могут быть связаны со статическими системами системы и могут полагаться на состояние системы при установке зависимостей.
Пример
Давайте посмотрим на пример этой системы в игре.
На этой высокопрофессиональной диаграмме мы видим, что когда мы работаем над my_app
Тогда мы зависим от Ruby, MySQL и Rmagick
Анкет MySQL ожидается в /usr/local/bin/mysql
и указывает на MySQL 5.7, Rmagick
зависит от Imagemagick@6
, что зависит от pkg-config
и Freetype
(среди прочего).
Теоретически эта система работает хорошо. Это просто с четким направленным графом зависимости. Тем не менее, это идеальный сценарий и редко фактический результат реального мира.
Проблема возникает в системе, когда у вас есть несколько приложений, работающих бок о бок. Представьте себе сценарий, где my_app
и nother_app
Оба зависят от MySQL. Первый зависит от MySQL 5.7, а второй — на MySQL 5.5. К сожалению, все зависимости предполагают, что MySQL находится в /usr/local/bin/mysql
Анкет Этот путь часто жестко кодируется во многих зависимостях, или мы используем тот же каталог, установленный некоторой глобальной переменной и ожидаем, что двоичный файл будет называться mysql
. Этот факт означает, что у нас может быть только одна версия, работающая за раз без какого -то хакерского жонглирования глобально установленными переменными среды.
Что мы могли бы сделать, так это сделать MySQL 5.5 быть другим двоичным именем (например, /usr/local/bin/mysql_55
), но большинство пакетов и систем ожидают mysql
не mysql_55
И так это также вызывает много проблем.
Этот сценарий подразумевает, что нам нужно обновить все зависимые приложения одновременно, чтобы иметь возможность изменить версию MySQL. Эта проблема раздражена, поскольку у нас есть больше приложений/услуг, так как есть больше шансов на это и больше возможностей для перекрытия зависимостей.
Что это значит?
Эта проблема распространена у большинства современных менеджеров зависимостей. Мы допустили ошибку, предполагая, что только одна версия программного обеспечения Piece может работать одновременно — или, возможно, преднамеренное упрощение. Я подозреваю, что мы сделали это так далеко, потому что серверы, особенно контейнерные услуги, часто означают, что система работает только в одном приложении. Однако на своем собственном компьютере вы можете запустить несколько приложений одновременно.
Я видел, как эта проблема часто возникала с зависимостью системы от ImageMagick (программное обеспечение для манипулирования программным изображением), MySQL (программное обеспечение базы данных) и линию чтения (Ruby, Python и другие языки зависят от этого. При изменении линии чтения вам, возможно, придется перекомпилировать все версии Ruby и Python, и все установленные драгоценные камни/яйца/колеса/зависимости).
Вы можете смягчить эту проблему с такими шаблонами, как использование Docker-Compose
Анкет Docker-Compose
Паттерн помещает весь ваш код в контейнер, так что проблема с множеством версий не может произойти так же легко. Этот шаблон, однако, означает, что ваш редактор теперь должен быть способен работать в результирующем экземпляре Docker, или вам нужно синхронизировать свои файлы с местной машиной (который я видел, управляя сотнями экземпляров этой модели, вызвать Множество проблем синхронизации и путаницы в том, где лежит источник истины).
Так без Docker-Compose
(Что все еще может достичь этого случая края!), Мы говорили о том, как мы не можем иметь дубликаты версий в то же место Из -за именования, но мы может иметь несколько версий в разных местах . Проблема становится управлением этими разными местами и рассказывает зависимости, как запускать в этом контексте.
Существует система, которая учитывает все преимущества управления зависимостями и может обрабатывать различные места, называемые NIX.
Мы только что говорили о том, как управление зависимостями наивно в большинстве современных систем зависимостей. Я считаю, что это реликвия из моментов, когда у систем было меньше зависимостей и меньше места на жестком диске, чтобы сохранить эти зависимости.
Поскольку количество зависимостей и размер этих зависимостей продолжают расти, было невозможно держать их на том же небольшом жестком диске 1990 -х годов при разработке некоторых более старых программного обеспечения для управления зависимостями, такими как APT Linux (Advanced Package Tool) В 1998 году Rubygems (Ruby) в 2003/2004 годах, Disutils (Python) 1998 года, PYPI (Python) 2003 года. Проблема размера жесткого диска-моя теория, и я не буду слишком глубоко погрузиться в нее, но я чувствую, что это дает некоторую сочувствие к решениям 15-25 лет назад. Я также подозреваю, что управляющие зависимостями все вроде «скопировали» друг друга на протяжении многих лет, не переоценивая базовые теории зависимости или сознательно поддерживать упрощение. Тем не менее, Менеджеры зависимостей, которых мы должны предоставить нам бесценную услугу, и я очень благодарен за них , но я думаю, что могут быть некоторые улучшения.
Что такое NIX?
Nix — это менеджер пакетов, который «функциональный» и «чистый». Это означает, что он рассматривает пакеты, такие как значения на чисто функциональных языках программирования, таких как Haskell. Эти свойства NIX преобразуют, чтобы означать, что пакеты создаются функциями, которые не имеют побочных эффектов и не могут измениться.
Этот метод отличается от такой системы, как Homebrew, NPM и Rubygems, которая может по -разному установить пакет, если у вас есть различные другие установленные программные обеспечения, конкретные пакеты в определенных местах или установленные переменные среды.
Вместо этого NIX опирается на систему для создания всего каталога зависимостей и версий зависимостей с построенным хэшем. Хэш построен, принимая во внимание все, что используется для построения пакета, поэтому мы можем гарантировать, что он уникален для любой настройки сборки. Затем, вместо того, чтобы ссылаться на MySQL напрямую, NIX относится к хешированной копии через символику. Эта настройка означает, что мы можем ссылаться на одно и то же двоичное имя (например, mysql
, который мы видели, требуется), но она указывает на другую версию на основе приложения, которое вы используете, и в некоторых случаях — другая версия Для разных зависимостей. Вы можете увидеть это на следующих диаграммах:
Чистые пакеты
Когда я говорю «чистый пакет», я имею в виду, что на упаковку не влияют и не влияют на что -либо вне указанного, что означает, что переменные среды, другие системные зависимости и Даже твое Главная
и Tmpdir
Справочники не влияют на результирующую зависимость.
На Linux зависимости создаются с использованием того, что известно как вывод в практически изолированной области вашей системы. На Mac у вас нет доступа к Tmpdir
или ДОМ
И обе эти переменные среды установлены на пятна, которых нет. Точно так же Путь
пуст, что сообщает вашей системе, где найти зависимости, поэтому у вас нет доступа к своим заранее установленным зависимостям.
Вместо того, чтобы полагаться на то, что было ранее в системе, вы указываете точно Что нужно, чтобы запустить и построить. NIX использует только то, что ранее установлено в системе NIX, если и только тогда, когда рассчитываемый хэш (который определяет, совместимо), соответствует хеш запрашиваемой зависимости, в противном случае NIX строит новый.
Этот метод создает гарантированный нециклический график зависимости, свободный от конфликтов, и является способом «правильно» обрабатывать все случаи управления зависимостью.
Что я могу сделать?
Так что ты можешь сделать? Честно говоря, вы, вероятно, сейчас не можете сделать много без кучи работы. Тем не менее, я надеюсь, что это поможет вам понять, что вы испытываете конфликты зависимости. Если вы не хотите вложить время, чтобы переключиться на nix-os
(дистрибуция Linux), nix-shell
(Подборная, которая обрабатывает активацию соответствующих зависимостей) или написание собственной интеграции с NIX, тогда у вас, вероятно, нечего изменить.
Тем не менее, если вы работаете в более крупной организации со многими взаимосвязанными услугами, то может стать более насущным, и NIX может стать более насущным. В качестве эталона, в компании, где я работал, с примерно 1000 членов в команде RND, 50% проблем поддержки внутренних разработчиков были связаны с управлением зависимостями.
Последнее слово
Мы рассмотрели, как большинство современных систем управления зависимостями не обрабатывают краевой случай в управлении зависимостями. Этот случай края может быть достигнут, имея 2 разных и расходящихся требования для зависимости, вызывая конфликт, потому что мы можем использовать только по одному за раз. Затем мы изучили NIX и как это решает эту проблему, используя изолированную систему сборки и функционально связанную систему. Я не думаю, что у кого-то есть что-то, что можно сделать, без большого переписывания систем зависимостей, но мы можем улучшить сообщения об ошибках!
Я надеюсь, что соответствующим образом управляемое управление зависимостями улучшится в будущем, станет гораздо простым и гораздо более доступным. На данный момент, если вы пишете диспетчер зависимостей, пожалуйста, посмотрите на то, что сообщения об ошибках более ясны, когда зависимости вступают в конфликт, и обеспечивайте лучшее обмен сообщениями об ошибках (используя методы, которые я описываю в моей презентации Crobykaigi Conference в 2018 году !).
Ресурсы
Если вы хотите прочитать больше о NIX, вот несколько ресурсов:
- http://notes.burke.libbey.me/learning-nix/
- Мой друг написал кучу вещей, которые он узнал о NIX. Это довольно полезно!
- https://nixcloud.io/tour/
- Эта ссылка является экскурсией по функциональному языку NIX. Это довольно отличный тур, который может быть использован для изучения отличного способа учить, в дополнение к изучению языка NIX.
- https://nixos.org/nixos/nix-pills/
- Это несколько десятков «таблеток» размером с укус, которые позволяют вам принимать небольшие дозы NIX, чтобы узнать
- https://nixos.org/~eelco/pubs/phd-thesis.pdf
- Никс пришел из работы на докторскую степень Тезис голландского компьютерного ученых. Их сосредоточилось на создании математически и логически звуковой системы, и я думаю, что они достигли этого
Другие полезные ссылки
- Nix Packages Repo: https://github.com/nixos/nixpkgs
- NIX OS Руководство: https://nixos.org/nixos/manual/
- Nix Packages Manual: https://nixos.org/nixpkgs/manual/
- Неофициальный Nix Wiki: https://nixos.wiki
Спасибо за чтение!
Оригинал: «https://dev.to/jules2689/the-common-edge-case-all-dependency-managers-miss-in4»