2010-12-07 38 views
2

Je construis un service web pour récupérer une liste d'objets composites. Une sous-propriété complexe de chaque objet de la liste doit-elle être remplie à la fois ou est-ce que le client peut demander cette information si nécessaire?WebService doit avoir des méthodes séparées pour remplir les propriétés dans la classe composite?

Exemple:

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); 

Est-ce une mauvaise conception d'avoir une autre méthode WebService comme:

public List<InvoiceLine> GetInvoiceLines(string invoiceNumber)

et nécessitent client d'abord obtenir une liste de toutes les factures enregistrées (avec liste vide de InvoiceLines en eux, et attendent d'eux d'appeler:

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

pour simuler une "charge paresseuse".

Cela semble être un bon moyen d'économiser du volume, mais au détriment de plus d'appels pour obtenir des données en cas de besoin. Est-ce que cela en vaut la peine ou est-ce un anti-modèle quelconque?

Il ne semble pas juste de retourner un objet demi-peuplé ...

Merci à l'avance pour tous les pointeurs/liens.

+0

finalement mis en œuvre en tant que: public Liste GetInvoices (string customerNumber, bool LastInvoiceDetailsOnly); – Leon

Répondre

2

La granularité de l'interface de service est toujours une décision importante lors de la conception de vos services. Étant donné que les appels de service Web sont généralement des appels réseau ou, à tout le moins, des appels hors processus, ils sont relativement coûteux. Si votre interface de service est trop fine (ou «bavarde»), cela peut affecter les performances. Bien sûr, vous devez tenir compte de votre application et de vos besoins lorsque vous déterminez le bon niveau de granularité. Software components: Coarse-grained versus fine-grained bien qu'un peu sec a de bonnes informations.

Il ne semble pas juste de retourner un objet demi-peuplé ...

Je suis d'accord.

Dans votre cas, supposons que InvoiceLines est coûteux à récupérer et n'est pas requis la plupart du temps. Si tel est le cas, vous pouvez encapsuler le résumé de la facture ou l'en-tête et renvoyer cette information. Toutefois, si le consommateur a besoin de la facture complète, offrez-lui la possibilité de le faire.

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); 

En général, je préfère éviter d'imposer une séquence d'appels au consommateur du service. C'est-à-dire que vous devez d'abord obtenir la facture, puis vous devez obtenir les détails. Cela peut entraîner des problèmes de performances et également un couplage plus étroit entre les applications.

+0

Merci! Je vais combiner les vôtres et les recommandations de John Saunders ensemble. J'ai conçu tout retourner à la fois, mais on m'a demandé d'envisager une nouvelle conception, car il serait inutile d'obtenir toutes ces données à chaque fois et les utilisateurs se soucient uniquement de la «dernière» facture. Nous ne connaissons pas la façon dont les utilisateurs vont utiliser l'application - ils peuvent en avoir besoin tout le temps ou juste le dernier 99%. – Leon

+1

Ensuite, ayez une opération nommée "GetLatestInvoice", qui obtient seulement la dernière facture! –

1

Les services Web ne doivent pas être «bavards»: vous communiquez sur un réseau, et tout échange de demande/réponse coûte du temps. Vous ne voulez pas demander au client de demander dix fois quand il pourrait demander une fois.

Laisser le client demander toutes les données à la fois.

Si cela se révèle être un problème de performance, puis permettre au client de spécifier la quantité de données qu'ils veulent, mais il devrait encore tous être retournés dans un seul appel.

+0

Merci! Cela a été soulevé dans la revue de conception comme un goulot d'étranglement possible si les utilisateurs finaux la plupart du temps finissent par regarder les lignes de la «dernière» facture. J'ai besoin de montrer des métadonnées sur chaque facture (en renvoyant donc une liste de celles-ci), mais ne montre que des lignes pour une à la fois - en fonction de la sélection exacte des utilisateurs. – Leon

+1

Rappelez-vous que vous pouvez choisir d'en récupérer plus d'une grâce à la procédure stockée, mais n'en afficher qu'une seule. Le client peut mettre en cache les données. Cela vous donne un service réactif, et même l'effet de "chargement paresseux", sans beaucoup de trafic réseau de va-et-vient. –

1

Je ne pense pas que ce soit une mauvaise conception, je pense que c'est un compromis que vous devez considérer.Lequel est le plus important: renvoyer un graphique d'objet complet, ou les économies potentielles de transmission. Si, par exemple, vous êtes plus susceptible d'avoir des clients avec plusieurs centaines de milliers de InvoiceLines et que vous n'avez besoin que de ceux dans des circonstances très spécifiques, il semble très logique de les séparer de la manière dont vous le mentionnez.

Cependant, si vous avez presque toujours besoin du InvoiceLines, et que vous ne parlez que 10 instances, il est plus logique de toujours les envoyer ensemble.

+1

Merci pour la réponse. Je suis d'accord que c'est plus un compromis qu'un mauvais design, mais je n'aime pas que ça couple la logique du graphe d'objets à moitié cuit. Ce service Web peut être utilisé par d'autres applications, ce qui les obligerait à connaître les détails d'implémentation. – Leon