Spring Entities должны конвертировать в Dto в сервисе?

После комментария к этому вопросу. Я начал заниматься исследованиями, но я все еще смущен.
Объекты должны преобразовываться в Dto перед возвратом в контроллер? Для меня это звучит не очень практично.

Ответ 1

Мы говорим о архитектуре программного обеспечения, и, как всегда, когда мы говорим о архитектуре программного обеспечения, существует тысяча способов сделать что-то и много мнений о том, что является лучшим способом. Но нет лучшего способа, все имеет свои преимущества и недостатки. Имейте это в виду!

Обычно у вас разные слои:

  • Уровень сохранения для хранения данных
  • Бизнес-уровень для работы с данными
  • Уровень презентации для отображения данных

Как правило, каждый слой будет использовать свой собственный вид объектов:

  • Стойкость: Хранилища, Сущности
  • Бизнес-уровень: услуги, объекты домена
  • Уровень презентации: контроллеры, DTO

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

Зачем? Потому что вы хотите, чтобы каждый слой был отделен от других слоев. Если вы будете использовать сущности в своем контроллере, ваша презентация будет зависеть от того, как хранятся ваши данные. Это очень плохо. Ваше представление не имеет никакого отношения к тому, как хранятся данные. Он не должен даже знать, что и как хранятся данные.

Подумайте об этом: вы меняете свою модель базы данных, например, добавляете новый столбец в одну из таблиц базы данных. Если вы передадите объекты контроллеру (или, что еще хуже: ваш контроллер предоставляет их как JSON), изменение в базе данных приведет к изменению вашей презентации. Если объекты напрямую отображаются как JSON, это может даже привести к изменениям в JavaScript или некоторых других клиентах, которые используют JSON. Поэтому для простого изменения базы данных может потребоваться изменение в интерфейсе JavaScript, потому что вы очень сильно соедините свои слои. Вы определенно не хотите этого в реальном проекте.

Как? Вы сомневаетесь, что это практично, поэтому просто небольшой пример того, как это сделать в (псевдо) коде:

class Repository {
    public Person loadById(Long id) {
        PersonEntity entity = loadEntityById(id);
        Person person = new Person();
        person.setId(entity.getId());
        person.setName(entity.getFirstName + " " + entity.getLastName());
        return person;
    }
}

В этом примере ваш репозиторий будет использовать сущности внутри. Ни один другой слой не знает или не использует эти сущности! Это деталь реализации этого конкретного слоя. Поэтому, если репозиторию будет предложено вернуть "человек", он будет работать с сущностью, но он вернет объект домена. Таким образом, доменный уровень, который работает с репо, сохраняется в случае, если объекты необходимо изменить. И, как вы можете видеть в случае имени, домен и база данных могут быть разными. Пока база данных хранит имя от имени и фамилии, домен знает только одно имя. Это подробная информация о том, как сохранить имя.

То же самое касается контроллеров и DTO, всего лишь одного слоя.