L'un des avantages des classes de domaine riches est que vous pouvez appeler leur comportement (méthodes) chaque fois que vous avez la référence à l'objet dans n'importe quelle couche. De plus, vous avez tendance à écrire des méthodes petites et distribuées qui collaborent ensemble. Dans les classes de domaine anémique, vous avez tendance à écrire des méthodes procédurales lourdes (dans la couche de service) qui sont généralement gérées par un cas d'utilisation. Ils sont généralement moins maintenables que les classes de domaine riches.
Un exemple de classes de domaine avec des comportements:
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()
}
}
La méthode needToDeliver()
retournera la liste des articles qui doivent être livrés, y compris les bonus. Il peut être appelé à l'intérieur de la classe, depuis une autre classe associée ou depuis une autre couche. Par exemple, si vous passez Order
à la vue, vous pouvez utiliser les éléments needToDeliver()
sélectionnés Order
pour afficher la liste des éléments à confirmer par l'utilisateur avant de cliquer sur le bouton Enregistrer pour conserver leOrder
.
Répondre au commentaire
Voici comment j'utilise la classe de domaine du contrôleur:
def save = {
Order order = new Order()
order.addItem(new Item())
order.addItem(new Item())
repository.create(order)
}
La création de Order
et son LineItem
est en une seule transaction. Si l'un des LineItem
ne peut pas être créé, nonOrder
ne sera créé.
J'ai tendance à avoir une méthode qui représente une seule transaction, telle que:
def deliver = {
Order order = repository.findOrderByNumber('ORDER-1')
order.deliver()
// save order if necessary
}
Tout ce qu'il y a à l'intérieur deliver()
sera exécuté en une seule transaction. Si je dois exécuter de nombreuses méthodes non liées en une seule transaction, je créerais une classe de service.
Pour éviter une exception de chargement paresseux, j'utilise le graphique d'entité nommé JPA 2.1. Par exemple, dans l'écran du contrôleur pour la livraison, je peux créer une méthode pour charger l' delivery
attribut et ignorer bonus
, comme repository.findOrderByNumberFetchDelivery()
. Dans l'écran bonus, j'appelle une autre méthode qui charge l' bonus
attribut et l'ignore delivery
, telle que repository.findOrderByNumberFetchBonus()
. Cela nécessite dicipline car je ne peux toujours pas appeler à l' deliver()
intérieur de l'écran bonus.