Звичайний старий об’єкт CLR проти об'єкта передачі даних


405

POCO = Простий старий CLR (або краще: Class)

DTO = Об'єкт передачі даних

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

Чи POCO та DTO те саме?


5
"POCO = Простий старий CLR (або краще: клас)". Таким чином, об'єкти подібного характеру у VB.NET також будуть POCO, а не POVO.
Дж. Полфер

Відповіді:


568

POCO дотримується правил OOP. Він повинен (але не повинен) мати стан та поведінку. POCO походить від POJO, придуманого Мартіном Фаулером [ анекдот тут ]. Він використовував термін POJO як спосіб зробити більш сексуальним відхилення рамкових важких реалізацій EJB. POCO слід використовувати в тому ж контексті в .Net. Не дозволяйте рамкам диктувати дизайн вашого об'єкта.

Єдина мета DTO - передати стан і не повинна мати поведінки. Дивіться пояснення Мартіна Фаулера про перехід до допиту для прикладу використання цієї моделі.

Ось відмінність: POCO описує підхід до програмування (гарне старомодне об'єктно-орієнтоване програмування), де DTO - це шаблон, який використовується для "передачі даних" за допомогою об'єктів.

Хоча ви можете ставитися до POCO, як DTO, ви ризикуєте створити анемічну модель домену, якщо це зробите. Крім того, існує невідповідність структури, оскільки DTO повинні бути розроблені для передачі даних, а не для відображення справжньої структури бізнес-домену. Результатом цього є те, що DTO, як правило, більш плоскі, ніж ваш фактичний домен.

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


Я знаю, що тут багато посилався на Мартіна Фаулера, але він придумав термін POJO і написав книгу PoEAA, яка є остаточним посиланням на DTO.
Майкл Медоуз

Я не впевнений, якщо DTO не повинен мати поведінку. Судячи з діаграми Мартіна Фаулера, DTO може мати поведінку.
Beatles1692,

39
@ Beatles1692, зображені методи - це серіалізаційний код. Це, мабуть, занадто широке твердження, щоб сказати "немає поведінки". Як щодо "жодної логіки бізнесу". Код серіалізації та об'єкти низького рівня, такі як хеш-код, рівність та стринг, повинні бути прийнятними.
Майкл Медоуз

1
@PositiveGuy Модель служить іншим цілям, ніж DTO. DTO повинен застосовуватися для передачі даних з одного домену в інший (незалежно від того, чи вони перебувають в одному і тому ж часі виконання) не має значення. Модель "представляє" аспект домену, наприклад екран, послугу або джерело даних. Моделі включають стан і поведінку, які є репрезентативними для того, що вони моделюють.
Майкл Медоуз

2
Зауважте, що анемічні моделі домену не обов'язково погані, особливо якщо ваш додаток переважно CRUD. Улюблена простота над Мартіном Фаулером.
Маріуш Джамро

50

Для мене, мабуть, зайве робити внесок, оскільки я вже заявив про свою позицію у своїй статті в блозі, але останній абзац цієї статті щось резюмує:

Отже, на закінчення, навчіться любити POCO і переконайтеся, що ви не поширюєте жодної дезінформації про те, що це те саме, що і DTO. DTO - це прості контейнери даних, які використовуються для переміщення даних між шарами програми. POCO - це повноцінні бізнес-об'єкти з однією вимогою, щоб вони були наполегливістю (без методів отримання та збереження). Нарешті, якщо ви ще не перевірили книгу Джиммі Нілссона, підберіть її з місцевих університетів. У ньому є приклади на C #, і це чудове читання.

До речі, Патріку, я читав POCO як статтю про спосіб життя, і я повністю згоден, що це фантастична стаття. Це насправді розділ із книги Джиммі Нілссона, який я рекомендував. Я поняття не мав, що це доступно в Інтернеті. Його книга справді є найкращим джерелом інформації, яку я знайшов про POCO / DTO / Repository / та інших практиках розробки DDD.


4
Посилання на статтю в блозі: rlacovara.blogspot.com/2009/03/…
Jamie Ide

28

POCO - це просто об'єкт, який не приймає залежності від зовнішніх рамок. Це ГРАНІ.

Будь POCO має поведінку чи ні, це не має значення.

DTO може бути POCO, як і доменний об'єкт (який, як правило, багатий на поведінку).

Зазвичай DTO мають більшу ймовірність приймати залежності від зовнішніх рамок (наприклад, атрибутів) для цілей серіалізації, оскільки зазвичай вони виходять на межі системи.

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



6

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

Одним із прикладів, коли POCO є чимось іншим, ніж DTO, - коли ви говорите про POCO всередині вашої доменної моделі / бізнес-логічної моделі, що є хорошим представленням OO вашої проблемної області. Ви можете використовувати POCO у всій програмі, але це може спричинити небажаний побічний ефект від таких витоків знань. Наприклад, DTO використовуються з рівня обслуговування, з яким спілкується користувальницький інтерфейс, DTO - це плоське представлення даних і використовується лише для надання користувальницьким інтерфейсом даних та передачі змін назад на рівень обслуговування. Сервісний рівень відповідає за відображення обох способів DTO до об'єктів домену POCO.

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


2
@David Landman, включене вами посилання стосується локальної схеми DTO, тобто коли DTO використовуються для перенесення стану в межах вашої системи. У цих випадках вам слід бути дуже обережними, оскільки всередині вашої системи у вас вже має бути чітко визначений домен, яким можна ділитися. Передаючи стан через межі системи, DTO важко уникнути і досить доцільно у всіх випадках.
Майкл Медоуз

@Michal Meadows, так, посилання дійсно говорить про інший підмножині проблем. Але я думаю, що у випадку передачі стану через системний кордон вам слід скористатися службою перекладу, щоб зіставити POCO з одного контексту на POCO з іншого контексту. Або ви говорите про бундері на системному рівні?
Деві Лендман

1

Основний випадок використання DTO - це повернення даних із веб-служби. У цьому випадку POCO і DTO рівнозначні. Будь-яка поведінка в POCO буде видалена при поверненні з веб-сервісу, тож насправді не має значення, чи має вона поведінку.


5
Я думаю, що ваша відповідь неправильно представляє те, що мало трапляється. У випадку веб-служби генерується проксі-сервер на основі відкритого стану об'єкта. Це означає, що DTO створюється окремо від POCO, який просто має такий же державний стан, що і POCO. Це може здатися тонким, але це важливо. Причина в тому, що навіть якщо проксі-сервер ідентичний оригіналу, він фактично не побудований з одного класу.
Майкл Медоуз

Ні, ні. Один використовує DTO для повернення / отримання даних між рівнями, в даному випадку - веб-службою. Вибирають DTO, оскільки він має лише дані, а поведінку не має. Це правда, що клас проксі також буде, ймовірно, DTO, і якщо ви використовували клас POCO замість цього, був би створений проксі. Але в цьому випадку клас POCO фактично є DTO, оскільки його поведінка не перекладається. Я все ще кажу, використовуйте DTO, тому що ви не пропустите поведінку, яка ніколи не існувала.
Джон Сондерс

5
** Семантично: Веб-сервіси розкривають мішки стану об'єкта за допомогою WSDL. Від них генеруються проксі. Вони не можуть включати поведінку. Якщо ви користуєтесь веб-послугою, єдиний зв'язок між вашим об'єктом та об'єктом, що піддається впливу, полягає в тому, що він має однаковий публічний стан, створений на основі перевірки.
Майкл Медоуз

7
@John, я думаю, ти переживаєш. Я кажу, що ти маєш рацію, але твоє формулювання вводить в оману. "У цьому випадку POCO і DTO рівноцінні." Семантично це неправда. POCO можуть використовуватися як DTO та навпаки, але це не означає, що вони еквівалентні ... не більше ніж автомобіль та пікап рівноцінні, хоча вони можуть бути використані для того, щоб загнати вас до продуктового магазину. Вони мають функцію перекриття, але вам важко буде знайти когось, який скаже вам про розуміння, еквівалентному F350, навіть в контексті продуктової поїздки.
Майкл Медоуз

3
Ця відповідь настільки помилкова, веб-сервіс недостатньо загальний для одного. Найголовніше - це добре встановлений факт, що DTO НЕ є POCO. DTO є контейнером даних, в той час як POCO є об'єктами як властивості і не знають стійкості (немає методів отримання або збереження).
Том Стікель

1

ось загальне правило: DTO == зло та індикатор переробленого програмного забезпечення. POCO == добре. "Корпоративна" модель знищила мізки багатьох людей у ​​світі Java EE. будь ласка, не повторіть помилку в .NET land.


7
Не могли б ви детальніше розглянути? DTO необхідні під час повернення даних з веб-сервісу, щоб уникнути впровадження та специфіки платформи в договорі.
Джон Сондерс

1
Так, John DTO розроблений для того, що ви говорите, і працює добре. Але, на жаль, вони часто звикають, коли не потрібні в однорівневих веб-додатках і мають мало значення.
Крейг

9
Я думаю, @drscroogemcduck, що, можливо, ти не любиш ДТО, тому що вони використовуються як перший засіб, а не як останній, але вони не є притаманними злом ... не більше, ніж сумнозвісний однотонний або заводський зразки. Що таке зло - це архітектори, котрі підштовхують рамки до горла розробників, які змушують їх робити ЗНО на все. Для того, що вони роблять, ідеально підходить передача даних, DTO (якщо вони зроблені обережно).
Майкл Медоуз

0

Класи DTO використовуються для серіалізації / десеріалізації даних з різних джерел. Коли ви хочете десаріалізувати об’єкт з джерела, не має значення, яке це зовнішнє джерело: сервіс, файл, база даних тощо, можливо, ви хочете використовувати лише частину цього, але ви хочете, щоб простий спосіб дезаріалізувати ці дані до об’єкт. після цього ви копіюєте ці дані в XModel, який ви хочете використовувати. Серіалізатор - це прекрасна технологія завантаження об'єктів DTO. Чому? вам потрібно лише одна функція для завантаження (десеріалізації) об'єкта.


0

TL; DR:

DTO описує схему передачі стану. POCO нічого не описує. Це ще один спосіб сказати "об'єкт" в OOP. Він походить від POJO (Java), придуманого Мартіном Фаулером, який буквально просто описує його як більш фантазійне ім'я для "об'єкта", оскільки "об'єкт" не дуже сексуальний.

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

POCO - це звичайний об'єкт, але те, що мається на увазі під «звичайним», - це те, що він не є особливим. Це просто означає, що це об'єкт CLR, не маючи на увазі малюнок. Родовий термін. Він не створений для роботи з деякими іншими рамками. Так що якщо ваш POCO є[JsonProperty] або прикраси EF, це його властивості, то я б стверджував, що це не POCO.

Ось декілька прикладів різних видів шаблонів об'єктів для порівняння:

  • Модель перегляду : використовується для моделювання даних для подання. Зазвичай має примітки до даних для сприяння прив'язці та валідації. У MVVM він також виконує функції контролера. Це більше, ніж DTO
  • Об'єкт значення : використовується для представлення значень
  • Корегований корінь : використовується для управління державою та інваріантами
  • Обробники : використовуються для відповіді на подію / повідомлення
  • Атрибути : використовуються як прикраси для вирішення проблем, що перетинаються між собою
  • Сервіс : використовується для виконання складних завдань
  • Контролер : використовується для управління потоком запитів та відповідей
  • Фабрика : використовується для налаштування та / або складання складних об'єктів для використання, коли конструктор недостатньо хороший. Також використовується для прийняття рішень щодо того, які об’єкти потрібно створити під час виконання.
  • Сховище / DAO : використовується для доступу до даних

Це все просто об’єкти, але зауважте, що більшість із них, як правило, прив’язані до візерунка. Таким чином, ви можете назвати їх "об'єктами", або ви можете бути більш конкретними щодо його намірів і називати його таким, яким він є. Ось чому ми маємо шаблони дизайну; описати складні поняття в кількох роботах. DTO - зразок. Сукупний корінь - це шаблон, модель перегляду - це візерунок (наприклад, MVC & MVVM). POCO - це не зразок.

POCO не описує шаблону. Це просто інший спосіб посилання на класи / об'єкти в OOP. Розглядайте це як абстрактне поняття; вони можуть посилатися на що завгодно. IMO, є односторонні відносини, хоча оскільки об'єкт досягає точки, коли він може чисто виконувати лише одну мету, це вже не POCO. Наприклад, як тільки ви позначите свій клас прикрасами, щоб він працював з деякими рамками, це вже не POCO. Тому:

  • DTO - POCO
  • POCO не є DTO
  • Модель перегляду - POCO
  • POCO - це не модель перегляду

Сенс у розрізненні між ними полягає в тому, щоб чіткі та послідовні зразки дотримувалися зусиль, щоб не перетинати проблеми і не призводити до тісного зв'язку. Наприклад, якщо у вас є бізнес-об'єкт, який має методи мутації стану, але також прикрашений до пекла декораціями EF для збереження на SQL Server AND JsonProperty, щоб він міг бути відправлений назад через кінцеву точку API. Цей об'єкт буде нетерпимим до змін і, ймовірно, буде залитий варіантами властивостей (наприклад, UserId, UserPk, UserKey, UserGuid, де деякі з них позначені так, щоб їх не було збережено в БД, а інші позначені, щоб не бути серіалізованими до JSON в кінцевій точці API).

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


-13

Навіть не називайте їх DTO. Їх називають Моделями .... Період. Моделі ніколи не мають поведінки. Я не знаю, хто придумав цей тупий термін DTO, але це повинно бути .NET річ все, що я можу зрозуміти. Подумайте про перегляд моделей MVC, одна і та сама дамба **, моделі використовуються для передачі стану між шарами сервера або протягом провідного періоду, вони всі моделі. Властивості з даними. Це моделі, по яких ви пропускаєте над дротом. Моделі, моделі моделей. Це воно.

Я хочу, щоб дурний термін DTO відійшов від нашої лексики.


1
я не знаю, звідки у вас ідея, що моделі ніколи не мають поведінки. Як ви моделюєте щось, крім CRUD, не моделюючи поведінку? Навіть ViewModels мають поведінку в багатьох випадках, особливо в додатках MVVM. DTO - корисний термін, оскільки він точно описує мету; для передачі даних.
Джеральд

9
заперечується як фактично некоректне, так і за понтифікаційне ставлення.
joedotnot

Дурниці. Моделі повинні бути дурними контейнерами. DTO немає, це термін, складений MS. Ви переносите моделі між доменами, службами та програмами. Період. DTO - це марний термін, який не потрібен і лише більше плутає речі. Моделі, Моделі та інші Моделі. Моделі можуть мати або не мати поведінки. Переглядати моделі не слід. Така поведінка повинна бути в BL, а не в класі Model.
PositiveGuy

Я згоден, що DTO є функціонально Моделями. ViewModels має поведінку і це те, що ви пов'язуєте в MVVM. ЯКЩО я написав додаток, де мої моделі були більш розумні (в основному VM, але я не хотів їх називати), і вони "прийняли" об'єкт DTO. Це дозволило мені мати більше варіантів з рамкою. Отже, від CRUD (або навіть EF) я передавав би об’єкт через WCF-послуги та отримував об’єкт DTO та інкапсулював його (додаючи OnProp Change тощо). Мої ViewModels виконали подальше капсулювання і, можливо, прийняли два (або список) "Моделей". Жорстким визначенням буде VM.
SQLMason

"Ви переносите моделі між доменами, службами та програмами" Чому ви вважаєте, що термін модель є більш підходящою та придатною, ніж термін DTO для такої поведінки, яку ви описуєте?
caa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.