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

Примере:

class InvoiceLine
{
  string ServiceDescription;
  decimal ChargeTotal;
}

class Invoice
{
  string InvoiceNumber;
  string CustomerNumber;
  List<InvoiceLine> InvoiceLines;
}

//Returns all invoices send to this customer
public List<Invoice> GetInvoices(string customerNumber);

Плохой дизайн иметь другой метод в WebService как:

public List<InvoiceLine> GetInvoiceLines(string invoiceNumber)

И потребовать от клиента сначала получить список всех сохраненных счетов-фактур (с пустым списком InvoiceLines в них и ожидать, что они вызовут:

invoices[0].InvoiceLines = webService.GetInvoiceLines(customerNumber);

Имитировать "ленивую загрузку".

Это кажется хорошим способом сэкономить на объеме, но за счет большего количества вызовов для получения данных при необходимости. Стоит ли это того или это какой-то антипаттерн?

Просто не кажется правильным возвращать наполовину заполненный объект ...

Заранее благодарим за любые указатели / ссылки.

2
Leon 7 Дек 2010 в 22:56
В конечном итоге реализовано как: public List GetInvoices (string customerNumber, bool LastInvoiceDetailsOnly);
 – 
Leon
8 Дек 2010 в 01:11

3 ответа

Лучший ответ

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

Просто не кажется правильным возвращать наполовину заполненный объект ...

Я согласен.

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

class InvoiceLine
{
  string ServiceDescription;
  decimal ChargeTotal;
}

class Invoice
{
  InvoiceSummary InvoiceSummary;
  List<InvoiceLine> InvoiceLines;
}

class InvoiceSummary
{
  string InvoiceNumber;
  string CustomerNumber;
}

public InvoiceSummary GetInvoiceSummary(string customerNumber);
public Invoice GetInvoice(string customerNumber);

В общем, я предпочитаю избегать навязывания последовательности обращений потребителю услуги. То есть сначала вы должны получить счет, а затем - детали. Это может привести к проблемам с производительностью, а также к более тесной связи между приложениями.

2
Randy Levy 7 Дек 2010 в 23:35
Спасибо! Я собираюсь объединить ваши рекомендации и рекомендации Джона Сондерса. Я планировал вернуть все сразу, но меня попросили рассмотреть возможность редизайна, поскольку было бы расточительно получать все эти данные каждый раз, а пользователи заботятся только о «последнем» счете. Мы не знаем, как пользователи будут использовать приложение - они могут нуждаться в них все время или только на 99%.
 – 
Leon
8 Дек 2010 в 01:05
1
Затем выполните операцию «GetLatestInvoice», которая получает только последний счет!
 – 
John Saunders
8 Дек 2010 в 01:38

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

Позвольте клиенту запросить все данные сразу.

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

1
John Saunders 7 Дек 2010 в 23:35
Спасибо! Это было замечено в обзоре дизайна как возможное узкое место, если конечные пользователи в основном смотрят на «последние» строки счета-фактуры. Мне нужно отображать метаданные о каждом счете (следовательно, возвращать их список), но показывать строки только по одной за раз - в зависимости от того, какой именно пользователь выберет.
 – 
Leon
8 Дек 2010 в 00:53
1
Напомним, что вы можете выбрать более одной из хранимых процедур, но показывать только одну. Клиент может кэшировать данные. Это обеспечивает быстрое реагирование на запросы и даже эффект «ленивой загрузки» без большого количества двустороннего сетевого трафика.
 – 
John Saunders
8 Дек 2010 в 01:37

Я не думаю, что это плохой дизайн, я думаю, что это компромисс, который нужно учитывать. Что важнее: возврат полного графа объекта или потенциальная экономия на передаче.

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

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

1
CodingGorilla 7 Дек 2010 в 23:37
1
Спасибо за ответ. Я согласен с тем, что это скорее компромисс, чем плохой дизайн, но мне не нравится, что он объединяет логику полусырого графа объекта. Эта веб-служба может использоваться другими приложениями, и это заставит их узнать подробности реализации.
 – 
Leon
8 Дек 2010 в 00:57