.NET Core и Dependency Hell?
От: fmiracle  
Дата: 20.10.16 09:24
Оценка: 2 (1)
Изучаю новую .net core
Запуск под Линукс — прекрасно.
Консольные тулы — отлично.

Разбивка всего на отдельные мелкие-мелкие компоненты — тоже хорошо, но вызывает опасения. Удачный пример такой разбивки есть — нода с ее npm. Но нода и npm позволяют приложению использовать одновременно несколько разные версий одной библиотеки и это дает возможность спокойно разрабатывать эти отдельные модули реально независимо друг от друга и не переживать про то, какую версию библиотек при этом используешь ты и какую, возможно, будут использовать пользователи твоей библиотеки.

А что с .net Core?
Описание nuget
https://docs.nuget.org/ndocs/consume-packages/dependency-resolution

Показывает, что если приложение использует Сборку1 и Сборку2, а Сборка1 использует Сборку2, но другой версии, то использоваться будет единственная версия Сборки2, определяемой приложением.

Но тут возможны очень неприятные неожиданности, если окажется, что Сборка1 корректно работает только с той, своей версией Сборки2, а с новой версией работает, но некорректно

Проблема есть или я что-то неправильно понимаю?
Отредактировано 20.10.2016 9:29 fmiracle . Предыдущая версия . Еще …
Отредактировано 20.10.2016 9:28 fmiracle . Предыдущая версия .
Re: Broken diamond
От: Qbit86 Кипр
Дата: 20.10.16 09:44
Оценка: 6 (1)
Здравствуйте, fmiracle, Вы писали:

F>Но нода и npm позволяют приложению использовать одновременно несколько разные версий одной библиотеки и это дает возможность спокойно разрабатывать эти отдельные модули реально независимо друг от друга и не переживать про то, какую версию библиотек при этом используешь ты и какую, возможно, будут использовать пользователи твоей библиотеки.


Предположим, библиотека Foo использует библиотеку Qux-v1 публично, скажем, создаёт и возвращает типы из библиотеки Qux-v1. А библиотека Bar использует библиотеку Qux-v2 тоже публично, скажем, принимает в параметрах типы из Qux-v2. Как npm организует одновременное использование Foo и Bar, скажем, передачу экземпляров Qux из Foo в Bar?
Глаза у меня добрые, но рубашка — смирительная!
Re: .NET Core и Dependency Hell?
От: Sinix  
Дата: 20.10.16 10:16
Оценка: 4 (2) +1
Здравствуйте, fmiracle, Вы писали:

F>Изучаю новую .net core.


F>Разбивка всего на отдельные мелкие-мелкие компоненты — тоже хорошо, но вызывает опасения.

Оно доделано, но только наполовину.

Проблема в том, что подключение одной библиотеки легко заканчивается десятком подтянутых зависимостей в project references и эт точно не есть хорошо.
Особенно если человек заиспользовал какую-нить библиотеку хелперов, которая лепит свои классы в стандартные namespaces, или подрубил что-то тяжёлое, типа рослина/newtonsoft.

Первый шаг в плане пофиксить сделан с project.json transitive dependencies, но это только начало работы.
По-хорошему надо вводить понятие bundles (по аналогии с frameworks) и явно разделять public api dependencies (могут использоваться твоим кодом) и infrastructure dependencies (подтягиваются, но недоступны для использования, надо подключать явно).
Чтоб можно было сказать "мне нужен xunit, net.standard 1.5 и BenchmarkDotNet" и не получить в подарок вот это.

42 additional nuget packages, 300+ mb of binaries in the packages folder and 17 (or so) additional assembly references.


F>Но нода и npm позволяют приложению использовать одновременно несколько разные версий одной библиотеки и это дает возможность спокойно разрабатывать эти отдельные модули реально независимо друг от друга и не переживать про то, какую версию библиотек при этом используешь ты и какую, возможно, будут использовать пользователи твоей библиотеки.

Что приведёт к очень интересным последствиям при попытке передать mydll.v1!Dictionary в код, который ожидает mydll.v2!Dictionary. Нафиг-нафиг, только проверка совместимости версий при компиляции и только явное разруливание конфликтов, иначе никак. Текущий nuget так и делает, через appconfig.
Re[2]: Bundles, Frameworks
От: Qbit86 Кипр
Дата: 20.10.16 10:23
Оценка:
Здравствуйте, Sinix, Вы писали:

S>По-хорошему надо вводить понятие bundles (по аналогии с frameworks) и явно разделять public api dependencies (могут использоваться твоим кодом) и infrastructure dependencies (подтягиваются, но недоступны для использования, надо подключать явно).


Можешь подробнее раскрыть про bundles/frameworks? Разделены ли публичные и приватные зависимости на какой-нибудь платформе?
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Broken diamond
От: fmiracle  
Дата: 20.10.16 10:55
Оценка: +1
Здравствуйте, Qbit86, Вы писали:

Q>Предположим, библиотека Foo использует библиотеку Qux-v1 публично, скажем, создаёт и возвращает типы из библиотеки Qux-v1. А библиотека Bar использует библиотеку Qux-v2 тоже публично, скажем, принимает в параметрах типы из Qux-v2. Как npm организует одновременное использование Foo и Bar, скажем, передачу экземпляров Qux из Foo в Bar?


Да никак. JS же весь динамический, потому и спокойно будут передаваться работать оба типа. Но может быть незапланированное поведение в таком случае, это верно замечено.
Зато отлично решается более частый случай, если мне для приложения нужен XML парсер, и библиотеке, реализующей, веб-сервер, нужен XML парсер для своей внутренней работы. И я могу использовать более новую/старую версию, чем версия, которой пользуется веб-сервер и не мешать ему.
Re[2]: .NET Core и Dependency Hell?
От: fmiracle  
Дата: 20.10.16 10:58
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Что приведёт к очень интересным последствиям при попытке передать mydll.v1!Dictionary в код, который ожидает mydll.v2!Dictionary. Нафиг-нафиг, только проверка совместимости версий при компиляции и только явное разруливание конфликтов, иначе никак. Текущий nuget так и делает, через appconfig.


Текущий это из .net core или какой?
Где можно посмотреть про разруливание в appconfig? Пока я нашел только способ что если подключить сборку непосредственно в приложение — это будет версия, которая и будет побеждающей при конфликтах.
Re[3]: Broken diamond
От: Qbit86 Кипр
Дата: 20.10.16 11:17
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Да никак.


Тогда я бы не называл это «удачный пример такой разбивки». Это огромная дыра.

F>JS же весь динамический, потому и спокойно будут передаваться работать оба типа.


Только если автор Qux в своём классе переименует поля/свойства и изменит сигнатуры методов, то получим ошибку в рантайме, правильно?
Глаза у меня добрые, но рубашка — смирительная!
Отредактировано 20.10.2016 11:20 Qbit86 . Предыдущая версия .
Re[3]: Bundles, Frameworks
От: Sinix  
Дата: 20.10.16 11:43
Оценка:
Здравствуйте, Qbit86, Вы писали:

S>>По-хорошему надо вводить понятие bundles (по аналогии с frameworks) и явно разделять public api dependencies (могут использоваться твоим кодом) и infrastructure dependencies (подтягиваются, но недоступны для использования, надо подключать явно).


Q>Можешь подробнее раскрыть про bundles/frameworks? Разделены ли публичные и приватные зависимости на какой-нибудь платформе?

Самому интересно, есть ли такое в публичных package manager-ах.

Смысл этого действа стандартный, очень часто встречается в самописных системах сборки / развёртывания.

Микрозависимости (отдельные пакеты) собираются в метапакеты (bundles), которые позволяют просто сказать "поставь мне такую версию продукта" и не заморачиваться с отдельными зависимостями. Версии метапакетов на версии библиотек не влияют и конфликтов сами по себе не порождают, это просто список библиотек. Ближайший аналог в нюгете — .net standard

Ну и как правило в состав метапакета включаются чисто приватные сборки / другие пакеты. Конечному пользователю они не нужны, но позволяют подтянуть инфраструктурные зависимости стандартным способом, без велосипедов типа такого.

Хм, запостить идею в roslyn project system что ли?
UPD о, только подумал, а оно уже завелось. Всегда бы так.
Отредактировано 20.10.2016 13:00 Sinix . Предыдущая версия .
Re[4]: Broken diamond
От: fmiracle  
Дата: 20.10.16 11:46
Оценка:
Здравствуйте, Qbit86, Вы писали:

F>>Да никак.

Q>Тогда я бы не называл это «удачный пример такой разбивки». Это огромная дыра.
F>>JS же весь динамический, потому и спокойно будут передаваться работать оба типа.
Q>Только если автор Qux в своём классе переименует поля/свойства и изменит сигнатуры методов, то получим ошибку в рантайме, правильно?

Ну да, я же дальше написал, что в этом случае — ошибка возможна.

Огромность дыры вещь относительная.
По крайней мере дыра проявляется только если библиотеки явно взаимодействуют друг с другом через наше приложение. Если же библиотека использует какую-то зависимость для своих внутренних дел — ни малейшей проблемы нет.

Текущий вариант nuget, как я вижу, может привести к ошибке именно в этом случае, если использование зависимости инкапсулировано в библиотеке и не покидает ее пределов. Потому что ее вдруг заставляют работаь с более новой версией зависимой сборки
Такая дыра мне кажется куда как более возможна, а главное, менее очевидна, чем описанный тобой случай.

С другой стороны, это в ноде случай передачи между библиотеками объекта, структура которого сильно важна — редкость. В .net, пожалуй, такая проблема действительно будет гораздо серьезнее.
Re[4]: Bundles, Frameworks
От: fmiracle  
Дата: 20.10.16 11:52
Оценка:
Здравствуйте, Sinix, Вы писали:

Q>>Можешь подробнее раскрыть про bundles/frameworks? Разделены ли публичные и приватные зависимости на какой-нибудь платформе?

S>Самому интересно, есть ли такое в публичных package manager-ах.
S>Смысл этого действа стандартный, очень часто встречается в самописных системах сборки / развёртывания.
S>Микрозависимости (отдельные пакеты) собираются в метапакеты (bundles), которые позволяют просто сказать "поставь мне такую версию продукта" и не заморачиваться с отдельными зависимостями. Версии метапакетов на версии библиотек не влияют и конфликтов сами по себе не порождают, это просто список библиотек. Ближайший аналог в нюгете — .net standard


Так а в чем разница с .net standard? Он же вроде именно так определяется:

Metapackages are a NuGet package convention for describing a set of packages that are meaningful together. They represent this set of packages by making them dependencies. They can optionally establish a framework for this set of packages by specifying a framework.

By referencing a metapackage, you are, in effect, adding a reference to each of its dependent packages as a single gesture.
...

The .NET Standard Library metapackage:

NETStandard.Library — Describes the libraries that are part of the ".NET Standard Library". Applies to all .NET implementations (for example, .NET Framework, .NET Core and Mono) that support the .NET Standard Library. Establishes the 'netstandard' framework.


Я просто как раз читаю и пытаюсь осознать все новые веяния в .net с выходом Core... Пока еще некоторая каша в голове
Re[3]: .NET Core и Dependency Hell?
От: Sinix  
Дата: 20.10.16 12:03
Оценка: 6 (1)
Здравствуйте, fmiracle, Вы писали:

F>Текущий это из .net core или какой?

F>Где можно посмотреть про разруливание в appconfig? Пока я нашел только способ что если подключить сборку непосредственно в приложение — это будет версия, которая и будет побеждающей при конфликтах.

нюгет 3.0 и свежее. Конфликты разруливаются через вкладку Manage nuget packages for solution > Consolidate, вот пример.
Re[5]: Bundles, Frameworks
От: Sinix  
Дата: 20.10.16 12:11
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Так а в чем разница с .net standard? Он же вроде именно так определяется:

Сорри, криво написал. "Самому интересно" было про "Разделены ли публичные и приватные зависимости". Метапакеты нюгета пока такого не умеют.

F>Я просто как раз читаю и пытаюсь осознать все новые веяния в .net с выходом Core... Пока еще некоторая каша в голове

Там веяний столько и они так часто меняются, что я бы не пытался детально разбирать технологии, пока оно всё не утрясётся. Общее впечатление получить — да, глубоко копать, если не вляпался в выпуск чего-то на .core пока рановато.
Re[5]: Broken diamond
От: Sinix  
Дата: 20.10.16 12:26
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Если же библиотека использует какую-то зависимость для своих внутренних дел — ни малейшей проблемы нет.

Есть, встречал подобные косяки неоднократно. Подробней расписано вот тут (классика не стареет), см disadvantages для LoadFrom.

Из очевидного: достаточно выставить свой тип через стандартный интерфейс (я не зря пример с Dictionary приводил, мы так напарывались). Также неплохо выстреливает рефлексия с Type.GetType("SomeTypeName").
Из неочевидного — любой разделяемый ресурс типа мутекса или кэширования в именованном слоте tls или сохраняемого файла настроек.

Для эстетов — блокировка по static-полю библиотеки, которая оказалась загружена в нескольких контекстах. Лютейший баг был
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.