Re[9]: Окончательное решение ада зависимостей?
От: · Великобритания  
Дата: 17.05.25 10:08
Оценка:
Здравствуйте, Manticore, Вы писали:

M>·>Ну в том вопросе было про библиотеки и компоненты. Я вот до сих пор не понял как же компилятор ругается, если компоненты подключаются как зависимости. Вот конкретный пример. Допустим ты разрабатываешь rest-сервис. Тебе надо http-компонент и ssl-компонент. Компоненты разрабатываются и распространяются хрен знает когда и кем через какой-то публичный репо. Для твоего сервиса требуется http-3.1.4 (зависит от logger-1.0) и ssl-2.7.1 (зависит от logger-2.0). В твоём коде вообще ничего с logger нет, ты про него ничего не знаешь и знать не хочешь. Т.е. никакого "подключаешь несколько разных версий одной бинарной либы" у тебя нет. Несколько версий приходят транзитивно по зависимостям, у себя ты просто подключаешь соответствующие компоненты... и? В каком конкретно месте ругнётся компилятор?

M>Если типы logger не видны в публичном API http и ssl, то ни в каком. Если logger-2.0 не умеет уживаться в одном процессе с logger-1.0, это баг logger-2.0.
Ну дык, а ты думаешь в рай попал, где багов нет? В этом-то и есть суть ада зависимостей.

M>·>Допустим компилятор даже ругнулся. Как ты будешь делать "конвертирование между ее публичными типами"? В каком месте?

M>Там где они используются совместно. Если одна зависимость возвращает тип из подзависимости, и это значение надо передать в другую зависимость которая использует подзависимость другой версии.
Представь себе у тебя 5 зависимостей и все они друг-другу что-то передают. Например прокидывают объекты через одну очередь. Тебе придётся писать 2^5 конверсий из каждой версии в каждую, даже если они все совместимы по типам/сигнатурам?

M>·>Тебе придётся брать и изучать исходники чужих компонент, про которые ты ничего не знаешь и вообще не копенгаген и пытаться их совместить, пересобрать и передиплоить в свой приватный репо, в публичный — у тебя пермиссий нет. Собственно это и есть ад.

M>В 99.9% случаев достаточно чтения документации. Например, я использую в одной своей либе crypto-bigint 0.6 и 0.7-pre. Библиотека эллиптических кривых возвращает мне порядок кривой в виде типа crypto_bigint::Uint из 0.6, а мне надо передать это значение в другую библиотеку которая использует 0.7-pre. Я смотрю в документацию, crypto_bigint::Uint можно конвертировать в указатель на массив цифр, можно сериализовать. Соответственно, в 0.7 можно восстановить из этого.
Эээээ. А как это согласуется с "Расте уважают semver"? Почему ВНЕЗАПНО просто нельзя использовать 0.7?

M>Насчет "пересобрать и передиплоить в свой приватный репо" я, если честно, вообще не понял о чем ты.

Чтобы код для адаптации версий между собой реюзать из разных мест. В моём примере выше — создать "http-3.1.4_withLogger2", т.е. адаптированный http-3.1.4 для совместимости с logger-2.0.

M>>>О точном определении "ада зависимостей" — к ТС.

M>·>Ну я бы хотел просто понять какой же конкретно ад зависимостей по твоему пониманию был решён в rust?
M>Конфликт между совместимыми по API зависимостями. Т.к. в Расте уважают semver, любая более поздняя но совместимая по семверу либа может без проблем заменить более раннюю. Так что можно существенно облегчить граф зависимостей. Возможно, ТС имел в виду именно это.
Ну так и semver не в расте придумали. Конечно, подход "всё умеет уживаться друг с другом" — это и есть сабж. Но баги это не отменяет. Да и усложняет сильно всё. Что надо полный backward compatibility иметь, что раздувает код всякими "конвертировать в указатель на массив цифр, можно сериализовать".

M>·>Всё равно не понимаю причём тут компилятор. Обычно этим занимается package manager или project management tool. Т.к. работа идёт не на уровне сорцов, а на уровне пакетов/crates/dll/jar/etc. Во многих системах уже много лет есть механизмы описания и валидации графа зависимостей на совместимость... Что нового появилось в rust?

M>См. выше. Но, повторю, это лишь моя версия, я знаю что в Питоне граф зависимостей плоский, так что подход Раста по сравнению с ним — это шаг вперед. Но в JS зависимости в виде дерева, так что может там тоже зависимости объединяют. Что там есть "во многих системах" я не знаю, приводи конкретные примеры, сравним.
Ну все эти pinned-версии, range-версии, и т.п. есть в большинстве pm тулзов.

M>>>Нет. Подзависимости с версиями, например, 1.1 и 1.2 будут объединены в одну зависимость с версией как минимум 1.2. Если подзависимости требуют точные версии (=1.1 и =1.2), то резолвер выдаст ошибку (поэтому пинить версии в нормальных релизах считается дурным тоном и практически никогда не делается). Несколько копий зависимостей может быть только если их мажорные версии различаются. См. https://doc.rust-lang.org/cargo/reference/resolver.html

M>·>cargo — это вроде как не компилятор.
M>Нет, не компилятор, но объединение зависимостей в cargo убирает большинство "несовместимостей", так что компилятор ругается только на то что автоматически не исправить. "что с чем не совместимо" очевидно из ошибки компилятора, "как же это теперь решать" в большинстве случаев очевидно из документации, "как собственно убедиться, что решение будет работать" — для этого пишут тесты.
Ну вроде про автоматическое исправление это и есть совместимость по типам-сигнатурам. Неясно причём тут номера версий.

M>·>Сорцы чего? Я не понял. Возвращаюсь к примеру выше. Компилируя свой rest-сервис откуда возьмутся сорцы http/ssl/logger? Они все одновременно будут компилится?!

M>В Расте, да.
Это ж сколько оно компилируется... И главное зачем..

M>·>Если так, то что тебе, как разработчику rest-сервиса дадут 100500 ошибок компиляции в тоннах кода http и ssl компонент?

M>Откуда ошибки-то? Если подзависимости используются внутри зависимостей это их внутреннее дело, пока они не светят их типы в публичном API. И даже тогда ошибка будет только если ты тип из одной версии попытаешься передать куда-то где нужен тип из другой. Я регулярно вижу в дереве зависимостей один и тот же крейт разных версий. Проблем это не создает, кроме времени компиляции.
А вот такое не создаёт проблем? В зависимости где какие версии — количество инстансов одной переменной разное.

The final rustc invocation by cargo will only add the shared dependency once. If you use two different incompatible versions of the shared dependency, then it will be added "twice".

Как вообще с таким справляться?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.