Gibt es Best Practices für die Organisation von (Java-) Paketen? [geschlossen]

201

Vor einiger Zeit wurde hier eine Frage zur feinkörnigen Organisation von Java-Paketen beantwortet. Zum Beispiel my.project.util, my.project.factory, my.project.serviceetc.

Ich kann es jetzt nicht finden, also kann ich die Frage genauso gut stellen.

Gibt es Best Practices in Bezug auf die Organisation von Paketen in Java und was steckt darin?

Wie organisieren Sie Ihre Klassen in Ihrem Java-Projekt?

Zum Beispiel hat ein Projekt, an dem ich mit ein paar Leuten arbeite, ein Paket namens Beans. Es war ursprünglich ein Projekt mit einfachen Bohnen, endete aber (aufgrund mangelnder Erfahrung und Zeitmangel) (fast) mit allem. Ich habe sie ein wenig aufgeräumt, indem ich einige Factory-Klassen in ein Factory-Paket eingefügt habe (Klassen mit statischen Methoden, die Beans erstellen), aber wir haben andere Klassen, die Geschäftslogik ausführen, und andere, die einfache Verarbeitung (nicht mit Geschäftslogik) ausführen, wie das Abrufen eine Nachricht für einen Code aus einer Eigenschaftendatei.

Ihre Gedanken und Kommentare werden geschätzt.

Cyntech
quelle
74
Ich bin mit dem Abschluss dieser Frage nicht einverstanden. Ich bin nicht anderer Meinung, dass Best-Practice-Fragen fast immer auf Erfahrung und Meinung beruhen. Ich bin jedoch nicht der Meinung, dass diese Fragen bei Stack Overflow geschlossen werden sollten. Dies ist der Kern einer guten Programmierung, bei der Best Practices verwendet werden und die Suche nach der besten Lösung diese Meinungen und Erfahrungen nutzt. Bitte öffnen Sie diese Frage erneut.
Cyntech
Ich schlage vor, dass Sie dies lesen : isfice.com/blog/archives/5164 . TL; DR ... die ganze Idee von "Best Practices" ist gebrochen. Im besten Fall ist es eine ungeheure Fehlbezeichnung, im schlimmsten Fall ist es geradezu schädlich.
Stephen C

Antworten:

174

Paketorganisation oder Paketstrukturierung ist normalerweise eine hitzige Diskussion. Im Folgenden finden Sie einige einfache Richtlinien für die Benennung und Strukturierung von Paketen:

  • Befolgen Sie die Namenskonventionen für Java- Pakete
  • Strukturieren Sie Ihre Pakete nach ihrer funktionalen Rolle sowie nach ihrer Geschäftsrolle
    • Teilen Sie Ihre Pakete nach ihren Funktionen oder Modulen auf. z.B com.company.product.modulea
    • Eine weitere Aufschlüsselung kann auf Ebenen in Ihrer Software basieren. Aber gehen Sie nicht über Bord, wenn Sie nur wenige Klassen im Paket haben, dann ist es sinnvoll, alles im Paket zu haben. zB com.company.product.module.weboder com.company.product.module.utiletc.
    • Vermeiden Sie es, bei der Strukturierung über Bord zu gehen. IMO vermeiden Sie separate Verpackungen für Ausnahmen, Fabriken usw., es sei denn, es besteht dringender Bedarf.
  • Wenn Ihr Projekt klein ist, halten Sie es mit wenigen Paketen einfach. zB com.company.product.modelund com.company.product.utilusw.
  • Schauen Sie sich einige der beliebtesten Open Source-Projekte für Apache-Projekte an . Sehen Sie, wie sie die Strukturierung für Projekte unterschiedlicher Größe verwenden.
  • Berücksichtigen Sie beim Benennen auch das Erstellen und Verteilen (damit Sie Ihre API oder Ihr SDK in einem anderen Paket verteilen können, siehe Servlet-API).

Nach einigen Experimenten und Versuchen sollten Sie in der Lage sein, eine Struktur zu finden, mit der Sie vertraut sind. Seien Sie nicht auf eine Konvention fixiert, sondern offen für Änderungen.

Naikus
quelle
Vielen Dank für Ihre Antwort. Dies ist größtenteils das, was wir zu erfassen versucht haben, aber viel nicht verwandter Code ist in unser Beans-Paket gelangt, aus dem meine Frage stammt.
Cyntech
2
Ich bin damit einverstanden, dass Paket für Feature am sinnvollsten ist. Ich habe eine großartige Analogie gehört, die sich einmal auf eine Bürostruktur des Unternehmens bezog. In einem mehrschichtigen Ansatz würde jede der Personen pro Ebene in einem Unternehmen miteinander sitzen, dh Führungskräfte, Manager, Administratoren, Mitarbeiter / Arbeiter sitzen alle in getrennten Abschnitten in einem Gebäude. Diese Struktur ist wahrscheinlich nicht so effektiv wie ein organisierter Ansatz mit "Merkmalen". Dh wenn der Vertriebsleiter mit dem Vertriebsleiter zusammensitzt, der mit den Vertriebsmitarbeitern zusammensitzt, die alle mit einem Vertriebsadministrator zusammenarbeiten. Dies sorgt für einen besseren Zusammenhalt zwischen den Abteilungen, wenn diese auf diese Weise organisiert werden.
alex
Stimmen Sie Ihren Punkten zu. Nur ein Punkt, der über den Firmennamen im Paket hervorgehoben werden muss, wenn das Unternehmen das erworbene Produkt verkauft. Das Management möchte den Firmennamen entfernen. Das könnte Overhead sein.
Tushar D
182

Ich organisiere Pakete nach Funktionen , nicht nach Mustern oder Implementierungsrollen. Ich denke Pakete wie:

  • beans
  • factories
  • collections

sind falsch.

Ich bevorzuge zum Beispiel:

  • orders
  • store
  • reports

So kann ich Implementierungsdetails durch Paketsichtbarkeit ausblenden . Die Fabrik der Bestellungen sollte im ordersPaket enthalten sein, damit Details zum Erstellen einer Bestellung ausgeblendet werden.

onof
quelle
10
Dieser Beitrag macht einen guten Punkt über die Sichtbarkeit von Paketen. Ich habe noch nie gesehen, dass Java-Paketumfang verwendet wird, aber die richtige Paketstruktur könnte es Entwicklern ermöglichen, ihn besser zu nutzen.
Jpnh
23
Das ist genau richtig, aber nur wenige Entwickler tun dies. Pakete sollten zusammenhängende Sammlungen von Klassen sein, von denen einige nur innerhalb des Pakets sichtbar sind. Dies würde die Kopplung zwischen Klassen minimieren, die nicht gekoppelt werden sollten, da sie unterschiedliche Merkmale betreffen. Der paketweise Ansatz nutzt keine Modifikatoren für die Sichtbarkeit von Paketen, und Pakete in einem solchen Projekt weisen eine geringe Kohäsion und einen hohen Grad an Kopplung zwischen Paketen auf.
Nate Reed
Haben Sie ein Beispiel dafür? Ich benutze Spring-MVC. Es fällt mir schwer, es nach Feature / Modul zu organisieren, da Spring config xml verwendet.
Eric Huang
2
@onof Ich organisiere meinen Code auch nach Funktionen, aber was sind die Best Practices für Basisklassen, die von allen Funktionen gemeinsam genutzt werden?
Marc
Ich folgte dem ersten Stil. aber jetzt muss ich von einem paket zum anderen springen, wenn ich mit klassen arbeite. Es macht wirklich eine schlechte Erfahrung. Ich wechsle jetzt zum zweiten Stil, weil ich denke, dass es einfacher sein wird, verwandten Klassen zusammen zu folgen.
M. Kazem Akhgary 14.
40

Kurze Antwort: Ein Paket pro Modul / Feature, möglicherweise mit Unterpaketen. Stellen Sie eng verwandte Dinge in einem Paket zusammen. Vermeiden Sie zirkuläre Abhängigkeiten zwischen Paketen.

Lange Antwort: Ich stimme dem größten Teil dieses Artikels zu

Peter Tseng
quelle
2
Unterpakete unterbrechen die Kapselung. Ein "Unterpaket" ist wirklich ein völlig unabhängiges Paket für sich
Ricardo Gamba
21

Ich bevorzuge Features vor Ebenen, aber ich denke, es hängt von Ihrem Projekt ab. Betrachten Sie Ihre Kräfte:

  • Abhängigkeiten
    Versuchen Sie, Paketabhängigkeiten zu minimieren, insbesondere zwischen Features. Extrahieren Sie ggf. APIs.
  • Teamorganisation
    In einigen Organisationen arbeiten Teams an Features und in anderen auf Ebenen. Dies beeinflusst die Organisation des Codes, verwendet ihn zur Formalisierung von APIs oder zur Förderung der Zusammenarbeit.
  • Bereitstellung und Versionierung
    Wenn Sie alles in ein Modul integrieren, wird die Bereitstellung und Versionierung einfacher, die Fehlerbehebung jedoch schwieriger. Das Aufteilen ermöglicht eine bessere Kontrolle, Skalierbarkeit und Verfügbarkeit.
  • Auf Änderungen reagieren
    Gut organisierter Code ist viel einfacher zu ändern als ein großer Schlammball.
  • Größe (Personen und Codezeilen)
    Je größer, desto formalisierter / standardisierter muss es sein.
  • Bedeutung / Qualität
    Einige Codes sind wichtiger als andere. APIs sollten stabiler sein als die Implementierung. Daher muss es klar getrennt werden.
  • Abstraktionsgrad und Einstiegspunkt
    Für einen Außenstehenden sollte es möglich sein, zu wissen, worum es im Code geht und wo er mit dem Lesen des Paketbaums beginnen kann.

Beispiel:

com/company/module
  + feature1/
    - MainClass          // The entry point for exploring
    + api/               // Public interface, used by other features
    + domain/
      - AggregateRoot
      + api/             // Internal API, complements the public, used by web
      + impl/ 
    + persistence/       
    + web/               // presentation layer 
    + services/          // Rest or other remote API 
    + support/            
  + feature2/
  + support/             // Any support or utils used by more than on feature
    + io
    + config
    + persistence
    + web

Dies ist nur ein Beispiel. Es ist ziemlich formal. Zum Beispiel werden 2 Schnittstellen für feature1 definiert . Normalerweise ist dies nicht erforderlich, könnte aber eine gute Idee sein, wenn es von verschiedenen Personen unterschiedlich verwendet wird. Sie können die interne API die Öffentlichkeit erweitern lassen.

Ich mag die "impl" - oder "support" -Namen nicht, aber sie helfen dabei, die weniger wichtigen Dinge von den wichtigen (Domain und API) zu trennen. Wenn es um die Benennung geht, möchte ich so konkret wie möglich sein. Wenn Sie ein Paket namens 'utils' mit 20 Klassen haben, wechseln Sie StringUtilszu support / string, HttpUtilsupport / http usw.

ThomasGran
quelle
13

Gibt es Best Practices in Bezug auf die Organisation von Paketen in Java und was steckt darin?

Nicht wirklich, nein. Es gibt viele Ideen und viele Meinungen, aber echte "Best Practice" ist es, Ihren gesunden Menschenverstand zu verwenden!

(Bitte lesen Sie Keine Best Practices, um eine Perspektive auf "Best Practices" und die Personen, die sie fördern, zu erhalten.)

Es gibt jedoch einen Grundsatz, der wahrscheinlich breite Akzeptanz findet. Ihre Paketstruktur sollte die (informelle) Modulstruktur Ihrer Anwendung widerspiegeln, und Sie sollten darauf abzielen, zyklische Abhängigkeiten zwischen Modulen zu minimieren (oder im Idealfall vollständig zu vermeiden).

(Zyklische Abhängigkeiten zwischen Klassen in einem Paket / Modul sind in Ordnung, aber Zyklen zwischen Paketen erschweren das Verständnis der Architektur Ihrer Anwendung und können ein Hindernis für die Wiederverwendung von Code darstellen. Insbesondere wenn Sie Maven verwenden, werden Sie feststellen, dass zyklisch Abhängigkeiten zwischen Paketen und Modulen bedeuten, dass das gesamte miteinander verbundene Durcheinander ein Maven-Artefakt sein muss.)

Ich sollte noch hinzufügen, dass es ist für Paketnamen eine weithin akzeptierte Best Practice. Und das heißt, Ihre Paketnamen sollten mit dem Domainnamen Ihrer Organisation in umgekehrter Reihenfolge beginnen. Wenn Sie diese Regel befolgen, verringern Sie die Wahrscheinlichkeit von Problemen, die dadurch verursacht werden, dass Ihre (vollständigen) Klassennamen mit denen anderer Personen in Konflikt geraten.

Stephen C.
quelle
9

Ich habe einige Leute gesehen, die "Paket für Feature" über "Paket für Schicht" beworben haben, aber ich habe über viele Jahre hinweg einige Ansätze verwendet und "Paket für Schicht" viel besser gefunden als "Paket für Feature".

Darüber hinaus habe ich festgestellt, dass eine Hybridstrategie: "Paket für Modul, Schicht dann Feature" in der Praxis sehr gut funktioniert, da sie viele Vorteile von "Paket für Feature" bietet:

  • Fördert die Erstellung wiederverwendbarer Frameworks (Bibliotheken mit Modell- und UI-Aspekten)
  • Ermöglicht Plug-and-Play-Layer-Implementierungen - mit 'package by feature' praktisch unmöglich, da Layer-Implementierungen im selben Paket / Verzeichnis wie der Modellcode abgelegt werden.
  • Viel mehr...

Ich erkläre hier ausführlich: Struktur und Organisation des Java-Paketnamens Paketnamens, aber meine Standardpaketstruktur lautet:

revdomain.moduleType.moduleName.layer. [layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

Wo:

revdomain Reverse Domain zB com.mycompany

moduleType [app * | framework | util]

Modulname, z. B. myAppName, wenn der Modultyp eine App ist, oder 'Finanzen', wenn es sich um ein Buchhaltungsframework handelt

Ebene [Modell | UI | Persistenz | Sicherheit usw.]

layerImpl zB Wicket, jsp, jpa, jdo, hibernate (Hinweis: Wird nicht verwendet, wenn die Ebene ein Modell ist)

Merkmal zB Finanzen

UnterfunktionN zB Buchhaltung

Unterfunktion N + 1, z. B. Abschreibung

* Manchmal wurde 'app' weggelassen, wenn moduleType eine Anwendung ist, aber wenn Sie es dort einfügen, wird die Paketstruktur über alle Modultypen hinweg konsistent.

Volksman
quelle
5

Ich kenne keine Standardpraktiken für die Paketorganisation. Ich erstelle im Allgemeinen Pakete, die ein ziemlich breites Spektrum abdecken, aber ich kann innerhalb eines Projekts unterscheiden. Zum Beispiel enthält ein persönliches Projekt, an dem ich gerade arbeite, ein Paket, das meinen benutzerdefinierten UI-Steuerelementen gewidmet ist (voll von Klassen, die Swing-Klassen unterordnen). Ich habe ein Paket für meine Datenbankverwaltung, ein Paket für eine Reihe von Listenern / Ereignissen, die ich erstellt habe, und so weiter.

Andererseits habe ich von einem Kollegen ein neues Paket für fast alles erstellen lassen, was er getan hat. Jede andere MVC, die er wollte, bekam ein eigenes Paket, und es schien, dass ein MVC-Satz die einzige Gruppierung von Klassen war, die sich im selben Paket befinden durfte. Ich erinnere mich, dass er einmal 5 verschiedene Pakete hatte, die jeweils eine Klasse enthielten. Ich denke, seine Methode ist ein bisschen extrem (und das Team hat ihn gezwungen, seine Paketanzahl zu reduzieren, wenn wir einfach nicht damit umgehen konnten), aber für eine nicht triviale Anwendung würde man also alles in dasselbe Paket packen. Es ist ein Gleichgewichtspunkt, den Sie und Ihre Teamkollegen selbst finden müssen.

Eine Sache, die Sie tun können, ist zu versuchen, einen Schritt zurückzutreten und zu überlegen: Wenn Sie ein neues Mitglied wären, das in das Projekt eingeführt wurde, oder Ihr Projekt als Open Source oder API veröffentlicht wurde, wie einfach / schwierig wäre es, das zu finden, was Sie wollen? Denn genau das möchte ich von Paketen: Organisation. Ähnlich wie beim Speichern von Dateien in Ordnern auf meinem Computer erwarte ich, dass ich sie wiederfinden kann, ohne mein gesamtes Laufwerk durchsuchen zu müssen. Ich erwarte, die gewünschte Klasse finden zu können, ohne die Liste aller Klassen im Paket durchsuchen zu müssen.

Brian S.
quelle