Wenn man ein Domain-Driven Design mit Spring JPA umsetzt (so wie wir das z.B. im ST2-Praktikum machen), dann sollten alle Entwickler:innen im Team dieselben Konventionen für die Strukturierung des Codes verwenden. Nur so bleibt der Code übersichtlich und wartbar. Für ST2 geben wir eine bestimmte Konvention vor, wie die Packages strukturiert werden sollen. In der Praxis gibt es viele verschiedene Varianten hiervon. Diese ist genauso gut wie andere mögliche Konventionen - aber auf irgendetwas müssen wir uns ja einigen.
Mit dieser Konvention gehen wir davon aus, die die Top-Level-Packages in Ihrem Projekt den Aggregates entsprechen. Das sind die “Haupt-Geschäftsobjekte” in Ihrem Projekt. (Siehe die obigen Videos zur Erklärung, was genau Aggregates sind, und wie man sie findet.)
Die Namenskonvention ist einfach der Name des Aggregates in Kleinbuchstaben und Singular (Einzahl).
Damit ist festgelegt, dass Ihr Softwaresystem vertikal geschnitten ist: Es gibt Packages für die verschiedenen “Teil-Domänen” Ihrer Anwendung. Innerhalb dieser Aggregate-Packages müssen wir dann eine Schichtenarchitektur abbilden. Dabei folgen wir der 4-schichtigen Architektur nach Eric Evans (siehe das “Blue Book”). Diese geht von vier Schichten aus
Somit bilden wir die Schichten (2) und (3) in jedem Aggregate ab. Das bedeutet, dass jedes Aggregate zwei Sub-Packages
hat, nämlich application
und domain
. In dem nachfolgenden Bild sind die Regeln zusammengefasst, und dann danach einzeln
erklärt.
application
Hier liegen die Application Services, Controller, Adapter, DTOs, … also alles, was für die Kommunikation mit “außen”
benötigt wird. In erster Näherung kann man sagen: Alles, was in Spring mit @Service
oder @RestController
annotiert wird,
kommt in dieses Package.
Als Namenskonvention gilt:
@Service
annotiert wird, heißt ...Service
@RestController
annotiert wird, heißt ...Controller
domain
Dieses Package enthält die Entities, Value Objects, und Repositories des Aggregates. Hier liegt also die eigentliche Geschäftslogik der Anwendung.
Als Namenskonvention gilt:
$BasketClass$
)Repository
(z.B. $BasketClass$Repository
)