Обычный старый объект CLR против объекта передачи данных

POCO = Обычный старый объект CLR (или лучше: класс)

DTO = объект передачи данных

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

POCO и DTO - это одно и то же?


person Patrick Peters    schedule 07.04.2009    source источник
comment
POCO = Обычный старый объект CLR (или лучше: класс). Таким образом, объекты такого рода в VB.NET тоже будут POCO, а не POVO.   -  person J. Polfer    schedule 20.06.2013


Ответы (10)


POCO следует правилам ООП. Он должен (но не обязательно) иметь поведение состояний и. POCO происходит от POJO, придуманной Мартином Фаулером [здесь анекдот]. Он использовал термин POJO как способ сделать более привлекательным отказ от тяжелых реализаций EJB фреймворка. POCO следует использовать в том же контексте в .Net. Не позволяйте фреймворкам диктовать дизайн вашего объекта.

Единственная цель DTO - передать состояние и не должно иметь никакого поведения. См. объяснение DTO Мартина Фаулера для примера использования этого шаблона.

В этом разница: POCO описывает подход к программированию (старомодное объектно-ориентированное программирование), где DTO - это шаблон, который используется для «передачи данных» с помощью объектов.

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

В домене любой разумной сложности вам почти всегда лучше создавать отдельные доменные POCO и переводить их в DTO. DDD (дизайн, управляемый доменом) определяет антикоррупционный слой (другая ссылка здесь, но лучше всего это купить книгу), что является хорошей структурой, которая делает четкую сегрегацию.

person Michael Meadows    schedule 07.04.2009
comment
Я знаю, что здесь много ссылался на Мартина Фаулера, но он ввел термин POJO и написал книгу PoEAA, которая является исчерпывающим справочником по DTO. - person Michael Meadows; 07.04.2009
comment
Я не уверен, что у DTO не должно быть поведения. Судя по диаграмме Мартина Фаулера, у DTO могло быть поведение. - person Beatles1692; 27.05.2009
comment
@ Beatles1692, изображенные методы представляют собой код сериализации. Вероятно, это слишком широкое утверждение, чтобы сказать «нет поведения». Как насчет бизнес-логики. Код сериализации и объекты низкого уровня, такие как хэш-код, равенство и tostring, должны быть приемлемыми. - person Michael Meadows; 27.05.2009
comment
Я также нашел хороший шаблон сборки от Microsoft для разделения DTO и бизнес-объектов (POCO): msdn.microsoft.com/en-us/library/ms978717.aspx - person Patrick Peters; 08.03.2012
comment
даже не называйте их DTO. Их называют моделями. DTO - это глупые термины. - person PositiveGuy; 05.03.2015
comment
@MSSucks в моделях MVC часто содержат бизнес-логику, поэтому термин DTO с меньшей вероятностью будет интерпретироваться по-другому. - person KCD; 03.08.2016
comment
@PositiveGuy Модель служит другой цели, чем DTO. DTO должен использоваться для передачи данных из одного домена в другой (независимо от того, находятся они в одной среде выполнения или нет). Модель представляет собой аспект домена, например экран, службу или источник данных. Модели включают состояние и поведение, которые представляют то, что они моделируют. - person Michael Meadows; 17.03.2017
comment
Обратите внимание, что анемичные доменные модели не обязательно плохие, особенно если ваше приложение в основном является CRUD. Предпочитайте простоту Мартину Фаулеру. - person Mariusz Jamro; 23.08.2018

Вероятно, для меня излишне вносить свой вклад, поскольку я уже изложил свою позицию в своей статье в блоге, но последний абзац этой статьи подводит итог:

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

Кстати, Патрик. Я прочитал POCO как статью о стиле жизни и полностью согласен, это фантастическая статья. На самом деле это отрывок из книги Джимми Нильссона, который я рекомендовал. Я понятия не имел, что он доступен в Интернете. Его книга действительно является лучшим источником информации о POCO / DTO / Repository / и других методах разработки DDD, которые я нашел.

person Community    schedule 09.04.2009
comment
Ссылка на статью в блоге: rlacovara.blogspot .com / 2009/03 / - person Jamie Ide; 07.08.2010

POCO - это просто объект, который не зависит от внешней структуры. Это ОБЫЧНАЯ.

Неважно, имеет ли POCO поведение или нет.

DTO может быть POCO, как и объект домена (который обычно имеет богатое поведение).

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

В типичных архитектурах в стиле Onion (часто используемых в рамках широко распространенного подхода DDD) уровень домена размещается в центре, и поэтому его объекты на этом этапе не должны иметь зависимостей за пределами этого уровня.

person Neil    schedule 03.11.2009

Я написал статью по этой теме: DTO vs Value Object против POCO.

Суммируя:

  • DTO! = Объект значения
  • DTO ⊂ POCO
  • Объект значения ⊂ POCO
person Vladimir    schedule 13.04.2015

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

Один из примеров, когда POCO отличается от DTO, - это когда вы говорите о POCO внутри вашей модели предметной области / модели бизнес-логики, которая является хорошим объектно-ориентированным представлением вашей проблемной области. Вы можете использовать POCO во всем приложении, но это может иметь некоторые нежелательные побочные эффекты, такие как утечка информации. DTO, например, используются из уровня обслуживания, с которым взаимодействует пользовательский интерфейс, DTO представляют собой плоское представление данных и используются только для предоставления пользовательскому интерфейсу данных и передачи изменений обратно на уровень обслуживания. Уровень сервиса отвечает за отображение обоих путей DTO на объекты домена POCO.

Обновление Мартин Фаулер сказал, что этот подход - трудный путь. принимать, и его следует принимать только в случае значительного несоответствия между уровнем домена и пользовательским интерфейсом.

person Davy Landman    schedule 07.04.2009
comment
@David Landman, ссылка, которую вы включили, предназначена для шаблона Local DTO, когда DTO используются для передачи состояния в пределах вашей системы. В этих случаях вы должны быть очень осторожны, так как в вашей системе у вас уже должен быть четко определенный домен, который можно использовать совместно. При передаче состояния через границы системы DTO трудно избежать, и он подходит во всех случаях. - person Michael Meadows; 26.05.2009
comment
@Michal Meadows, да, ссылка действительно говорит о другом подмножестве проблем. Но я думаю, что в случае передачи состояния через границу системы вам следует использовать службу перевода, чтобы сопоставить POCO из одного контекста с POCO из другого контекста. Или вы говорите о границах на системном уровне? - person Davy Landman; 26.05.2009

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

person John Saunders    schedule 07.04.2009
comment
Думаю, ваш ответ немного искажает то, что происходит. В случае веб-службы прокси создается на основе открытого состояния объекта. Это означает, что DTO создается отдельно от POCO, который просто имеет то же публичное состояние, что и POCO. Это может показаться тонким, но это важно. Причина в том, что даже если прокси идентичен оригиналу, он фактически не построен из того же класса. - person Michael Meadows; 26.05.2009
comment
Нет, нет. Один использует DTO для возврата / получения данных между уровнями, в данном случае веб-службы. Один выбирает DTO, потому что он содержит только данные, а не поведение. Верно, что прокси-класс также, вероятно, будет DTO, и что если бы вы использовали вместо этого класс POCO, прокси-сервер был бы создан. Но в этом случае класс POCO фактически является DTO, поскольку его поведение не переводится. Я все еще советую использовать DTO, потому что вы не пропустите поведение, которого никогда не существовало. - person John Saunders; 26.05.2009
comment
@ Джон Сондерс, извини, если я не понял. Я спорю не с обоснованностью вашего аргумента, а с его семантикой. ** На ваш вопрос: DTO предназначен для защиты ваших POCO от того, что вы описываете. Чтобы это произошло, DTO должны быть сопоставлены с POCO. В простых и умеренно сложных решениях это может быть излишним, и поэтому вы правы. - person Michael Meadows; 26.05.2009
comment
** Семантически: веб-службы предоставляют пакеты состояний объектов с помощью WSDL. Из них создаются прокси. Они не могут включать поведение. При использовании веб-службы единственная связь между вашим объектом и открытым объектом домена состоит в том, что он имеет одно и то же общедоступное состояние, созданное на основе проверки. - person Michael Meadows; 26.05.2009
comment
@ Майкл: Понятия не имею, о чем ты говоришь. Если вы хотите, чтобы это изменилось, опубликуйте несколько цитат или что-то в этом роде. Я какое-то время использую DTO в веб-сервисах, и это никогда не было сделано для защиты какого-либо POCO. Это было сделано для передачи данных в объекте. - person John Saunders; 26.05.2009
comment
@ Джон, я думаю, ты слишком остро реагируешь. Я говорю, что вы правы, но ваша формулировка вводит в заблуждение. В этом случае POCO и DTO эквивалентны. Семантически это не так. POCO могут использоваться как DTO и наоборот, но это не значит, что они эквивалентны ... не более чем автомобиль и пикап эквивалентны, даже если они оба могут использоваться, чтобы отвезти вас в продуктовый магазин. У них есть перекрывающиеся функции, но вам будет трудно найти кого-то, кто сказал бы, что понимание эквивалентно F350, даже в контексте поездки за продуктами. - person Michael Meadows; 26.05.2009
comment
Этот ответ настолько неправильный, что веб-сервис для него недостаточно универсален. Что наиболее важно, это хорошо установленный факт, что DTO НЕ является POCO. DTO - это контейнер данных, а POCO - это объекты как свойства, которые игнорируют персистентность (нет методов get или save). - person Tom Stickel; 08.12.2011

TL;DR:

DTO описывает схему передачи состояния. POCO ничего не описывает. Это еще один способ сказать «объект» в ООП. Он происходит от POJO (Java), придуманного Мартином Фаулером, который буквально описывает его как более красивое название для «объекта», потому что «объект» не очень привлекателен.

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

POCO - это простой объект, но под «простым» подразумевается то, что он не особенный. Это просто означает, что это объект CLR без подразумеваемого шаблона. Общий термин. Он не предназначен для работы с другими фреймворками. Так что, если ваш POCO имеет [JsonProperty] или EF-украшения по всем своим свойствам, например, тогда я бы сказал, что это не POCO.

Вот несколько примеров различных видов паттернов объектов для сравнения:

  • Модель представления: используется для моделирования данных для представления. Обычно имеет аннотации к данным для облегчения привязки и проверки. В MVVM он также действует как контроллер. Это больше, чем DTO
  • Объект значения: используется для представления значений.
  • Aggregate Root: используется для управления состоянием и инвариантами.
  • Обработчики: используются для ответа на событие / сообщение.
  • Атрибуты: используются в качестве украшения для решения общих проблем.
  • Сервис: используется для выполнения сложных задач.
  • Контроллер: используется для управления потоком запросов и ответов.
  • Завод: используется для настройки и / или сборки сложных объектов для использования, когда конструктор недостаточно хорош. Также используется для принятия решений о том, какие объекты необходимо создать во время выполнения.
  • Репозиторий / DAO: используется для доступа к данным.

Все это просто объекты, но обратите внимание, что большинство из них обычно привязано к узору. Таким образом, вы можете называть их «объектами» или уточнить его намерение и назвать его тем, чем оно является. Вот почему у нас есть шаблоны проектирования; описать сложные концепции в нескольких работах. DTO - это шаблон. Совокупный корень - это шаблон, модель представления - это шаблон (например, MVC и MVVM). POCO - это не шаблон.

POCO не описывает шаблон. Это просто другой способ обращения к классам / объектам в ООП. Думайте об этом как об абстрактном понятии; они могут иметь в виду что угодно. ИМО, есть односторонние отношения, потому что, как только объект достигает точки, где он может чисто служить только одной цели, он больше не является POCO. Например, как только вы разметите свой класс украшениями, чтобы он работал с какой-либо структурой, он больше не является POCO. Следовательно:

  • DTO - это POCO
  • POCO - это не DTO
  • Модель представления - это POCO
  • POCO - это не модель просмотра

Смысл в том, чтобы проводить различие между ними, состоит в том, чтобы сохранять четкие и последовательные шаблоны, чтобы не перекрестно беспокоиться и не приводить к тесной связи. Например, если у вас есть бизнес-объект, у которого есть методы для изменения состояния, но он также чертовски украшен украшениями EF для сохранения на SQL Server И JsonProperty, чтобы его можно было отправить обратно через конечную точку API. Этот объект будет нетерпимым к изменению и, вероятно, будет завален вариантами свойств (например, UserId, UserPk, UserKey, UserGuid, где некоторые из них помечены, чтобы не сохраняться в БД, а другие помечены, чтобы не сериализоваться в JSON в конечной точке API).

Так что, если бы вы сказали мне, что что-то было DTO, я бы, вероятно, позаботился о том, чтобы оно никогда не использовалось ни для чего, кроме перемещения состояния. Если бы вы сказали мне, что что-то было моделью представления, я бы, вероятно, убедился, что это не сохраняется в базе данных. Если бы вы сказали мне, что что-то было моделью предметной области, я бы, вероятно, удостоверился, что она не зависит от чего-либо вне домена. Но если бы вы сказали мне, что что-то было POCO, вы бы вообще не рассказали мне много.

person Sinaesthetic    schedule 04.08.2019

вот общее правило: DTO == зло и индикатор чрезмерно спроектированного программного обеспечения. POCO == хорошо. Паттерны «предприятия» разрушили умы многих людей в мире Java EE. пожалуйста, не повторяйте ошибку в мире .NET.

person benmmurphy    schedule 07.04.2009
comment
Не могли бы вы уточнить, пожалуйста? DTO необходимы при возврате данных из веб-службы, чтобы избежать специфики реализации и платформы в контракте. - person John Saunders; 07.04.2009
comment
Да, DTO Джона созданы для того, что вы говорите, и хорошо работают. Но, к сожалению, они часто используются, когда не требуются в одноуровневых веб-приложениях, и не имеют большой ценности. - person Craig; 09.04.2009
comment
Я думаю, @drscroogemcduck, что, возможно, вам не нравятся DTO, потому что они используются как первое средство, а не последнее средство, но они по своей сути не злые ... не больше, чем печально известный синглтон или заводские выкройки. Зло - это архитекторы, которые запихивают разработчикам в глотку фреймворки, вынуждая их создавать DTO для всего. Для того, что они делают, передачи данных, DTO (если все сделано разумно) идеально подходят. - person Michael Meadows; 26.05.2009

Классы DTO используются для сериализации / десериализации данных из разных источников. Если вы хотите десериализовать объект из источника, независимо от того, какой это внешний источник: служба, файл, база данных и т. Д., Вы можете захотеть использовать только часть этого, но вам нужен простой способ десериализации этих данных в объект. после этого вы копируете эти данные в XModel, который хотите использовать. Сериализатор - это прекрасная технология для загрузки объектов DTO. Почему? вам нужна только одна функция для загрузки (десериализации) объекта.

person Herman Van Der Blom    schedule 27.11.2017

Даже не называйте их DTO. Они называются Модели .... Период. У моделей никогда не бывает поведения. Я не знаю, кто придумал этот тупой термин DTO, но, должно быть, это .NET - это все, что я могу понять. Подумайте о моделях представления в MVC, одной и той же даме **, модели используются для передачи состояния между уровнями на стороне сервера или за период проводки, все они являются моделями. Свойства с данными. Это модели, которые вы передаете по проволоке. Модели, модели Модели. Вот и все.

Я бы хотел, чтобы глупый термин DTO исчез из нашего словаря.

person PositiveGuy    schedule 05.03.2015
comment
Не знаю, откуда у вас идея, что у моделей никогда не бывает поведения. Как вы моделируете что-либо, кроме CRUD, без моделирования поведения? Даже ViewModels во многих случаях имеют поведение, особенно в приложениях MVVM. DTO - полезный термин, потому что он точно описывает цель; для передачи данных. - person Gerald; 09.04.2015
comment
проголосовали против за фактическую неверность и за понтификационное отношение. - person joedotnot; 13.04.2015
comment
Ерунда. Модели должны быть тупыми контейнерами. Нет никакого DTO, это выдуманный термин MS. Вы переносите модели между доменами, сервисами и приложениями. Период. DTO - это пустая трата времени, в котором нет необходимости, и он только еще больше сбивает с толку. Модели, модели и другие модели, вот и все. Модели могут иметь, а могут и не иметь поведения. Просмотр моделей не следует. Такое поведение должно быть в BL, а не в классе Model. - person PositiveGuy; 13.04.2015
comment
Я согласен с тем, что DTO функционально являются моделями. ViewModels имеет поведение и это то, к чему вы привязываетесь в MVVM. ОДНАКО я написал приложение, в котором мои модели были более интеллектуальными (в основном виртуальные машины, но я не хотел их называть), и они приняли объект DTO. Это позволило мне иметь больше возможностей для фреймворка. Итак, из CRUD (или даже EF) я бы передал объект через службы WCF, получил объект DTO и инкапсулировал его (добавив OnProp Change и т. Д.). Мои ViewModels выполнили дальнейшую инкапсуляцию и, возможно, приняли две (или список) моделей. Жесткое определение - виртуальные машины. - person SQLMason; 16.09.2015
comment
Вы переносите модели между доменами, службами и приложениями. Почему вы думаете, что термин модель более уместен и подходит, чем термин DTO для описываемого вами поведения? - person caa; 30.11.2015