Как вы подходите к переходным конфликтам зависимостей, которые известны только во время выполнения? [закрыто]

9

Как вы обычно подходите к проблемам транзитивной зависимости, возникающим во время выполнения в больших программных проектах?

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

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

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

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

Решения, которые я придумала, работают только в течение часа или двух, и затем они перестают работать из-за изменений в вышестоящих компонентах. Примером вышестоящего компонента является артефакт, от которого зависит проект, над которым я работаю, который построен на более ранней стадии в конвейере CI.


По другим просьбам я собираюсь включить информацию о том, какая технология используется, рискуя закрыть вопрос о предоставлении слишком большого количества информации или о том, что тело станет слишком длинным:

  • Maven используется для управления зависимостями; а также
  • Spring используется в качестве DI-контейнера;
  • Большинство проблем с зависимостями связаны с перекрывающимися контекстами компонентов в результате загрузки других модулей во время выполнения.
  • Продукт работает должным образом, и есть шведские столы модульных тестов, и интеграционные тесты, чтобы ускорить функциональную корректность программы

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

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

Тайлер
источник
Вы говорите о чем-то похожем на то, что DI-контейнер не настроен должным образом, чтобы знать, что для IFoo используется IFooImpl?
Энди
Нет, это больше похоже на то, что package (b) в проекте (b) является транзитивной зависимостью пакета (a) в проекте (A), но (B) вводится только во время выполнения. Все программное обеспечение работает исходя из того, что я могу сказать, но мне просто нужно присвоить набор зависимостей, чтобы все переходные зависимости были разрешены правильно. Существуют наборы зависимостей, которые позволят продукту правильно запускаться, но эти конфигурации очень хрупкие. Как младший разработчик Я не могу это контролировать.
Тайлер
2
Да ладно, «проблема зависимости» - это очень общий термин, и каждый, кто его читает, вероятно, предполагает что-то другое. В реальных условиях это зависит от технологии, поэтому, пожалуйста, приведите реальный пример для конкретной технологии, которую вы имеете в виду. Проблемы возникают из-за отсутствия необходимых компонентов? Или из-за неправильной версии? Какой механизм разрешения зависимостей уже существует? Просьба уточнить.
Док Браун
1
В мире .Net я решаю эту проблему, просто устанавливая пакеты в свой основной проект приложения. Хотя ни один код приложения не использует библиотеки плагинов напрямую, компилятор .Net гарантирует, что DLL находится в правильном месте во время сборки и, следовательно, развертывания.
Энди
2
«У меня нет контроля над управлением зависимостями, и я не могу изменить какой-либо код» - что на самом деле вы можете изменить? Если вы не можете ничего изменить, вопрос кажется бессмысленным.
Док Браун

Ответы:

6

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

По сути, вы должны определить базовую среду, состоящую из небольшого ядра приложения, а также с любыми зависимостями, которые универсально согласованы, и всеми интерфейсами, необходимыми для взаимодействия модулей друг с другом. Затем каждый загружаемый модуль получает свой собственный загрузчик классов, который может получить доступ к (1) классам из среды выполнения, (2) классам из ядра приложения и (3) классам из этого модуля и его прямым зависимостям. Вся межмодульная связь проходит через интерфейсы, определенные в ядре, так что ни один модуль напрямую не зависит от другого.

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

Жюль
источник
1
Я не имею права перепроектировать проект, чтобы решить проблему зависимости. Впрочем, переключиться на архитектуру, похожую на микроядро, было бы круто.
Тайлер
2
@Tyler: тем не менее, я думаю, что это хороший, общий ответ на общую часть вопроса.
Док Браун
1
Это звучит как осги.
SpaceTrucker
4

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

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

Более того, чтобы сделать тесты более эффективными, ваши компоненты должны быстро выходить из строя при возникновении проблемы с зависимостями. Это означает, что как только зависимость разрешена и компонент загружен, потенциальные конфликты зависимости должны быть проверены и немедленно сигнализированы. Если система сначала запускается за час до того, как будет обнаружено столкновение, становится очень трудно определить причину проблемы. Я не знаю, предоставляет ли Maven / Spring встроенную стратегию «быстрого отказа», но если это не так, постарайтесь думать в этом направлении.

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

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

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

Док Браун
источник
2

Считайте, что я просто размышляю здесь В зависимости от требований / временных ограничений я мог бы рассмотреть это:

1) создать список интерфейсов и их реализаций (используя отражение, если доступно)

2) создать своего рода обертку вокруг вашего DI. Когда DI просят предоставить конкретную реализацию, посмотрите, существует ли уже правило DI; если правило существует - просто верните то, что предоставляет ваш DI; в противном случае, если есть единственная реализация интерфейса, и вы можете создать экземпляр - зарегистрируйте и верните экземпляр; в противном случае войти и потерпеть неудачу.

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

Однако, возможно, это большая работа, и она не надежна - что если у вас странное состояние, требующее определенной зависимости один раз в голубой луне?

Что вы имеете в виду, когда говорите «изменения в вышестоящих компонентах»?

Evgeni
источник
Извините, я не хотел предоставлять слишком много справочной информации - когда я описываю рабочую среду, вопросы обычно опускаются и загораются до смерти. Я обновлю оригинальный вопрос разделом с определениями.
Тайлер
2

Если я правильно понимаю вас, проблема в том, что код, который вам нужно использовать, имеет зависимости во время выполнения от модулей, выраженных в Spring XML, но maven о них не говорится. Поэтому, когда вы используете их, то, что им нужно (транзитивные зависимости), не находится на вашем пути к классам, и они не делают то, что должны.

Я предполагаю, что когда вы спрашиваете своих коллег, «как мне заставить это работать?», Они спрашивают: «Очевидно, вам нужен этот список из 35 модулей и версий , как вы могли этого не знать?»

Предположительно, когда интеграционное тестирование завершено, необходимые модули объявляются как тестовые зависимости. Таким образом, системное решение состоит в том, чтобы настроить проверки интеграционных тестовых модулей, чтобы гарантировать, что у них есть только сторонние инструменты тестирования, объявленные как тестовые зависимости. Это может даже быть автоматизировано плагином Maven Enforcer .

Видимо, вы не можете сделать это, поэтому ваш лучший вариант, вероятно, находится здесь .

Сору
источник
Это именно то, что происходит, из того, что я могу сказать. До сих пор я манипулировал 30 зависимостями и вертелся в области, чтобы устранить коллизии, но здесь необходим экспертный анализ.
Тайлер