Перейти к содержанию

DTO

Материал из Википедии — свободной энциклопедии

Data Transfer Object (DTO) — один из шаблонов проектирования, используется для передачи данных между подсистемами приложения[1], чтобы уменьшить количество вызовов методов (например, базы данных), снизить сетевую нагрузку[1][2]. Впервые представлен Мартином Фаулером в своей книге «Шаблоны корпоративных приложений» в 2002 году[2].

Особенности

[править | править код]

Как правило, создаётся плоская структура данных без бизнес-логики (поведения)[1]. Только хранилище, методы доступы, и, по необходимости, методы сериализации и синтаксического анализа[1].

Данные сопоставляются из доменных моделей с DTO, как правило, с помощью компонента сопоставления в слое представления или фасадном слое[1].

Например, мобильному приложению нужно показать информацию о человеке: аватар и имя. Внутри системы User хранится пароль, идентификатор, номер телефона и прочие служебные данные. Чтобы не передавать данные целиком, создавая нагрузку на сеть, и не раскрывать внутреннюю структуру создаётся простой UserDto, содержащий только имя и аватар — что и требуется приложению[1].

Преимущества

[править | править код]
  1. Снижение количества вызова методов, как следствие снижение сетевой нагрузки[1].
  2. Инкапсуляция логики сериализации, что обеспечивает единую абстракцию сериализации[1].
  3. Отделение доменной модели от уровня представления[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);
    }
}

Распространенные ошибки

[править | править код]
  1. Создание DTO под каждый случай. Это увеличивает количество классов и мапперов, которые предстоит поддерживать[1].
  2. Избегать внедрения DTO, оставляя единый большой контракт для множества сценариев, где многие атрибуты не используются, но передаются по сети[1].
  3. Добавление бизнес-логики в класс DTO[1].
  4. Создание LocalDTO, для передачи данных между доменными областями[1].

Аналогичный результат, но специализирующийся на более сложных сценариях[1]:

Егор Бугаенко считает, что DTO нарушает фундаментальный принцип инкапсуляции в ООП, инкапсулируя данные других объектов, которые в свою очередь инкапсулируют данные в себе[3].

В 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».

Литература

[править | править код]
  • Мартин Фаулер. Шаблоны корпоративных приложений (Signature Series) = Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series). — М.: «Вильямс», 2012. — 544 с. — ISBN 978-5-8459-1611-2.

Примечания

[править | править код]
  1. 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 года.
  2. 1 2 P of EAA. Дата обращения: 22 февраля 2026. Архивировано 19 февраля 2026 года.
  3. Data Transfer Object Is a Shame. Дата обращения: 22 февраля 2026. Архивировано 31 января 2026 года.