Einer der Vorteile von Rich Domain-Klassen besteht darin, dass Sie ihr Verhalten (Methoden) jedes Mal aufrufen können, wenn Sie den Verweis auf das Objekt in einer beliebigen Ebene haben. Außerdem neigen Sie dazu, kleine und verteilte Methoden zu schreiben, die zusammenarbeiten. In anämischen Domänenklassen neigen Sie dazu, fette Verfahrensmethoden (in der Serviceschicht) zu schreiben, die normalerweise vom Anwendungsfall abhängen. Sie sind im Vergleich zu Rich-Domain-Klassen normalerweise weniger wartbar.
Ein Beispiel für Domänenklassen mit Verhalten:
class Order {
String number
List<OrderItem> items
ItemList bonus
Delivery delivery
void addItem(Item item) { // add bonus if necessary }
ItemList needToDeliver() { // items + bonus }
void deliver() {
delivery = new Delivery()
delivery.items = needToDeliver()
}
}
Die Methode needToDeliver()
gibt eine Liste der Artikel zurück, die geliefert werden müssen, einschließlich Bonus. Es kann innerhalb der Klasse, von einer anderen verwandten Klasse oder von einer anderen Ebene aufgerufen werden. Wenn Sie beispielsweise Order
zur Ansicht übergehen , können Sie mit needToDeliver()
ausgewählt Order
die Liste der Elemente anzeigen, die vom Benutzer bestätigt werden sollen, bevor er auf die Schaltfläche Speichern klickt, um die Anzeige beizubehalten Order
.
Auf Kommentar antworten
So verwende ich die Domänenklasse vom Controller:
def save = {
Order order = new Order()
order.addItem(new Item())
order.addItem(new Item())
repository.create(order)
}
Die Erstellung von Order
und seine LineItem
ist in einer Transaktion. Wenn einer der LineItem
nicht erstellt werden kann, wird kein Order
erstellt.
Ich neige dazu, Methoden zu haben, die eine einzelne Transaktion darstellen, wie zum Beispiel:
def deliver = {
Order order = repository.findOrderByNumber('ORDER-1')
order.deliver()
// save order if necessary
}
Alles, was sich darin befindet, deliver()
wird als eine einzige Transaktion ausgeführt. Wenn ich viele nicht verwandte Methoden in einer einzigen Transaktion ausführen muss, würde ich eine Serviceklasse erstellen.
Um eine verzögerte Ladeausnahme zu vermeiden, verwende ich JPA 2.1 mit dem Namen Entity Graph. Im Bildschirm "Controller für Zustellung" kann ich beispielsweise eine Methode zum Laden von delivery
Attributen und zum Ignorieren erstellen bonus
, z repository.findOrderByNumberFetchDelivery()
. Im Bonusbildschirm rufe ich eine andere Methode auf, die bonus
Attribute lädt und ignoriert delivery
, z repository.findOrderByNumberFetchBonus()
. Dies erfordert Disziplin, da ich immer noch nicht deliver()
im Bonusbildschirm anrufen kann .