So lösen Sie zirkuläre Paketabhängigkeiten

11

Ich überarbeite eine große Codebasis, in der sich die meisten Klassen in einem Paket befinden. Zur besseren Modularität erstelle ich Unterpakete für jede Funktionalität.

Ich erinnere mich, dass ich irgendwo erfahren habe, dass ein Paketabhängigkeitsdiagramm keine Schleifen haben sollte, aber ich weiß nicht, wie ich das folgende Problem lösen soll: FigureIst im Paket figure, Layoutist im Paket layout, Layouterfordert die Abbildung, um das Layout auszuführen, also layouthängt das Paket vom Paket ab figure. Auf der anderen Seite Figurekann a andere Figures enthalten , die ihre eigenen haben Layout, was das Paket figurevom Paket abhängig macht layout.

Ich habe mir einige Lösungen überlegt, wie das Erstellen einer ContainerSchnittstelle, die diese Figureimplementiert und in das LayoutPaket einfügt. Ist das eine gute Lösung? Irgendwelche anderen Möglichkeiten?

Vielen Dank

vainolo
quelle
Es ist Module (zB verschiedene Jars) können keine zirkulären Abhängigkeiten haben. Pakete KÖNNEN und HABEN häufig kreisförmige Abhängigkeiten, solange sie zum selben Modul gehören.
Lorus
@lorus Das ist also kein Designproblem?
Vainolo
2
Nein ist es nicht. Pakete sind normalerweise nur Namespaces. Dies kann sich nur ändern, wenn sie für etwas anderes verwendet werden, z. B. um die Sichtbarkeit ihrer Inhalte in der OSGi-Umgebung zu ändern. Kümmere dich nicht anders.
Lorus
1
Beachten Sie, dass viele Behörden zyklische Abhängigkeiten verurteilen, und dies manchmal aus gutem Grund. Bevor Sie jedoch blind umgestalten, sollten Sie sicherstellen, dass einer dieser Gründe tatsächlich auf Sie zutrifft. Wenn die Paketstruktur Ihnen keine Probleme bereitet und Sie nicht guten Gewissens erkennen können, warum dies in Zukunft der Fall sein sollte, ändern Sie nichts so Grundlegendes, nur um abstrakte architektonische Werte zu erfüllen.
Kilian Foth

Antworten:

9

Sie sollten über die Umkehrung der Kontrolle nachdenken

Sie definieren im Grunde genommen eine Schnittstelle für Ihre, Layoutdie sich irgendwo in der Nähe Ihrer Layout-Klasse in einem eigenen Paket befindet, sodass Sie ein Implementierungspaket und ein öffentliches Schnittstellenpaket haben - nennen Sie es beispielsweise Layoutable(ich weiß nicht, ob das richtig Englisch ist). Jetzt - Layout implementiert nicht diese Schnittstelle, sondern die FigureKlasse. Ebenso würden Sie eine Schnittstelle für Figure erstellen, die Drawablezum Beispiel ist.

So

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

Jetzt - Abbildung implementiert Layoutable und kann daher von Layout verwendet werden und (ich bin mir noch nicht sicher, ob Sie dies wollten) - Layout implementiert Drawable und kann in einer Figur gezeichnet werden. Der Punkt ist, dass die Klasse, die einen Dienst verfügbar macht, ihn über eine Schnittstelle verfügbar macht (hier: Layout und Layoutable) - die Klasse, die diesen Dienst verwenden möchte, muss die Schnittstelle implementieren.

Dann hätten Sie so etwas wie ein Erstellerobjekt, das beide miteinander verbindet. Der Schöpfer würde also sowohl von Layoutals auch von abhängig sein Figure, aber Layoutund Figureselbst wäre unabhängig.

Das ist die grobe Idee.

Eine ausgezeichnete Quelle für Lösungen für diese Probleme ist das Buch Java Application Architecture von Kirk Knoernschild.

michael_s
quelle
Ist dies nicht dasselbe wie die Containerin der Frage vorgeschlagene Schnittstelle?
Vaughandroid
Ja - und nein - ich würde sie nicht beide in das gleiche Paket packen, wie ich angegeben habe. Und dahinter steckte nicht viel Theorie. Und in diesem Fall reicht es nicht aus, es auf einer Seite zu machen, Sie müssen es auf beiden Seiten machen. In Ordung?
michael_s
Hoppla, ich habe das bisschen in der ursprünglichen Frage über Containerdas gleiche Paket wie verpasst Layout. Das würde nicht funktionieren, während Ihre Lösung würde.
Vaughandroid
ah - ok - ich schien den Teil mit dem Container verpasst zu haben, als ich
hackte
0

Ich bin mir nicht Figuresicher, was ein ist, aber vielleicht sollte es im selben Paket sein wie Layout?

Ihre vorgeschlagene ContainerSchnittstellenlösung würde nicht funktionieren - wenn Sie die ContainerSchnittstelle nicht in ein drittes Paket einfügen, besteht immer noch eine zirkuläre Abhängigkeit zwischen den beiden Paketen. Siehe die Antwort von michael_s für etwas, das funktionieren würde.

Eine andere Sache, wie andere erwähnt haben - es wird wahrscheinlich nie ein Problem sein. Du wirst nur Probleme in Zukunft laufen , wenn Figureund Layoutwill in getrennt sein Module . Sie können damit umgehen, wenn dies erforderlich wird. Da die beiden Klassen jedoch ziemlich eng miteinander verbunden zu sein scheinen, ist dies höchst unwahrscheinlich.

Vaughandroid
quelle