WCF / SOA - Pourquoi devrais-je créer des objets paramètres pour des requêtes simples

12

Notre entreprise lance une initiative SOA assez importante. Nous faisons bien des choses: la communication est bonne; de l'argent pour les outils, le cas échéant; et nous avons apporté une bonne expertise pour nous aider dans la transition.

Nous essayons d'élaborer des normes que nous pouvons suivre en tant que groupe, et l'une des normes proposées me dérange beaucoup:

Nous avons standardisé le modèle où chaque opération prend un objet de demande et retourne un objet de réponse.

Je me rends compte que c'est plus ou moins une approche standard pour beaucoup de gens, mais je me demande pourquoi devrais-je m'embêter? (Je ne suis pas si bon avec la sagesse reçue, j'ai besoin d'un peu pourquoi).

La plupart des services que je fournirai sont de simples récupérations de métadonnées organisationnelles. Par exemple, recherchez la stratégie de sécurité pour un utilisateur particulier. Cela nécessite un identifiant utilisateur et rien d'autre. La norme me dit que je devrais encapsuler cette demande dans un objet et encapsuler la politique retournée dans un objet de réponse.

Mon malaise est amplifié par un regard sur le WSDL généré par nos contrats. WCF génère automatiquement des messages de demande et de réponse et encapsule même l'objet de demande / réponse.

Je comprends parfaitement que si vous faites une demande complexe, un objet d'entrée complexe est garanti. C'est ce que vous feriez même si les services n'étaient pas impliqués.

Ma question est pourquoi devrais-je encapsuler automatiquement les demandes et les réponses lorsque:

  • Il rend les services simples moins expressifs
  • Vous le feriez quand même pour un service complexe
  • WCF crée quand même un message de demande / réponse

J'ai trouvé les arguments suivants en faveur de cette approche:

Il prend en charge la gestion des versions en permettant de glisser des paramètres facultatifs dans l'objet de demande.

À l'époque, j'ai fait pas mal de COM, et je considérerais cela presque comme un anti-modèle pour le contrôle de version. Pour certaines choses, je suppose que cela aiderait, mais je m'attends à ce que là où cela aiderait, vous avez déjà un objet paramètre de toute façon.

Il permet d'isoler les données et comportements communs à une classe de base

Celui-ci a du poids avec moi.

Il éloigne les gens d'un comportement de style RPC vers un comportement de messagerie

J'ai lu ceci sur le site de Microsoft et l'ai entendu de notre gourou, mais je n'ai toujours pas une idée claire de ce qu'ils signifient ou pourquoi il est précieux. Est-ce que les interfaces d'apparence naturelle font que les gens ont tendance à oublier qu'ils appellent un service distant?

Je cherche à refactoriser les signatures de peut-être 300 méthodes, donc c'est une quantité non triviale de douleur. Je suis un grand fan de cohérence dans les implémentations, donc je suis prêt à endurer la douleur, cela aidera simplement à savoir que cela en vaudra la peine à la fin.

Andy Davis
la source

Réponses:

3

Je pense que le versioning est probablement le meilleur argument. Lorsque vous avez un contrat d'exploitation existant comme

int GetPersons(int countryId);

que vous souhaitez améliorer, par exemple par un autre filtre plus tard

int GetPersons(int countryId, int age);

Vous devrez écrire un nouveau contrat d'exploitation et avec un nouveau nom car il doit être unique. Ou vous conservez le nom et publiez une nouvelle v2 de votre service avec l'ancienne v1 toujours en place pour une compatibilité descendante.

Si vous enveloppez le paramètre dans un objet, vous pouvez toujours l'étendre avec des paramètres par défaut / facultatifs et tous vos clients existants ne seront pas affectés lorsque vous réutilisez le même contrat d'opération.

Cependant, je vous conseille également de nommer vos objets de manière appropriée. Même si cela enveloppe simplement un int, si vous commencez par IntMessagequelque chose de similaire, vous ne vous rendez pas service en le prolongeant. Vous devez le nommer par exemple PersonFilterdès le début, ce qui signifie que vous devez réfléchir un peu à ce que cet appel de service devrait attendre comme paramètre sémantiquement et donc à ce qu'il est censé faire. Peut-être (et c'est peut-être très vague) que cela aidera à développer les bons services et à maintenir une API de taille décente.

Il permet d'isoler les données et comportements communs à une classe de base

C'est quelque chose à faire avec prudence. Les contrats d'héritage et de données ne vont pas si bien ensemble. Cela fonctionne, mais vous devrez spécifier tous les sous-types connus du contrat qui pourraient passer par le câble, sinon le sérialiseur de contrat de données ne se plaindra pas de types inconnus.

Mais ce que vous pourriez faire (mais probablement pas encore, je suis encore indécis à ce sujet) est de réutiliser les mêmes messages entre différents services. Si vous placez les contrats de données dans une dll distincte, vous pouvez partager cela entre le client et le service et vous n'avez pas besoin de convertir entre les types lorsque vous appelez différents services qui attendent essentiellement le même message. Par exemple, vous créez un PersonFilter et le soumettez à un service pour obtenir une liste de filtrage de personnes, puis à un autre service et avoir les mêmes objets sur le client. Je ne peux cependant pas trouver un bon exemple dans le monde réel et le danger est toujours qu'une extension des contrats de données ne soit pas assez générale pour tous les services qui utilisent ce contrat.

Dans l'ensemble, à part le versioning, je ne trouve pas non plus vraiment la raison de tuer pour le faire de cette façon.

Andreas
la source
Je pense que la raison pour laquelle je prends le
Andy Davis
(désolé, l'interface de commentaire me donne du chagrin) Merci d'avoir répondu. Je pense que la raison pour laquelle je prends l'argument de versioning avec un tel grain de sel est que si vous avez ajouté un nouvel argument, vous avez probablement changé la sémantique. Si (comme dans votre exemple) vous venez d'ajouter un âge, alors la sémantique était probablement pour la recherche et vous aviez un "objet de recherche" dedans pour commencer.
Andy Davis
Considérons maintenant mon exemple de politique de sécurité. Peut-être que nous décidons que pour fournir correctement une politique de sécurité, nous devons connaître non seulement l'utilisateur, mais l'installation dans laquelle ils travaillent. C'est bien plus que l'ajout d'un argument, nous avons changé la sémantique de l'appel. En supposant que nous sommes en mesure de fournir ces informations pour un appelant de la version précédente, je pense qu'il est plus logique de versionner le contrat de service. Ensuite, l'implémentation de l'ancienne version peut être isolée et vous ne finissez pas par mélanger l'ancienne sémantique avec la nouvelle.
Andy Davis
0

Les notes de Martin Fowler sur l' objet de transfert de données sont appropriées ici, je pense.

Lorsque vous travaillez avec une interface distante, comme Remote Façade (388), chaque appel est coûteux. Par conséquent, vous devez réduire le nombre d'appels, ce qui signifie que vous devez transférer plus de données à chaque appel. Une façon de procéder consiste à utiliser de nombreux paramètres. Cependant, c'est souvent difficile à programmer - en effet, c'est souvent impossible avec des langages tels que Java qui ne renvoient qu'une seule valeur.

La solution consiste à créer un objet de transfert de données pouvant contenir toutes les données de l'appel. Il doit être sérialisable pour traverser la connexion. Habituellement, un assembleur est utilisé côté serveur pour transférer des données entre le DTO et tous les objets de domaine.

La même chose pourrait s'appliquer aux demandes. Quant à RPC, et pourquoi son mauvais:

Est-ce que les interfaces d'apparence naturelle font que les gens ont tendance à oublier qu'ils appellent un service distant?

Je pense que c'est vrai, mais pas la raison principale. Une autre raison d'éviter le RPC est qu'il peut encourager des clients et des services étroitement couplés.

Kyle Hodgson
la source
Merci pour votre contribution, mais je ne pense pas que la discussion DTO soit si pertinente. C'est le même nombre d'appels, et si vous regardez le WSDL, tout est automatiquement empaqueté dans un objet de demande et de réponse. La convention concerne la sémantique visible , c'est-à-dire que les gens devraient considérer cela comme une demande et une réponse plutôt qu'un appel de méthode à distance.
Andy Davis
Souhaitez-vous élaborer sur les CPR encourageant les clients et les services étroitement couplés? Je ne vois pas du tout que cela affecte le service. Pour le client, je ne vois pas vraiment comment quelque chose change vraiment. Dans les deux cas, le client détient un proxy qui décrit un certain nombre d'opérations fournies par un service. Qui met en œuvre l'autre côté du service n'est en aucun cas l'affaire du client.
Andy Davis