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 Orderzur Ansicht übergehen , können Sie mit needToDeliver()ausgewählt Orderdie 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 Orderund seine LineItemist in einer Transaktion. Wenn einer der LineItemnicht erstellt werden kann, wird kein Ordererstellt.
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 deliveryAttributen und zum Ignorieren erstellen bonus, z repository.findOrderByNumberFetchDelivery(). Im Bonusbildschirm rufe ich eine andere Methode auf, die bonusAttribute lädt und ignoriert delivery, z repository.findOrderByNumberFetchBonus(). Dies erfordert Disziplin, da ich immer noch nicht deliver()im Bonusbildschirm anrufen kann .