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

Литература

Примечания

Категория:Шаблоны проектирования