2012-07-31 2 views
33

Vor kurzem stieß ich auf diese Javalobby Post http://java.dzone.com/articles/how-changing-java-package auf Java-Code Verpackung nach Merkmal.Ist Paket für Feature-Ansatz gut?

Ich mag die Idee, aber ich habe einige Fragen zu diesem Ansatz. Ich stellte meine Frage, bekam aber keine zufriedenstellende Antwort. Ich hoffe, dass jemand auf StackOverflow meine Fragen klären kann.

Ich mag die Idee von Paket für Feature, die die Zeit für das Verschieben über die Pakete während des Codierens drastisch reduziert und alle damit verbundenen Sachen werden an einem Ort sein (Paket). Aber was ist mit Interaktionen zwischen den Diensten in verschiedenen Paketen?

Angenommen, wir erstellen eine Blog-App und stellen alle benutzerbezogenen Vorgänge (Controller/Dienste/Repositories) in das Paket com.mycompany.myblog.users. Und alle Blog Post bezogenen Operationen (Controller/Dienste/Repositories) in com.mycompany.myblog.posts Paket.

Jetzt möchte ich User Profile zusammen mit allen Posts, die er gepostet hat, anzeigen. Sollte ich myblog.posts.PostsService.getPostsByUser(userId) von myblog.users.UserController.showUserProfile() anrufen?

Wie sieht es mit der Kopplung zwischen Paketen aus?

Auch wo immer ich über Paket für Feature lese, sagt jeder seine gute Praxis. Warum ermutigen dann viele Buchautoren und sogar Frameworks, nach Layern zu gruppieren? Einfach nur neugierig zu wissen :-)

Antwort

16

irgendwo beantwortet: einen Blick auf Onkel Bobs Nehmen

Package Design Principles

Er erklärt Gründe und Motivationen hinter diesen Grundsätzen.

EDIT: Ich hatte die ursprüngliche Antwort mehr als 2 Jahre zurück. Aber hat sich nicht geändert, weil es akzeptiert wurde. Aber ändern Sie es so, dass jeder neue Besucher davon profitieren kann und Link-Verrottung vermieden wird, wie von @bPraktik vorgeschlagen.

Klassen, die wiederverwendet werden, sollten zusammen verpackt werden, damit das Paket als eine Art vollständiges Produkt für Sie behandelt werden kann. Und diejenigen, die zusammen wiederverwendet werden, sollten von denen getrennt werden, die nicht wiederverwendet werden. Zum Beispiel werden Ihre Logging-Dienstprogrammklassen nicht unbedingt zusammen mit Ihren Dateiklassen verwendet. So verpacken Sie alle, die sie getrennt notieren. Protokollierungsklassen könnten jedoch miteinander verwandt sein. So erstellen Sie eine Art komplettes Produkt für die Protokollierung, sagen wir, für den Mangel an besseren Namen Commons-Logging-Paket es in einem (wiederverwendbaren Glas) und ein anderes separates komplettes Produkt für io Dienstprogramme, wieder für den Mangel an besseren Namen, sagen Gemeingüter- io.jar. Wenn Sie die Commons-io-Bibliothek aktualisieren, um Support-Java-NIO zu sagen, müssen Sie möglicherweise nicht unbedingt Änderungen an der Protokollierungsbibliothek vornehmen. Also ist es besser, sie zu trennen.

Nehmen wir an, Sie möchten, dass Ihre Logging-Utility-Klassen eine strukturierte Protokollierung unterstützen, z. B. eine Art Log-Analyse durch Tools wie Splunk. Einige Clients Ihres Protokollierungsdienstprogramms möchten möglicherweise auf Ihre neuere Version aktualisieren. einige andere nicht. Wenn Sie eine neue Version veröffentlichen, packen Sie alle benötigten Klassen zusammen und verwenden Sie sie zur Migration erneut. So können einige Clients Ihrer Utility-Klassen Ihr altes commons-logging jar löschen und in commons-logging-new jar wechseln. Einige andere Clients sind immer noch in Ordnung mit älteren jar. Es werden jedoch keine Clients benötigt, um diese beiden JAR-Dateien (neu und alt) zu haben, nur weil Sie sie gezwungen haben, einige Klassen für ältere gepackte JAR-Dateien zu verwenden.

Vermeiden Sie zyklische Abhängigkeiten. a hängen von b ab; b auf c; c auf d; aber d hängt von a ab. Das Szenario ist offensichtlich abschreckend, da es sehr schwierig sein wird, Schichten oder Module usw. zu definieren, und Sie können diese nicht unabhängig voneinander variieren.

Sie könnten Ihre Klassen auch so paketieren, dass sich bei Änderung einer Ebene oder eines Moduls andere Module oder Ebenen nicht unbedingt ändern müssen. Wenn Sie zum Beispiel von einem alten MVC-Framework zu einem Rest-API-Upgrade wechseln, müssen möglicherweise nur die Ansicht und der Controller geändert werden. Dein Modell nicht.

+2

Gut verbundener Artikel, aber bitte aktualisieren Sie diese Antwort, um Link-Rot zu vermeiden. – bPratik

+0

@bPratik aktualisiert. – Atul

10

Es gibt viele anderen Aspekt andere als Kupplung für Verpackungsdesign würde ich bei OOAD Principles aussehen suggeriert, vor allem Verpackungsdesign priciples wie

REP Die Release-Reuse Equivalency Prinzip Das Granulat Wiederverwendung ist das Granulat der Freisetzung.

CCP Das allgemeine Verschlussprinzip Klassen, die sich zusammen ändern, werden zusammen verpackt.

CRP Das allgemeine Wiederverwendungsprinzip Klassen, die zusammen verwendet werden, sind zusammen verpackt.

ADP Das Prinzip der azyklischen Abhängigkeiten Das Abhängigkeitsdiagramm von Paketen darf keine Zyklen haben.

SDP Das Prinzip der stabilen Abhängigkeiten Abhängig von der Stabilität.

SAP Das stabile Abstraktionsprinzip Die Abstraktheit nimmt mit der Stabilität zu.

für weitere Informationen können Sie book „Agile Softwareentwicklung, Grundsätze, Muster und Praktiken“

10

Ich persönlich mag das „Paket nach Merkmal“ -Ansatz lesen, obwohl Sie ziemlich viel Urteil brauchen anzuwenden Wo zeichne ich die Paketgrenzen ein? In vielen Fällen ist dies ein durchführbarer und vernünftiger Ansatz.

Sie sollten wahrscheinlich eine Kopplung zwischen Paketen und Modulen über öffentliche Schnittstellen erreichen - dies hält die Kopplung sauber und überschaubar.

Es ist völlig in Ordnung, wenn das Paket "Blogposts" in das Paket "Benutzer" aufgenommen wird, solange es dafür gut gestaltete öffentliche Schnittstellen verwendet.

Ein großer Ratschlag wenn Sie jedoch diesen Ansatz gehen: seien Sie sehr aufmerksam über Ihre Abhängigkeiten und insbesondere vermeiden Sie kreisförmige Abhängigkeiten zwischen Paketen. Ein gutes Design sollte wie ein Abhängigkeitsbaum aussehen - mit den Funktionsbereichen auf höherer Ebene, die von einer Reihe allgemeiner Dienste abhängen, die von Bibliotheken von Utility-Funktionen usw. abhängen. Zu einem gewissen Grad wird dies wie architektonische "Ebenen" aussehen. End-Pakete, die zu Back-End-Diensten aufrufen.