Як ви підходите до конфліктів транзитивної залежності, які відомі лише під час виконання? [зачинено]


9

Як ви зазвичай підходите до питань перехідної залежності, які виникають під час роботи у великих програмних проектах?

Останні три тижні я намагався запустити компонент великої частини програмного забезпечення в іншому компоненті програмного забезпечення, але він періодично вмирає через проблеми перехідної залежності, які відомі лише під час виконання.

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

Існує сотні, на сотні використовуваних залежностей, і є приблизно 50 підпроектів, пов'язаних з інструментом, над якими працюють окремо інші команди, де всі модулі мають глибоко вкладені залежності між собою. Ніхто не знає, для чого використовуються всі підпроекти, враховуючи масштаби та складність проекту.

У цій ситуації ви спробуєте створити візуальне подання DAG для кожної із залежних компонентів та спробуйте визначити, де можуть зіткнутися під час виконання? Я не маю контролю над тим, як управляти залежностями в інших підпроектах, і не можу змінити жоден код Java, написаний іншими розробниками.

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


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

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

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

Я не можу реконструювати проект, додавати додаткові гарантії якості, наполягати на зміні парадигми в компанії чи перемиканні мов як резолюція.


Ви говорите про щось на зразок контейнера DI неправильно налаштовано, щоб знати, що для IFoo використовувати IFooImpl?
Енді

Ні, це більше схоже на пакет (b) в проекті (b) - це перехідна залежність пакету (a) в проекті (A), але (B) вводиться лише під час виконання. Програмне забезпечення все працює від того, що я можу сказати, але мені просто необхідно встановити набір залежностей, щоб забезпечити правильне вирішення всіх перехідних залежностей. Існують набори залежностей, які дозволять продукту правильно запуститися, але ці конфігурації дуже крихкі. Як молодший дев. Я не маю контролю над цим.
Тайлер

2
Давай, "питання залежності" - це дуже загальний термін, і кожен, хто читає це, мабуть, передбачає щось інше. Для реальної програми програмного забезпечення - це технологічна залежність, тому, будь ласка, наведіть реальний приклад конкретної технології, яку ви маєте на увазі. Чи виникають проблеми, оскільки необхідні компоненти відсутні? Або тому, що надана неправильна версія? Який механізм вирішення залежності вже існує? Будь ласка, поясніть.
Doc Brown

1
У світі .Net я вирішую цю проблему, просто встановлюючи пакунки в основний проект програми. Хоча жоден код програми насправді не використовує бібліотеки плагінів безпосередньо, компілятор .Net гарантує, що DLL знаходиться в потрібному місці під час збирання та, таким чином, розгортання.
Енді,

2
"Я не маю контролю над тим, як управляти залежностями, і не можу змінити жоден код" - що насправді ви можете змінити? Якщо ви нічого не можете змінити, питання здається безглуздим.
Док Браун

Відповіді:


6

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

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

Ця методика використовується на серверах прикладних програм, щоб дозволити додаткам мати залежності, які інакше зіткнуться, тому ви можете побачити робочу реалізацію методики, наприклад, у Tomcat (і, якщо пощастить, можливо, ви зможете використовувати Tomcat's реалізація з невеликими змінами).


1
Мені заборонено переробляти проект для вирішення проблеми залежності. Хоча перехід на архітектуру, схожу на мікроядро, було б дуже крутим.
Тайлер

2
@Tyler: все ж я вважаю, що це хороша, загальна відповідь на загальну частину питання.
Док Браун

1
Це звучить трохи як osgi.
SpaceTrucker

4

Я ніколи не працював з Мейвен або Спринг, але щоб дати вам загальну відповідь на загальне питання: коли мова йде про проблеми залежності, ваша система повинна бути розроблена таким чином, щоб виявити їх якнайшвидше , і коли ці проблеми будуть виявлені , їх слід негайно повідомити, включаючи їх можливу причину.

В ідеалі цей момент часу не є "виробничим часом". Найкращий момент - це "час побудови", але це здається неможливим у вашому випадку. Отже другим найкращим варіантом є тести часу на виконання. Ви сказали нам, що існують "інтеграційні тести", але оскільки вони не виявляють проблем залежності, вони здаються неповними, або взагалі не перевіряють колізії залежностей. Саме тут слід почати намагатися вирішити проблему.

Більше того, щоб зробити тести ефективнішими, ваші компоненти повинні "швидко вийти з ладу", коли виникає проблема залежності. Це означає, що як тільки залежність вирішується і компонент завантажується, потенційні зіткнення залежності повинні бути негайно перевірені та сигналізовані. Якщо система спочатку працює протягом години, перш ніж буде виявлено зіткнення, виявити причину проблеми стає дуже важко. Я не знаю, чи Maven / Spring вже надає вам вбудовану стратегію "невдалої швидкості", але якщо це не так, спробуйте подумати в цьому напрямку.

Щоб пом'якшити проблеми на виробництві, ваша система повинна бути спроектована таким чином, щоб не загинути повністю, коли зіткнення залежності відбувається із менш важливим підкомпонентом. Збій, звичайно, не слід маскувати, але система в ідеалі повинна відхиляти завантаження цього компонента, записувати та / або сигналізувати про проблему та залишатися в стабільному стані. Коли компонент завантажується спочатку, система стає нестабільною, і ви виявите проблему лише після цього, тоді вам, ймовірно, доведеться вимкнути та перезапустити систему повністю, що, напевно, краще вам уникнути.

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

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


2

Подумайте про це, я просто задумався тут. Залежно від вимог / часових обмежень, я можу це врахувати:

1) створити список інтерфейсів та їх реалізацій (використовуючи відображення, якщо це можливо)

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

Я думаю, залежить від того, наскільки ви хочете взяти участь, але в кінцевому підсумку ви просто хочете мати повний перелік того, що вимагає чого - це рішення з часом генерує цей список.

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

Що ви маєте на увазі, коли говорите "зміни в компонентах вище"?


Вибачте, я не хотів надавати занадто багато довідкової інформації - коли я описую операційне середовище, запитання, як правило, звучать і спалахують до смерті. Я оновлю оригінальне запитання розділом з визначеннями.
Тайлер

2

Якщо я слідкую за вами правильно, проблема полягає в тому, що код, який потрібно використовувати, має залежність від часу виконання модулів, виражених у Spring XML, але maven про них не розповідається. Тож коли ви використовуєте їх, речі, які їм потрібні (перехідні залежності), не перебувають у вашому класі, і вони не роблять того, що повинні.

Я здогадуюсь, коли ви запитуєте своїх колег: "як я змушу це працювати?", Вони відповідають: "очевидно, вам потрібен цей список з 35 модулів та версій , як ви не могли цього знати?"

Імовірно, коли проводиться тестування інтеграції, необхідні модулі оголошуються як тестові залежності. Таким чином, систематичним рішенням є встановлення перевірок пам’яті тесту інтеграції, щоб гарантувати, що у них немає нічого, крім сторонніх інструментів тестування, оголошених як тестові залежності. Це навіть може бути автоматизовано плагіном Maven Execucer .

Мабуть, ви не можете цього зробити, тож найкращий варіант, ймовірно, знайдеться тут .


Саме так і відбувається, з чого я можу сказати. Поки що я жонглюю 30 залежностями і змішую сфери застосування для усунення зіткнень, але, експертний огляд - це те, що потрібно тут.
Тайлер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.