Каков наилучший способ использования DTO в SOA-приложении? - PullRequest
7 голосов
/ 05 мая 2011

Мы реализуем веб-приложение SOA с использованием EF, WCF и jQuery.

Вот краткая информация о нашей архитектуре:

-------------   ---
|    UI     |  |   |
-------------  |   |
| Services  |  | D |
-------------  | T |
| Businsess |  | O |
-------------  |   |
|    Dal    |  |   |
-------------   ---

Мы знаем, что для этого нам нужны классы DTOпередавать данные между уровнями, особенно между Сервисами и пользовательским интерфейсом, но у нас есть некоторые концептуальные проблемы относительно способа использования DTO (для отправки в пользовательский интерфейс или получения из пользовательского интерфейса).

Для проекта, управляемого данными, мы можем использоватьPOCO для автоматического создания объектов DTO.Но в больших приложениях это не так просто.

Мы знаем два решения для решения нашей проблемы:

Первое решение (с использованием POCO помимо новых DTO, созданных вручную)

Например, предположим, что мыиметь сущность со многими полями.И есть выпадающий список, который показывает записи сущностей.Нам нужен просто ключ сущности в качестве поля значения поля со списком и другое поле (например, Название) в качестве поля со списком.Поэтому мы создаем метод с именем «GetAllItemsTitle» для извлечения всех сущностей.Теперь нам нужно просто вернуть желаемую структуру (ключ и значение в этом примере).Поэтому мы должны создать новый класс для хранения в нем этой структуры (ключ и значение).

Это будет новый класс DTO:

[DataContract]
public class SampleManuallyDto
{
    [DataMember]
    public long Id { get; set; }

    [DataMember]
    public string Title { get; set; }
}

И сигнатура методакак это:

public List<SampleManuallyDto> GetAllItemsTitle()

Второе решение (с использованием обнуляемых или пустых DTO)

Мы можем обойти POCO и создать DTO вручную.Затем мы можем определить все свойства DTO как обнуляемые или что-то в этом роде, которое может быть распознано как пустое (я назвал его пустым).Это позволяет нам использовать DTO для нескольких целей.Конечно, мы должны следовать шаблону адаптера.Например, создайте два метода для тех Emptyable DTO с именами «FromEntity» и «ToEntity», которые преобразуют наши DTO, созданные вручную, в EntityObjects (структуры сущностей).

Теперь мы можем обойти создание новых классов DTO впример «первого решения» (GetAllItemsTitle).

Подпись метода будет выглядеть следующим образом:

public List<SampleDTO> GetAllItemsTitle()

Но в теле метода мы просто заполняем «Id» и «Title»свойства SampleDTO.Как я уже сказал, все свойства SampleDTO могут быть пустыми, поэтому мы просто заполняем те, которые хотим, а остальные оставляем пустыми.

Заключение

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

Но второе решение - более динамичный способ, и единственный способ узнать, что будет возвращено из «GetAllItemsTitle», - это просмотреть тело метода или его документацию.Поэтому мы беспокоимся о «ошибках времени выполнения».Разработчики могут предположить, что свойство не должно быть пустым, пока оно пустое.

Более того, наглядный пример, с которым мы столкнулись при такой проблеме, - «передача» данных из пользовательского интерфейса в службы.Например, для Обновления и Вставки и других подобных действий.Даже в отношении «критериев поиска» у нас есть такой же выбор.

Извините за длинный вопрос.Пожалуйста, помогите нам с любезными советами.

Ответы [ 3 ]

2 голосов
/ 05 мая 2011

Забудьте все о слое данных.Создайте DTO: s, который работает для каждого конкретного вызова веб-службы.

Не важно, как создается DTO или как он используется.Единственное, что имеет значение, - это то, как они спроектированы так, чтобы минимизировать количество вызовов веб-сервиса для каждой операции.

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

1 голос
/ 08 мая 2011

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

http://www.soapatterns.org/entity_abstraction.php

1 голос
/ 05 мая 2011

тогда как нам управлять огромным количеством DTO большого проекта? Вы имеете в виду, что у нас должен быть DTO для каждой комбинации UserInfo, такой как UserWithAddress, UserWithAddressAndAge, UserWithAge, UserWithPhoneNumber, UserWithBlahBlahBlah? Это было бы беспорядком в больших доменах и было бы трудно управлять и поддерживать. Я действительно предпочитаю NTO. Вы должны иметь одно Dto для каждого объекта, сопоставленного с реальным миром. это деловая обязанность указать, как это должно использоваться. После того, как вы создадите Dto, используйте его в соответствии с вашим бизнесом. Вызывая сервис GetUserAddress, и не ожидайте UserAge или чего-то другого. для пользователей существует единое DTO, поскольку мы сопоставляем пользователя с нашим объектно-ориентированным пользователем в нашем проекте.

и еще одна вещь! если мы создадим Dto для каждой отдельной цели и получим комбинацию услуг передачи данных, как разработчик, недавно присоединившийся к команде поддержки, как я могу найти требуемое Dto для моего нового метода? я должен обыскать все Dtos и быть осторожным с моим правильным выбором (что произойдет, если я стану ленивым и небрежным разработчиком?), может быть, мне следует прочитать документацию типа «ДТО ПРОЕКТА!» ознакомиться с доступными DTO.

...