Я работаю над стандартным веб-приложением с доменом, организованным по концепциям DDD. Мне интересно, какие объекты мои приложения должны принимать и возвращать. Скажем, у меня есть служба приложений для User
aggregate.
1) DTOs/простые типы (строка, int и т.д.)
public interface UserApplicationService {
void registerUser(UserDTO userDTO);
List<UserDTO> getUsersForOrganization(String organizationId);
}
В этом случае служба приложения отвечает за вызов ассемблера, который преобразует DTO в объекты домена и наоборот.
Преимущество этого подхода в том, что моя служба приложений является четкой границей для моих объектов домена. Еще одна проблема заключается в том, что служба приложений является четкой границей транзакций. Объекты домена, управляемые контекстом персистентности, не течет где-то за пределами транзакции.
Недостатком является то, что в случае форм проверка должна основываться на DTO. Поэтому мои правила проверки дублируются между доменом (объект отвечает за его состояние) и правилами проверки DTO. (Как в случае Spring пример приложения MVC). Кроме того, если для некоторых частей зрения требуется другая форма модели (скажем, у UserDTO недостаточно информации для визуализации), мне нужно будет создать еще один DTO и базу на пару DTO, возвращенных из службы приложений, составить еще одну, используемый для просмотра.
2) Типы доменов
public interface UserApplicationService {
void registerUser(User user);
List<User> getUsersForOrganization(OrganizationId organizationId);
}
В этом случае контроллер/ведущий отвечает за преобразование.
Большой недостаток заключается в том, что объекты моего домена протекают из службы приложений - нет четкого разделения. Кроме того, где наши границы транзакций? Доменные объекты, к которым может быть присоединен, например, сеанс Hibernate, утечки вне уровня служб приложений. (Тем не менее, я заметил, что это то, как написано множество примеров приложений.)
Преимущество может заключаться в том, что диспетчер/ведущий отвечает за подготовку модели для просмотра, поэтому он может составлять DTO на основе требований к представлению. Например, для просмотра может потребоваться дополнительная информация, которая не возвращается в DTO из #getUsersForOrganizationMethod. Кроме того, проверка может основываться на объектах домена, поэтому она не дублируется между DTO и объектами домена.
3) Объекты домена + фасад
Это третий вариант, используемый в приложении DDDsample. Службы приложений возвращают типы доменов, но есть некоторый фасад, который отвечает за преобразование. Таким образом, в моем случае, диспетчер/ведущий разговаривает с фасадом с DTO, фасад делает трансформацию и разговаривает с приложениями, использующими объекты домена. Однако, по моему скромному мнению, это кажется немного подавляющим - слишком много слоев, слишком много шаблонов. Для одного приложения это может показаться здоровым, но если у нас их было десятки, нам нужно иметь одинаковое количество фасадных методов - чистое дублирование. Кроме того, где границы транзакций?