2013-05-14 17 views
8

Ich verwende seit einiger Zeit Sonar-Code-Qualität-Management-Plattform, und in den meisten Fällen finde ich es sehr hilfreich, versteckte Designfehler meiner Code-Basis zu enthüllen.Sind alle zyklischen Verweise zwischen Java-Paketen fehlerhaft?

Allerdings gibt es eine Regel, die mir mehr Ärger als Hilfe gibt, und das ist ihre Überprüfung auf "zyklische Paketreferenz" Verletzungen.

Ich denke, ich verstehe völlig, wo eine solche Abhängigkeit zwischen Pacakges eine schlechte Sache ist. Zum Beispiel ist es in einem typischen dreistufigen Darstellungs/Dienst/Persistenz-Schichten-Design fast immer eine schlechte Idee, den Datenbankbehandlungscode einen Verweis zurück zu UI-bezogenen Klassen zu haben. Ich habe kein Problem damit, es als "Verletzung" zu bezeichnen.

Aber betrachten wir andere Fälle, d. H. Wie das Entwerfen einer IDE-ähnlichen Anwendung. Nehmen wir an, wir haben ein Hauptpaket, das eine Anwendung Schnittstelle enthält, die definiert List Application.getViews() Methode, um Anwendungsansichten zu verweisen.

Wenn jedoch die Ansicht Schnittstelle eine Anwendung GetApplication() Methode hat zu seiner übergeordneten Anwendung zu verweisen, die ich glaube, ein ganz gewöhnliches Design ist, wird es eine zyklische Referenz einführen, sofern jede der Schnittstellen sind in com.myapp.ui und com.myapp.ui.view jeweils getrennt.

Natürlich können Sie nur setzen die Ansicht Schnittstelle in das com.myapp.ui den Zyklus zu brechen. Aber wenn man verschiedene andere Ansicht im Zusammenhang APIS in com.myapp.ui.view haben, viele von ihnen eine andere abstrakte APIs wie Abstract, InhaltAlle, AbstractContentView, etc, ich frage mich, ob es ratsam ist, sie zu halten in separaten Paketen zu einem Verwaltungszweck.

und betrachten die genannte Anwendung hat viele andere ähnliche Fälle wie com.myapp.ui.action, com.myapp.ui.perspective, usw., die wirklich com.myapp.ui thepacakge machen würde gedrängten wenn wir sie alle dort hineinbringen sollen.

Also, welchen Ansatz schlagen Sie vor, um eine solche Situation zu behandeln? Sind wirklich alle zyklischen Pakete eine schlechte Sache? Oder wenn ich mit ihnen leben muss, wie konfiguriere ich Sonar, um nur echte, problematische Zyklen zu überprüfen?

Danke!

Antwort

6

Jedes absolute - außer diesem;) - wird manchmal falsch sein. Also, ist jede zyklische Referenz schlecht? Nein. Sie müssen Ihr Urteilsvermögen verwenden.

Aber wenn Sie eine zyklische Abhängigkeit einführen, lohnt es sich zu fragen, ob Sie es wirklich brauchen, und warum. Die tl; dr ist, dass mehr als oft nicht, können Sie feststellen, dass das Durchbrechen des Zyklus kann Ihre Modularität verbessern, und vor allem Ihre Fähigkeit, Komponenten separat zu testen.

Um Ihr Beispiel zu verwenden, benötigt eine Ansicht wirklich eine getApplication(), die vermutlich ein relativ "schweres" Objekt zurückgibt (dh eines, das selbst eine Datenbank, ein Netzwerk usw. benötigt)? Vielleicht ... aber vielleicht nicht.Wenn das, was Sie wirklich von diesem getApplication benötigen, etwas mit ein paar Callbacks ist (wie wenn ein Benutzer eine Aktion initiiert), dann könnte es nützlich sein, eine Schnittstelle in einem gemeinsamen Paket für diesen Rückruf zu erstellen. Also, anstatt:

com.foo.app.Application 
com.foo.view.View 
    Application getApplication() 

würden Sie haben:

com.foo.common.Callback // maybe just a Callable, Runnable, etc? 
com.foo.app.Application 
    provides a Callback for some action foo 
com.foo.view.View 
    Callback getFooCallback() 

Die Frage, die Sie stellen sollten, ist: was das mir nicht geben? Es könnte sein, dass du so viel ausstechen musst, dass es dir nicht viel gibt - obwohl das vielleicht nahelegt, dass du deinen Unterricht etwas zerlegen kannst. Aber es könnte sein, dass es tatsächlich einfacher macht, Ihre Ansicht zu testen, denn jetzt kann Ihr Komponententest (1) die Ansicht testen, ohne eine ganze Anwendung hochzufahren, und (b) einen "Dummy" -Rückruf bereitstellen, der etwas wie das Speichern eines Zeichenfolge, die die Aktion beschreibt, und dann bestätigt Ihr Komponententest, dass es die richtige Zeichenfolge speicherte.

+0

Lassen Sie mich bitte versuchen, einen Fall zu denken, wo View.getApplication() gerechtfertigt sein könnte. Ich nehme an, es könnte eine übliche Anforderung für eine Sicht sein, auf andere Ressourcen zu verweisen, die normalerweise mit der Anwendung verbunden sind, wie ein i18n-Nachrichtenbündel oder eine JDBC-Datenquelle usw. Vielleicht können wir alle auf eine DI-Weise sortieren, aber ich glaube daran Definition ist eine Ansicht in diesem Fall ein Teil eines zusammengesetzten Ganzen, das nicht in einem getrennten Kontext gedacht werden kann. JDBC-Datenquelle kann also keine willkürliche sein, sondern eine, die ihre Elternanwendung bereitstellt. Wäre es nicht klarer, solche Abhängigkeiten auch im Design zu zeigen? – mysticfall