Data Transfer Object (DTO) — один из шаблонов проектирования, используется для передачи данных между подсистемами приложения, чтобы уменьшить количество вызовов методов (например, базы данных), снизить сетевую нагрузку. Впервые представлен Мартином Фаулером в своей книге «Шаблоны корпоративных приложений» в 2002 году.
Особенности
Как правило, создаётся плоская структура данных без бизнес-логики (поведения). Только хранилище, методы доступа, и, по необходимости, методы сериализации и синтаксического анализа.
Данные сопоставляются из доменных моделей с DTO, как правило, с помощью компонента сопоставления в слое представления или фасадном слое.
Пример
Например, мобильному приложению нужно показать информацию о человеке: аватар и имя. Внутри системы User хранится пароль, идентификатор, номер телефона и прочие служебные данные. Чтобы не передавать данные целиком, создавая нагрузку на сеть, и не раскрывать внутреннюю структуру создаётся простой UserDto, содержащий только имя и аватар — что и требуется приложению.
Преимущества Снижение количества вызова методов, как следствие снижение сетевой нагрузки. Инкапсуляция логики сериализации, что обеспечивает единую абстракцию сериализации. Отделение доменной модели от уровня представления.
Когда его использовать? Полезны в системах с удалёнными вызовами, помогая сокращать их количество. Когда доменная модель состоит из множества различных объектов, а презентационной модели требуются все эти данные. Когда необходимо на основе нескольких моделей создать новое представления. Когда упаковка различных запросов, упаковывается в единый интерфейс, что прямо сокращает сетевой трафик.
Пример public class User { private String id; private String name; private String password; private List<Role> roles; }
public class Role { private String id; private String name; }
DTO, который исключает пароль public class UserDTO { private String name; private List<String> roles; }
class UserController { private UserService userService; private RoleService roleService; private Mapper mapper;
@GetMapping @ResponseBody public List<UserDTO> getUsers() { return userService.getAll() .stream() .map(mapper::toDto) .collect(toList());
@Component class Mapper { public UserDTO toDto(User user) { String name = user.getName(); List<String> roles = user .getRoles() .stream() .map(Role::getName) .collect(toList());
return new UserDTO(name, roles);
Распространенные ошибки
Создание DTO под каждый случай. Это увеличивает количество классов и мапперов, которые предстоит поддерживать. Избегать внедрения DTO, оставляя единый большой контракт для множества сценариев, где многие атрибуты не используются, но передаются по сети. Добавление бизнес-логики в класс DTO. Создание LocalDTO, для передачи данных между доменными областями.
Аналоги Аналогичный результат, но специализирующийся на более сложных сценариях: CQRS Data Mappers CommandQuerySeparation
Критика Егор Бугаенко считает, что DTO нарушает фундаментальный принцип инкапсуляции в ООП, инкапсулируя данные других объектов, которые в свою очередь инкапсулируют данные в себе.
В Java В Enterprise JavaBeans DTO используется для сериализации.
Entity beans представляют объекты, находящиеся в постоянном хранилище, например, в базе данных. С одной стороны, это очень удобно, так как программа-клиент не должна заботиться о подсоединении к базе данных напрямую. С другой стороны, каждое изменение в entity bean может вызывать методы удалённого доступа, что увеличивает нагрузку на сеть и снижает скорость работы программы. Sun Java Center порекомендовал для решения этой проблемы изолировать все данные в отдельный объект и передавать этот объект в entity bean одним методом.
В версии EJB 3.0 модель записи данных была изменена, эта проблема была разрешена и нужда в DTO отпала.
Не следует путать DTO с Value Object — это разные паттерны. Путаница вызвана тем, что в ранней литературе по J2EE для описания DTO использовался термин «Value Object», однако позже его заменили на «Transfer Object».
Ссылки Transfer Object в каталоге шаблонов J2EE GeDA — библиотека для DTO с открытым кодом для Java
Литература
Примечания
Категория:Шаблоны проектирования