DTO
Data Transfer Object (DTO) — один из шаблонов проектирования, используется для передачи данных между подсистемами приложения[1], чтобы уменьшить количество вызовов методов (например, базы данных), снизить сетевую нагрузку[1][2]. Впервые представлен Мартином Фаулером в своей книге «Шаблоны корпоративных приложений» в 2002 году[2].
Особенности
[править | править код]Как правило, создаётся плоская структура данных без бизнес-логики (поведения)[1]. Только хранилище, методы доступы, и, по необходимости, методы сериализации и синтаксического анализа[1].
Данные сопоставляются из доменных моделей с DTO, как правило, с помощью компонента сопоставления в слое представления или фасадном слое[1].
Пример
[править | править код]Например, мобильному приложению нужно показать информацию о человеке: аватар и имя. Внутри системы User хранится пароль, идентификатор, номер телефона и прочие служебные данные. Чтобы не передавать данные целиком, создавая нагрузку на сеть, и не раскрывать внутреннюю структуру создаётся простой UserDto, содержащий только имя и аватар — что и требуется приложению[1].
Преимущества
[править | править код]- Снижение количества вызова методов, как следствие снижение сетевой нагрузки[1].
- Инкапсуляция логики сериализации, что обеспечивает единую абстракцию сериализации[1].
- Отделение доменной модели от уровня представления[1].
Когда его использовать?
[править | править код]- Полезны в системах с удалёнными вызовами, помогая сокращать их количество[1].
- Когда доменная модель состоит из множества различных объектов, а презентационной модели требуются все эти данные[1].
- Когда необходимо на основе нескольких моделей создать новое представления[1].
- Когда упаковка различных запросов, упаковывается в единый интерфейс, что прямо сокращает сетевой трафик[1].
Пример
[править | править код]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 под каждый случай. Это увеличивает количество классов и мапперов, которые предстоит поддерживать[1].
- Избегать внедрения DTO, оставляя единый большой контракт для множества сценариев, где многие атрибуты не используются, но передаются по сети[1].
- Добавление бизнес-логики в класс DTO[1].
- Создание LocalDTO, для передачи данных между доменными областями[1].
Аналоги
[править | править код]Аналогичный результат, но специализирующийся на более сложных сценариях[1]:
Критика
[править | править код]Егор Бугаенко считает, что DTO нарушает фундаментальный принцип инкапсуляции в ООП, инкапсулируя данные других объектов, которые в свою очередь инкапсулируют данные в себе[3].
В 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
Литература
[править | править код]- Мартин Фаулер. Шаблоны корпоративных приложений (Signature Series) = Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series). — М.: «Вильямс», 2012. — 544 с. — ISBN 978-5-8459-1611-2.
Примечания
[править | править код]- ↑ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 The DTO Pattern (Data Transfer Object). Дата обращения: 22 февраля 2026. Архивировано 17 ноября 2025 года.
- ↑ 1 2 P of EAA. Дата обращения: 22 февраля 2026. Архивировано 19 февраля 2026 года.
- ↑ Data Transfer Object Is a Shame. Дата обращения: 22 февраля 2026. Архивировано 31 января 2026 года.