Подтвердить что ты не робот

DTO: лучшие практики

Я рассматриваю возможность использования DTO вместо того, чтобы передавать объекты моего домена. Я прочитал несколько сообщений здесь, как и в других местах, и я понимаю, что есть несколько способов сделать это.

Если у меня всего около 10 классов домена во всех, и учитывая, что я хочу использовать DTO, а не объекты домена для потребления в моих представлениях (передние части WPF), то какой рекомендуемый подход. Я думаю, что использование таких инструментов, как automapper и т.д., Может быть, излишним для моей ситуации. Поэтому я подумываю написать свой собственный класс mapper, который будет иметь методы для преобразования типа домена в тип DTO.

Каков наилучший способ сделать это, есть ли образец, чтобы заставить меня начать это делать?

Второй вопрос: когда вы пишете те методы, которые будут создавать DTO, как я могу справиться с настройкой всех данных, особенно если тип домена имеет ссылки на другие объекты домена? Я пишу эквивалентные свойства в DTO для сопоставления этим типам ссылок в классе домена? Пожалуйста, спросите, не поставил ли я свой второй вопрос правильно. Но я думаю, вы понимаете, что я пытаюсь спросить.

Вопрос Thrid: при написании DTO я должен написать несколько DTO, каждый из которых содержит частичные данные для данной модели домена, так что каждый из них может использоваться для удовлетворения конкретного требования View или если у DTO есть все данные которые находятся в соответствующем классе модели.

4b9b3361

Ответ 1

Я читал несколько сообщений здесь о DTO, и мне кажется, что многие люди приравнивают их к тому, что я считаю ViewModel. DTO - это просто объект передачи данных - это то, что передается по кабелю. Таким образом, у меня есть сайт и службы, только сервисы будут иметь доступ к реальным объектам домена/объекта и возвращать DTO. Они могут отображать 1:1, но считают, что DTO может быть заполнен из другого вызова службы, запроса базы данных, чтения конфигурации - что угодно.

После этого веб-сайт затем может взять эти DTO и либо добавить их в ViewModel, либо преобразовать в один. Этот ViewModel может содержать много разных типов DTO. Простым примером может быть диспетчер задач - ViewModel содержит как объект задачи, который вы редактируете, так и группу объектов Dto.User, к которым может быть назначена задача.

Имейте в виду, что службы, возвращающие DTO, могут использоваться как веб-сайтом, так и, возможно, планшетом или телефоном. Эти приложения будут иметь разные представления, чтобы использовать свои дисплеи, и поэтому ViewModels будут отличаться, но DTO останется прежним.

Во всяком случае, мне нравятся такие типы обсуждений, поэтому кто-нибудь, пожалуйста, сообщите мне, что вы думаете.

Matt

Ответ 2

Я использую DTO в проекте. Я склонен сделать DTO только для отображения данных, которые мне нужны для определенного вида. Я извлекаю все данные, показанные в представлении, в моем классе доступа к данным. Например, у меня может быть объект Order, который ссылается на объект Client:

public class Client{
    public int Id{get;set;}
    public string Name{get;set;}
}

public class Order{
    public int OrderID{get;set;}
    public Client client{get;set;}
    public double Total{get;set;}
    public IEnumerable<OrderLine> lines {get;set;}
}

Тогда в моем OrderListDTO у меня может быть что-то вроде:

public class OrderListDTO{
    public int OrderId{get;set;}
    public string ClientName{get;set;}
    ...
 }

Какие поля я хочу показать на мой взгляд. Я извлекаю все эти поля в свой код доступа к базе данных, поэтому мне не нужно беспокоиться об объединении сущностей в моем представлении или коде контроллера.

Ответ 3

Я прихожу к проекту с spring-jdbc, и используется DAO. Несколько раз существующие сущности не охватывают все возможные данные из БД. Поэтому я начинаю использовать DTO.

Применяя правило программирования структуры 70, я помещаю все DTO в отдельный пакет:

package com.evil.dao;     // DAO interfaces for IOC.
package com.evil.dao.impl; // DAO implementation classes.
package com.evil.dao.dto; // DTOs

Теперь я переосмыслил и решил разместить все DTO в качестве внутренних классов на интерфейсах DAO для наборов результатов, которые не имеют повторного использования. Таким образом, интерфейс DAO выглядит так:

interface StatisticDao {
    class StatisticDto {
        int count;
        double amount;
        String type;

        public static void extract(ResultSet rs, StatisticDto dto) { ... }
    }

    List<StatisticDto> getStatistic(Criteria criteria);
}


class StatisticDaoImpl implements StatisticDao {
    List<StatisticDto> getStatistic(Criteria criteria) {
        ...
        RowCallbackHandler callback = new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                StatisticDao.StatisticDto.extract(rs, dto);
                // make action on dto
            }
        }
        namedTemplate.query(query, queryParams, callback);
    }
}

Я думаю, что совместное хранение связанных данных (пользовательский DTO с интерфейсом DAO) делает код лучше для PageUp/PageDown.

Ответ 4

Лучший способ разработки DTO

Способ начать разработку DTO заключается в понимании того, что их единственной целью является передача подмножества данных ваших бизнес-объектов различным клиентам (может быть пользовательский интерфейс или внешняя служба). Учитывая это понимание, вы можете создавать отдельные пакеты для каждого клиента... и писать свои классы DTO. Для сопоставления вы можете написать собственный интерфейс, определяющий интерфейс, который будет передан в factory создание объектов DTO, на основе которых будут извлекаться данные из объекта, для которого создается DTO. Вы также можете определить аннотации, которые будут помещены в ваши сущности, но лично учитывая количество используемых аннотаций, я бы предпочел интерфейс. Главное, что следует помнить о DTO, это то, что они также являются классами, а данные между DTO должны быть повторно использованы, другими словами, хотя может показаться соблазнительным создание DTO для каждого варианта использования, попробуйте повторно использовать существующие DTO, чтобы свести к минимуму это.

Начало работы

Что касается начала работы, как указано выше, единственной целью DTO является предоставление клиенту данных, которые ему нужны... поэтому вы помните, что можете просто установить данные в dto с помощью seters... или определить a factory, который создает DTO из Entity на основе интерфейса.....

Что касается третьего вопроса, сделайте то, что требуется вашему клиенту:)

Ответ 5

Я собираюсь предположить, что объекты вашей модели домена имеют идентификатор первичного ключа, который может соответствовать идентификатору из базы данных или хранилища, из которого они пришли.

Если вышесказанное верно, тогда ваш DTO преодолеет тип реферирования с другим DTO, как и ваши объекты домена, в виде идентификатора внешнего ключа. Таким образом, отношение OrderLine.OrderHeader к объекту домена будет OrderLine.OrderHeaderId cin DTO.

Надеюсь, что это поможет.

Могу ли я спросить, почему вы решили использовать DTO вместо ваших объектов с богатым доменом в представлении?

Ответ 6

Мы все знаем, что такое Dtos (вероятно). Но главное - злоупотреблять DTO или нет.

Передача данных с использованием Dtos между "локальными" службами является хорошей практикой, но требует огромных накладных расходов для вашей команды разработчиков.

Есть несколько фактов:

  1. Клиенты не должны видеть или взаимодействовать с сущностями (Daos). Так что вы всегда нужны Dtos для передачи данных в/из удаленного (вне процесса).
  2. Использование Dtos для передачи данных между сервисами необязательно. Если вы не планируете разделять ваш проект на микросервисы, вам не нужно этого делать. Это будет просто накладные расходы для вас.

И это мой комментарий: Если вы планируете распространять свой проект на микросервисы в долгом будущем. или не планируйте сделать это, тогда НЕ ПРЕОДОЛЯЙТЕ DTO

Вам нужно прочитать эту статью https://martinfowler.com/bliki/LocalDTO.html

Ответ 7

Вопрос 1: Если DTO, которое вам нужно перенести, является простым подмножеством вашего доменного объекта, вы можете использовать модель-маппер, чтобы избежать заполнения вашей кодовой базы отображением без логики. Но если вам нужно применить логику/преобразование к вашему отображению, сделайте это сами.

Вопрос 2: Вы можете и, вероятно, должны создать DTO для каждого объекта домена, который есть в вашем основном DTO. DTO может иметь несколько DTO внутри, по одному для каждого объекта домена, который вам нужно отобразить. И чтобы отобразить их, вы можете сделать это самостоятельно или даже использовать модель-картограф.

Вопрос 3: Не раскрывайте весь свой домен, если ваше мнение не требует этого. Кроме того, вам не нужно создавать DTO для каждого представления, попробуйте создать DTO, которое отображает то, что необходимо показать, и может быть использовано повторно, чтобы избежать множественных DTO, которые разделяют много информации. Но это в основном зависит от потребностей вашего приложения.

Если вам нужно разъяснение, просто спросите.