Як вирішити кругові залежності пакетів


11

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

Я пам’ятаю, десь дізнався, що на графіку залежності пакету не повинно бути циклів, але я не знаю, як вирішити таку проблему: Figureзнаходиться в пакеті figure, Layoutзнаходиться в пакеті layout, Layoutпотрібна фігура для виконання макета, тому пакет layoutзалежить від пакета figure. Але з іншого боку, a Figureможе містити інші Figures всередині нього, маючи своє власне Layout, що робить пакет figureзалежним від пакета layout.

У мене є деякі рішення, як, наприклад, створити Containerінтерфейс, який Figureреалізує і поміщає його в Layoutпакет. Це гарне рішення? Будь-які інші можливості?

Дякую


Це модулі (наприклад, різні банки) не можуть мати кругових залежностей. Пакети МОЖУТЬ і часто мають кругові залежності, якщо вони належать до одного модуля.
lorus

@lorus Отож це не проблема дизайну?
vainolo

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

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

Відповіді:


9

Вам варто подумати про інверсію управління

Ви в основному визначаєте інтерфейс для вашого, Layoutякий знаходиться десь біля вашого класу Layout у власному пакеті, щоб у вас був пакет реалізації та пакет загальнодоступного інтерфейсу - наприклад, зателефонуйте до нього Layoutable(я не знаю, чи правильно це англійською). Тепер - макет не буде реалізовувати цей інтерфейс, а не Figureклас. Так само ви створили б інтерфейс для рисунку, Drawableнаприклад.

Так

my.public.package.Layoutable
my.implementation.package.Layout
my.public.package.Drawable
my.implementation.package.Figure

Тепер - Рисунок реалізує Layoutable і, таким чином, може бути використаний Layout і (я ще не впевнений, чи це те, що ви хотіли) - Макет реалізує Dravable і його можна намалювати на рисунку. Справа в тому, що клас, який відкриває якусь послугу, робить її доступною через інтерфейс (тут: Layout and Layoutable) - клас, який хоче використовувати цю службу, повинен реалізувати інтерфейс.

Тоді у вас виникне щось на зразок об’єкта-творця, який би пов'язує обидва разом. Отже, творець мав би залежність Layoutяк від, так і від них Figure, але Layoutі Figureсам був би незалежним.

Це груба ідея.

Прекрасним джерелом для вирішення цих проблем є книга архітектури додатків Java Кірка Кноерншильда.


Хіба це не те саме, що Containerінтерфейс, як запропоновано у питанні?
vaughandroid

Так - і ні - я б не ставив їх обох в один і той же пакет, як я заявляв. І за цим не було багато теорії. І в цьому випадку недостатньо зробити це з одного боку, вам доведеться це робити з обох сторін. Добре?
michael_s

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

ах - гаразд - я, здається, пропустив частину з контейнером, хоча, коли я хакнув - мав би назвати його контейнером;)
michael_s

0

Мені не надто зрозуміло, що Figureтаке, але, можливо, воно повинно бути в тому ж пакеті, що і Layout?

Запропоноване Containerрішення інтерфейсу не буде працювати - якщо ви не помістите Containerінтерфейс у 3-й пакет, тоді ви все одно будете мати кругову залежність між двома пакетами. Дивіться відповідь michael_s, що б спрацювало.

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

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