Однією з переваг багатих класів доменів є те, що ви можете викликати їх поведінку (методи) щоразу, коли у вас є посилання на об’єкт на будь-якому рівні. Крім того, ви схильні писати невеликі та розподілені методи, які співпрацюють разом. У анемічних класах доменів ви схильні писати жирні процедурні методи (на сервісному рівні), які, як правило, визначаються варіантом використання. Вони, як правило, менш ремонтопридатні порівняно з багатими класами доменів.
Приклад класів домену з поведінкою:
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()
}
}
Метод needToDeliver()
поверне список товарів, які потрібно доставити, включаючи бонус. Його можна викликати всередині класу, з іншого пов'язаного класу або з іншого рівня. Наприклад, якщо ви переходите Order
до перегляду, тоді ви можете використовувати needToDeliver()
вибраний Order
для відображення списку елементів, що підтверджуються користувачем, перш ніж вони натискають кнопку збереження, щоб зберегти Order
.
Відповідаючи на коментар
Ось як я використовую клас домену з контролера:
def save = {
Order order = new Order()
order.addItem(new Item())
order.addItem(new Item())
repository.create(order)
}
Створення Order
і його LineItem
- в одній транзакції. Якщо одне з LineItem
неможливо створити, не Order
буде створено жодного .
Я, як правило, маю метод, який представляє одну транзакцію, такий як:
def deliver = {
Order order = repository.findOrderByNumber('ORDER-1')
order.deliver()
// save order if necessary
}
Що-небудь усередині deliver()
буде виконано як одна транзакція. Якщо мені потрібно виконати багато не пов’язаних між собою методів за одну транзакцію, я б створив клас обслуговування.
Щоб уникнути винятку з лінивого завантаження, я використовую графік сутності JPA 2.1 з іменем. Наприклад, у контролері екрана доставки я можу створити метод для завантаження delivery
атрибута та ігнорування bonus
, наприклад repository.findOrderByNumberFetchDelivery()
. На екрані бонусів я називаю інший метод, який завантажує bonus
атрибут та ігнорує delivery
, наприклад repository.findOrderByNumberFetchBonus()
. Для цього потрібен dicipline, оскільки я все ще не можу зателефонувати deliver()
на бонусний екран.