Рекомендации по отображению DTO в объекте домена? - PullRequest
66 голосов
/ 24 марта 2009

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

Ситуация:

У нас много доменных объектов. Мы используем модель CSLA, поэтому наши доменные объекты могут быть довольно сложными и содержать собственный доступ к данным. Вы не хотите передавать их по проводам. Мы собираемся написать несколько новых сервисов, которые будут возвращать данные в нескольких форматах (.Net, JSON и т. Д.). По этой (и другим) причинам мы также создаем компактный объект передачи данных для передачи по проводам.

Мой вопрос: как должны быть связаны объект DTO и домен?

Моя первая реакция - использовать решение типа паттерна Fowler, DTO . Я видел это много раз, и мне кажется, что это правильно. Доменный объект не содержит ссылки на DTO. Внешний объект («преобразователь» или «ассемблер») вызывается для создания DTO из объекта домена. Обычно на стороне объекта домена есть ORM. Недостатком этого является то, что «картограф» имеет тенденцию быть чрезвычайно сложным для любой реальной ситуации и может быть очень хрупким.

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

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

Спасибо за понимание.

Ответы [ 10 ]

35 голосов
/ 24 марта 2009

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

Лично я стараюсь не отображать сущности моего домена и возлагаю ответственность на то, что я называю «Уровень менеджера / обслуживания». Это слой, который находится между приложением и репозиторием (-ами) и обеспечивает бизнес-логику, такую ​​как координация рабочего процесса (если вы изменяете A, вам, возможно, придется изменить B, чтобы служба A работала со службой B).

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

22 голосов
/ 24 марта 2009

Вы можете использовать автомат, такой как , написанный Джимми Богардом , который не имеет связи между объектами и опирается на соглашения о присвоении имен.

7 голосов
/ 02 декабря 2011

Мы используем шаблоны T4 для создания классов отображения.

Pro's - читаемый человеком код, доступный во время компиляции, быстрее, чем средство отображения времени выполнения. 100% контроль над кодом (можно использовать частичные методы / шаблонные шаблоны для расширения функциональности на разовой основе)

Con - исключая определенные свойства, коллекции доменных объектов и т. Д., Изучая синтаксис T4.

2 голосов
/ 25 июня 2014

Как вы видите реализацию конструктора внутри класса DTO, который принимает в качестве параметра объект домена?

Скажи ... как-то так

class DTO {

     // attributes 

     public DTO (DomainObject domainObject) {
          this.prop = domainObject.getProp();
     }

     // methods
}
1 голос
/ 22 апреля 2011

Другое возможное решение: http://glue.codeplex.com.

Особенности:

  • Двунаправленное отображение
  • Автоматическое отображение
  • Отображение между различными типами
  • Вложенное отображение и выравнивание
  • Списки и массивы
  • Проверка отношений
  • Тестирование сопоставления
  • Свойства, поля и методы
0 голосов
/ 01 ноября 2018

Мы можем использовать для этого паттерны Factory, Memento и Builder. Фабрика скрывает подробности о том, как создать экземпляр модели домена из DTO. Memento позаботится о сериализации / десериализации модели домена в / из DTO и может даже получить доступ к частным членам. Builder позволяет отображать из DTO в домен с свободным интерфейсом.

0 голосов
/ 08 августа 2018

Другим вариантом будет использование ModelProjector . Он поддерживает все возможные сценарии и очень прост в использовании с минимальными затратами.

0 голосов
/ 12 октября 2014

Почему бы нам не сделать это?

class UserDTO {
}

class AdminDTO {
}

class DomainObject {

 // attributes
 public DomainObject(DTO dto) {
      this.dto = dto;
 }     

 // methods
 public function isActive() {
      return (this.dto.getStatus() == 'ACTIVE')
 }

 public function isModeratorAdmin() {
      return (this.dto.getAdminRole() == 'moderator')
 }

}


userdto = new UserDTO();
userdto.setStatus('ACTIVE');

obj = new DomainObject(userdto)
if(obj.isActive()) {
   //print active
}

admindto = new AdminDTO();
admindto.setAdminRole('moderator');

obj = new DomainObject(admindto)
if(obj.isModeratorAdmin()) {
   //print some thing
}

@ FrederikPrijck (или) кто-то: Пожалуйста, предложите. В приведенном выше примере DomainObject зависит от DTO. Таким образом я могу избежать кода для отображения объекта dto <-> domain.

или класс DomainObject может расширять класс DTO?

0 голосов
/ 08 сентября 2012

Я могу предложить созданный мной инструмент с открытым исходным кодом, размещенный на CodePlex: EntitiesToDTOs .

Отображение из DTO в Entity и наоборот реализуется методами расширения, которые составляют сторону ассемблера каждого конца.

Вы заканчиваете с кодом как:

Foo entity = new Foo();
FooDTO dto = entity.ToDTO();
entity = dto.ToEntity();

List<Foo> entityList = new List<Foo>();
List<FooDTO> dtoList = entityList.ToDTOs();
entityList = dtoList.ToEntities();
0 голосов
/ 01 июля 2009

Вы также можете попробовать Otis, объект-объект-сопоставитель. Концепции аналогичны отображению NHibernate (атрибут или XML).

http://code.google.com/p/otis-lib/wiki/GettingStarted

...