我正在构建一个Web服务来检索复合对象列表。是否应该立即填充列表中每个对象的复杂子属性,或者是否可以让客户端根据需要请求该信息。
示例:
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);
模拟“懒惰”。
这似乎是一种节省数量的好方法,但代价是在需要时获取更多数据。这是值得的还是某种反模式?
返回一个人口稠密的物体似乎是不对的......
提前感谢任何指针/链接。
答案 0 :(得分:2)
在设计服务时,服务接口粒度始终是一项重要决策。由于Web服务调用通常是网络调用,或者至少是进程外调用,因此它们相对昂贵。如果您的服务接口太精细(或“聊天”),那么这可能会影响性能。当然,在确定正确的粒度级别时,您需要考虑您的应用程序和您的要求。 Software components: Coarse-grained versus fine-grained虽然有点干,但有一些很好的信息。
返回一个似乎不对 人口稀少的物体......
我同意。
在您的情况下,我们假设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);
一般来说,我更愿意避免对服务的消费者强加一系列调用。首先,您必须获得发票,然后您必须获取详细信息。这可能会导致性能问题以及应用程序之间更紧密的耦合。
答案 1 :(得分:1)
Web服务不应该“健谈”:您通过网络进行通信,任何请求/响应交换都需要时间。你不想要求客户在问他一次时问十次。
让客户端立即请求所有数据。
如果结果是性能问题,那么允许客户端指定他们想要的数据量,但是仍然应该在一次调用中返回所有数据。
答案 2 :(得分:1)
我认为这不是一个糟糕的设计,我认为这是一个你需要考虑的权衡。更重要的是:返回完整的对象图,或潜在的传输节省。
例如,如果您更有可能拥有数百或数千InvoiceLines
的客户,并且您只需要在非常具体的情况下使用这些客户,那么将它们拆分为您的方式似乎是合乎逻辑的提。
但是,如果你几乎总是需要InvoiceLines
,并且你通常只会说10个实例,那么总是将它们一起发送会更有意义。