Uno dei vantaggi delle ricche classi di dominio è che puoi chiamare il loro comportamento (metodi) ogni volta che hai il riferimento all'oggetto in qualsiasi livello. Inoltre, tendi a scrivere metodi piccoli e distribuiti che collaborano insieme. Nelle classi di dominio anemiche, si tende a scrivere metodi procedurali pesanti (nel livello di servizio) che di solito sono guidati dal caso d'uso. Di solito sono meno gestibili rispetto alle classi di domini ricchi.
Un esempio di classi di dominio con comportamenti:
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()
}
}
Il metodo needToDeliver()
restituirà l'elenco degli articoli che devono essere consegnati incluso il bonus. Può essere chiamato all'interno della classe, da un'altra classe correlata o da un altro livello. Ad esempio, se si passa Order
alla visualizzazione, è possibile utilizzare needToDeliver()
di selezionato Order
per visualizzare l'elenco di elementi che devono essere confermati dall'utente prima che faccia clic sul pulsante Salva per persistere Order
.
Risposta al commento
Ecco come utilizzo la classe di dominio dal controller:
def save = {
Order order = new Order()
order.addItem(new Item())
order.addItem(new Item())
repository.create(order)
}
La creazione di Order
e la sua LineItem
è in un'unica transazione. Se uno dei LineItem
non può essere creato, non Order
verrà creato nessuno .
Tendo ad avere metodi che rappresentano una singola transazione, come ad esempio:
def deliver = {
Order order = repository.findOrderByNumber('ORDER-1')
order.deliver()
// save order if necessary
}
Qualsiasi cosa all'interno deliver()
verrà eseguita come una singola transazione. Se ho bisogno di eseguire molti metodi non correlati in una singola transazione, creerei una classe di servizio.
Per evitare un'eccezione di caricamento lento, utilizzo il grafico di entità denominato JPA 2.1. Ad esempio, nella schermata del controller per la consegna, posso creare un metodo per caricare l' delivery
attributo e ignorare bonus
, come repository.findOrderByNumberFetchDelivery()
. Nella schermata bonus, chiamo un altro metodo che carica l' bonus
attributo e ignoro delivery
, come repository.findOrderByNumberFetchBonus()
. Ciò richiede dicipline poiché non riesco ancora a chiamare deliver()
nella schermata bonus.