Яке використання DTO замість Entity?


18

Я працюю над додатком RCP, я новачок у цій програмі.

Весняні боби використовуються для написання ділової логіки для збереження / отримання об'єктів.

Але замість того, щоб направляти сутності безпосередньо до клієнта, ми переходимо до DTO та заповнюємо клієнта. Зберігаючи, ми знову перетворюємо DTO на сутність та економимо.

Яка користь від цих конверсій? Може хтось пояснить?


What's the benefit of these conversions?відокремлення моделі даних постійності від запропонованої споживачам моделі даних (представлення). Переваги роз'єднання широко обговорювались у SE, однак мета під DTO полягає в тому, щоб зібрати в одну відповідь стільки інформації, скільки вважається необхідною для клієнтів для збереження дзвінків на сервер. Що робить спілкування клієнт-сервер більш гладким.
Лаїв


Ваш приклад приємний. Коли ти є клієнтом (погляди ...), боляче змінюватись, але найбільша проблема полягає в тому, що в системі вже є інтеграція третьої сторони, що неможливо змінити (контракт, збори ...). Якщо у вашій системі буде інтеграція сторонніх розробників, будь-коли використовуйте DTO.
Лукас Гонсалвес

Відповіді:


45

Щоразу, коли розробник запитує "який сенс робити це?", Що вони насправді мають на увазі: "Я не бачу жодного випадку використання, коли це робить користь". З цією метою дозвольте показати кілька прикладів.


Усі приклади будуть засновані на цій простій моделі даних:

Суб'єкт Personгосподарювання має п'ять властивостей:Id, FirstName, LastName, Age, CityId

І ви можете припустити, що програма використовує ці дані різними способами (звіти, форми, спливаючі вікна, ...).

Уся програма вже існує. Все, що я згадую, - це зміна існуючої бази даних. Це важливо пам’ятати.


Приклад 1 - Зміна основної структури даних - Без DTO

Вимоги змінилися. Вік людини потрібно динамічно виводити з урядової бази даних (припустимо, виходячи з їх імені та прізвища).

Оскільки вам більше не потрібно зберігати Ageзначення локально, тому його потрібно видалити з Personсутності. Тут важливо усвідомити, що сутність представляє дані бази даних , і нічого більше. Якщо його немає в базі даних, це не в об'єкті.
Коли ви отримаєте вік із веб-служби уряду, він буде зберігатися в іншому об'єкті (або int).

Але ваш інтерфейс все ще відображає вік. Усі представлення даних створені для використання Person.Ageресурсу, якого зараз більше немає. Проблема представляється: усі погляди, які стосуються Ageлюдини, потрібно виправити .


Приклад 2 - Зміна основної структури даних - За допомогою DTO

У старій системі, є також PersonDTOоб'єкт з тими ж п'ятьма властивостями: Id, FirstName, LastName, Age, CityId. Після отримання a Person, сервісний рівень перетворює його в a, PersonDTOа потім повертає.

Але зараз вимоги змінилися. Вік людини потрібно динамічно виводити з урядової бази даних (припустимо, виходячи з їх імені та прізвища).

Оскільки вам більше не потрібно зберігати Ageзначення локально, тому його потрібно видалити з Personсутності. Тут важливо усвідомити, що сутність представляє дані бази даних , і нічого більше. Якщо його немає в базі даних, це не в об'єкті.

Однак, оскільки у вас є посередник PersonDTO, важливо бачити , що цей клас може тримати в Ageвласності. Службовий рівень отримає Person, перетворить його в а PersonDTO, потім також вибере вік людини з веб-служби уряду, збереже це значення в PersonDTO.Ageі передасть цей об’єкт.

Важлива частина тут полягає в тому, що кожен, хто використовує сервісний рівень, не бачить різниці між старою та новою системою . Сюди входить ваш інтерфейс. У старій системі вона отримала повний PersonDTOоб’єкт. А в новій системі вона все одно отримує повний PersonDTOоб’єкт. Погляди не потрібно оновлювати .

Це те, що ми маємо на увазі, коли ми використовуємо фразове розділення проблем : Є дві різні проблеми (зберігання даних у базі даних, подання даних у передній частині), і для них потрібен різний тип даних. Навіть якщо ці два типи даних зараз містять однакові дані, це може змінитися в майбутньому.
У наведеному прикладі Ageє різниця між двома типами даних: Person(об'єкт бази даних) не потребує Age, але PersonDTO(тип даних інтерфейсу) він потребує.
Виділяючи проблеми (= створення окремих типів даних) від початку, база коду набагато стійкіша до змін, внесених до моделі даних.

Ви можете стверджувати, що наявність об’єкта DTO, коли до бази даних додається новий стовпець, означає, що вам доведеться виконати подвійну роботу, додавши властивість як в об'єкті, так і в DTO. Це технічно правильно. Для підтримки двох класів замість одного потрібно трохи додаткових зусиль.

Однак вам потрібно порівняти необхідні зусилля. Коли додано один або кілька нових стовпців, копіювання / вставлення декількох властивостей не займе так довго. Коли модель даних структурно змінюється, потрібно змінити інтерфейс, можливо, таким чином, що викликає помилки лише під час виконання (а не під час компіляції), зажадає значно більше зусиль, і це вимагає від розробника (ів) піти на полювання на помилок.


Я можу навести більше прикладів, але принцип завжди буде однаковим.

Узагальнити

  • Окремі обов'язки (проблеми) повинні працювати окремо один від одного. Вони не повинні ділитися будь-якими ресурсами, такими як класи даних (наприклад Person)
  • Тільки тому, що сутність та його DTO мають однакові властивості, не означає, що вам потрібно об'єднати їх в одне ціле. Не обрізайте кути.
    • Скажімо, більш чіткий приклад, скажімо, наша база даних містить країни, пісні та людей. Всі ці структури мають Name. Але те, що всі вони мають Nameвластивість, не означає, що ми повинні змусити їх успадковувати спільний EntityWithNameбазовий клас. Різні Nameвластивості не мають значущого відношення.
    • Якщо одна з властивостей коли-небудь зміниться (наприклад, пісня Nameбуде перейменована на Titleлюдину або людина отримає FirstNameі LastName), вам доведеться витратити більше зусиль, щоб скасувати спадщину, яке вам навіть не потрібно було в першу чергу .
    • Хоча це не настільки очевидно, але ваш аргумент того, що вам не потрібен DTO, коли у вас є сутність, такий же. Ви дивитесь на зараз , але не готуєтесь до будь-яких майбутніх змін. ЯКЩО сутність та DTO абсолютно однакові, А якщо Ви можете гарантувати, що жодної зміни в моделі даних ніколи не буде; то ви правильні, що можете пропустити DTO. Але річ у тому, що ви ніколи не можете гарантувати, що модель даних ніколи не зміниться.
  • Належна практика не завжди окупається одразу. Це може почати окупатися в майбутньому, коли вам потрібно переглянути стару програму.
  • Основним вбивцею існуючих баз коду є те, що якість коду падає, постійно ускладнюючи підтримку бази коду, поки вона не перетвориться на марний безлад коду спагетті, який неможливо досягти.
  • Хороша практика, така як реалізація відокремлення проблем від місця доїзду, спрямована на те, щоб уникнути слизького схилу поганого обслуговування, щоб зберегти базу даних коду якомога довше.

Як правило, слід розглянути питання про розмежування проблем, подумайте про це так:

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

У добре відокремленій кодовій базі змін до конкретної проблеми потребує лише одна особа:

  • Зміна користувальницького інтерфейсу передбачає лише розробник інтерфейсу користувача.
  • Зміна методу зберігання даних передбачає лише розробник бази даних.
  • Зміна логіки бізнесу передбачає лише розробку бізнесу.

Якби всі ці розробники використовували одне Personціле об'єднання, і в суті було внесено незначну зміну, всі повинні були б бути залучені до процесу.

Але, використовуючи окремі класи даних для кожного шару, ця проблема не є такою поширеною:

  • Поки розробник бази даних може повернути дійсний PersonDTOоб'єкт, бізнес та розробник інтерфейсу не переймаються тим, чи змінив він спосіб зберігання / отримання даних.
  • Поки бізнес-розробник зберігає дані в базі даних і надає необхідні дані в інтерфейс, базу даних та розробники інтерфейсу користувача не хвилює, чи вирішив він переробити свої бізнес-правила.
  • Поки інтерфейс користувача може бути розроблений на основі "PersonViewModel", тоді розробник інтерфейсу може будувати інтерфейс користувача, як вони хочуть. База даних та бізнес-розробників не хвилює, як це робиться, оскільки це не впливає на них.

Ключова фраза тут, оскільки вона не впливає на них . Реалізація належного розгляду питань має на меті мінімізувати вплив (і, отже, задіяння) інших сторін.

Звичайно, деяких великих змін неможливо уникнути, якщо включити більше однієї особи, наприклад, коли до бази даних буде додано абсолютно нову сутність. Але не варто недооцінювати кількість незначних змін, які ви повинні внести протягом життя програми. Основні зміни - це числова меншість.


Вичерпна відповідь, спасибі У мене є запитання; Вдячний, якщо ви відповідаєте: 1 - Виправте мене, якщо я помиляюся. Бізнес-об'єкт або перегляд-об’єкт призначений для передачі даних між шаром презентації та бізнес-шаром, а об’єкт сутності - для передачі даних між бізнес-шаром та рівнем доступу до даних . і DTO можна використовувати як німий БО. 2 - Припустимо, що два погляди потребують різної інформації про компанію, тоді нам потрібні дві різні фірмовіДТО?
Араш

1
@Arash (1) "DTO" - це дійсно чітке визначення для будь-якого класу даних, який використовується для обміну між двома шарами. Діловий об'єкт і об’єкт перегляду є обома DTO. (2) Це дуже багато залежить від багатьох речей. Створення нового dto для кожної потрібної вам колекції - це громіздке завдання. Немає нічого поганого в тому, щоб просто повернути повний DTO компанії (де це розумно) і потім дозволити погляду вибирати сфери, які вас цікавлять. Це питання пошуку балансу між впровадженням адекватного розділення проблем та уникненням перенапруження та безглуздого повторення.
Flater

Тепер це для мене сенс. Дуже дякую. Флатер.
Араш

Ще одне питання. Ви сказали, що "бізнес-об'єкт і об'єкт перегляду". Я думав, що обидва рівні. Під час пошуку я зрозумів, що Business Object має загальне значення для порівняння з View Object . Але Бізнес-об’єкт має бути отриманий із випадку використання, а об'єкт об'єкта повинен бути похідний від Моделі даних, тому вони різні, я прав? Ви можете трохи пояснити, будь ласка?
Араш

@Arash: Різниця між тим, що ви називаєте "бізнес-об'єктом" та "об'єктом перегляду", - це контекст . Нам людям ця відмінність має значення, щоб правильно зрозуміти речі. Але компілятор (і за допомогою розширення сама мова) не бачить технічної різниці між ними. Коли я кажу, що вони однакові, я маю на увазі це з технічної точки зору. Обидва - просто клас із властивостями, призначеними для зберігання даних та передачі. У цьому плані різниці між ними немає.
Flater
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.