Jak rozwiązać zależności okrągłego pakietu


11

Refaktoryzuję dużą bazę kodu, w której większość klas znajduje się w jednym pakiecie. Dla lepszej modułowości tworzę podpakiety dla każdej funkcjonalności.

Pamiętam, że dowiadywałem się gdzieś, że wykres zależności pakietu nie powinien zawierać pętli, ale nie wiem, jak rozwiązać następujący problem: Figurejest w pakiecie figure, Layoutjest w pakiecie layout, Layoutwymaga wykonania rysunku, więc pakiet layoutzależy od pakietu figure. Ale z drugiej strony, Figuremoże zawierać w sobie inne Figures, które mają swoje własne Layout, co powoduje, że pakiet figurezależy od pakietu layout.

Wymyśliłem kilka rozwiązań, takich jak stworzenie Containerinterfejsu, który Figureimplementuje i umieszczenie go w Layoutpakiecie. Czy to dobre rozwiązanie? Jakieś inne możliwości?

Dzięki


To moduły (np. Różne słoiki) nie mogą mieć okrągłych zależności. Pakiety MOGĄ i często Mają zależności kołowe, o ile należą do tego samego modułu.
lorus

@lorus Więc to nie jest problem projektowy?
vainolo

2
Nie, nie jest. Pakiety są zwykle tylko przestrzeniami nazw, które mogą ulec zmianie tylko wtedy, gdy zostały użyte do czegoś innego, np. Do zmiany widoczności zawartości w środowisku OSGi. Nie przejmuj się inaczej.
lorus

1
Zauważ, że wiele organów potępia cykliczne zależności, a czasem z uzasadnionego powodu, ale zanim ślepo zreformujesz, powinieneś upewnić się, że jeden z tych powodów rzeczywiście dotyczy ciebie. Jeśli struktura pakietu nie sprawia Ci kłopotu i nie możesz z czystym sumieniem zrozumieć, dlaczego miałoby to w przyszłości nie zmieniać czegoś tak fundamentalnego, aby zaspokoić abstrakcyjne wartości architektoniczne.
Kilian Foth

Odpowiedzi:


9

Powinieneś pomyśleć o odwróceniu kontroli

Zasadniczo definiujesz interfejs, Layoutktóry znajduje się gdzieś w pobliżu klasy Layout we własnym pakiecie, więc miałbyś pakiet implementacyjny i pakiet interfejsu publicznego - na przykład zadzwoń do niego Layoutable(nie wiem, czy to jest poprawny angielski). Teraz - układ nie zaimplementuje tego interfejsu, ale Figureklasę. Podobnie stworzyłbyś na przykład interfejs dla Figure Drawable.

Więc

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

Teraz - Figure implementuje Layoutable, a zatem może być używany przez Layout i (nie jestem jeszcze pewien, czy tego właśnie chciałeś) - Layout implementuje Drawable i można go narysować na rysunku. Chodzi o to, że klasa, która udostępnia pewną usługę, udostępnia ją przez interfejs (tutaj: Layout i Layoutable) - klasa, która chce korzystać z tej usługi, musi implementować interfejs.

Wtedy miałbyś coś w rodzaju obiektu twórcy, który łączy oba razem. Tak więc twórca byłby zależny zarówno od, Layoutjak i od Figure, ale Layouti Figureoni byliby niezależni.

To jest szorstki pomysł.

Doskonałym źródłem rozwiązań tych problemów jest książka Java Application Architecture autorstwa Kirka Knoernschilda.


Czy to nie to samo, co Containerinterfejs sugerowany w pytaniu?
vaughandroid

Tak - i nie - nie umieściłbym ich obu w tym samym opakowaniu, jak powiedziałem. Nie kryło się za tym wiele teorii. I w tym przypadku nie wystarczy zrobić to po jednej stronie, musisz to zrobić po obu stronach. W porządku?
michael_s

Ups, brakowało mi trochę w pierwotnym pytaniu na temat korzystania Containerz tego samego pakietu co Layout. To nie zadziałałoby, podczas gdy twoje rozwiązanie.
vaughandroid

ah - ok - Wydawało mi się, że tęskniłem za częścią z kontenerem, kiedy hackowałem - powinienem nazwać go Container;)
michael_s

0

Nie jestem zbyt jasne, co to Figurejest a , ale może powinno być w tym samym pakiecie co Layout?

Proponowane Containerrozwiązanie interfejsu nie zadziałałoby - chyba że umieścisz Containerinterfejs w 3. pakiecie, nadal będziesz mieć cykliczną zależność między dwoma pakietami. Zobacz odpowiedź michaela na coś, co by działało.

Kolejna rzecz, jak wspomnieli inni - prawdopodobnie nigdy nie będzie to problemem. Jesteś tylko będzie napotkasz problemy w przyszłości, jeśli Figurei Layoutchce być w oddzielnych modułach . Możesz sobie z tym poradzić, jeśli i kiedy stanie się to konieczne, ale biorąc pod uwagę, że obie klasy wydają się dość blisko powiązane, wydaje się to bardzo mało prawdopodobne.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.