Лучшие практики сопоставления DTO с объектом домена?

StackOverflow https://stackoverflow.com/questions/678217

Вопрос

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

Ситуация:

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

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

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

Минусы — исключение определенных свойств, коллекций объектов предметной области и т. д., изучение синтаксиса T4.

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

Функции:

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

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

Сказать...Что-то вроде этого

class DTO {

     // attributes 

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

     // methods
}

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

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

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

Сопоставление 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();

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

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 <-->.

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

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

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

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

Единственной альтернативой было бы хранить карту где-нибудь еще, но куда она должна идти?Я пробовал внедрять картографические объекты/сервисы, но, после всего, что было сказано и сделано, это выглядело как чрезмерная инженерия (и, вероятно, так и было).Я добился определенного успеха в использовании Automapper и тому подобного для небольших проектов, но такие инструменты, как Automapper, имеют свои собственные подводные камни.Мне было довольно сложно найти проблемы, связанные с сопоставлениями, потому что сопоставления Automapper неявны и полностью отделены от остального кода (не как «разделение задач», а скорее как «где живет богом забытое отображение»), поэтому они иногда бывает трудно отследить.Нельзя сказать, что Automapper бесполезен, потому что он есть.Я просто считаю, что картографирование должно быть максимально очевидным и прозрачным, чтобы избежать проблем.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top