Quelques notes sur Service Design Patterns

Quelques semaines seulement après avoir publié une liste des dix livres que je considère comme fondamentaux pour un informaticien, je viens de finir un autre bouquin qui aurait été un excellent candidat : Service Design Pattern, de Robert Daigneau.

Douze post-it coincés dans un bouquin pour garder trace de points importants, c’est un record personnel Sourire. Alors, je me disais que ça valait le coup, non pas de faire réellement une revue du livre, mais plutôt d’expliquer ces quelques points qui m’ont paru importants. En particulier, de les commenter au regard de mon expérience actuelle de migration d’un ensemble applicatif d’un éditeur de logiciel vers une architecture SOA.

Notion de couplage

J’ai souvent entendu parler de deux types de couplage seulement, à savoir le couplage comportemental et le couplage temporel. De plus, on a souvent tendance à parler du couplage comme quelque chose de binaire. La page 9 explique bien que le couplage est plutôt une valeur plus ou moins forte, et qu’il est impossible (et pas souhaitable) d’atteindre des architectures complètement découplées.

Pour moi, c’est un peu comme la différence entre des langages fortement typés et des langages à typage dynamique. Le contrôle par compilateur correspond à un contrôle fort en amont, avec du typage. A l’inverse, les langages dynamiques sont plus permissifs sur les types, mais cela ne veut pas dire qu’ils ne connaissent pas les types. Il y a moins de couplage, mais il y en a toujours. Moins – en gros, n’avoir que des chaînes – ne servirait à rien.

C’est un peu la même chose pour le couplage : il est inutile d’essayer de le réduire à néant, car on élimine alors toute la sémantique métier avec, alors que les difficultés techniques associées ne baissent plus tellement.

Pour en revenir aux types de couplage, le livre utilise plutôt une décomposition en quatre types, plus techniques et donc plus faciles à comprendre : fonctionnel, structurel sur les données, temporel et sur l’URI. Ce dernier type de couplage, je trouve, est particulièrement sujet à approfondissement, car il est en lien avec l’utilisation de registres ou annuaires de services. Or, ce sujet est complexe, car la mort d’UDDI ne veut pas dire que les besoins initiaux qui avait prévalu à sa conception ont disparu pour autant… Mais j’y reviendrai un peu plus loin.

WSDL comme une documentation lisible par une machine

J’ai bien aimé la petite note à la page 15 expliquant que même si WSDL est prévu pour une exploitation de la définition d’un service par une machine, il ne peut que capturer une petite partie de l’information nécessaire pour utiliser ce service.

On a souvent tendance à se dire que WSDL porte une bonne partie du service, et qu’il suffit de rajouter quelques métadonnées sémantiques pour que la description soit complète. Mais c’est un piège qui amène au mode de développement “code –> WSDL –> proxy auto-généré –> code”, chargé à bloc en couplage technique.

Après, c’est vrai que ça serait bien que la norme embarque une gestion des échecs un peu plus détaillée, mais c’est bien de rappeler, surtout dans un bouquin technique pour des informaticiens qui n’aiment pas ça, qu’un service est surtout décrit par sa documentation (oui, je sais, j’utilise des gros mots).

Quelques considérations sur le pattern Linked Service

Le pattern Linked Service consiste à envoyer dans la réponse d’un service la liste des URI qui correspondent aux opérations qui auraient du sens à être appelées par la suite. Le cas typique est dans AtomPub, lorsqu’on renvoie sur l’URI d’un article complet, ou dans OData quand on fournit le token pour voir la page suivante de données.

Le livre, en page 79, fournit quelques excellentes remarques sur la sécurité et la génération des URIs. Je n’avais personnellement jamais pensé au problème effectivement élevé d’attaques de type MITM sur ce pattern, mais je sais maintenant qu’il faudra mitiger le risque. Le problème peut en plus être aggravé par le fait que le client peut, grâce à ces données, devenir de plus en plus léger, et se contenter de présenter les URIs avec leurs métadonnées descriptives (format XLink, OK, mais les valeurs ne sont pas encore normalisées). Or, si le client devient trop bête, il y aura encore moins de chance qu’il valide que les données n’ont pas été modifiées depuis leur envoi par le serveur.

Par contre, il va falloir réfléchir sérieusement sur la bonne façon de mettre ce pattern en action dans SOAP, car cette norme ne prévoit pas la notion de lien vers un autre appel. On retombe encore sur une raison d’utiliser plutôt REST, bien plus adapté à gérer les URIs. Bien sûr, SOAP est appelé sur du HTTP en général, mais REST utilise beaucoup mieux toutes les facettes de ce protocole.

Data-binding et Data Transfer Objects

La page 98 est une autre excellente ressource sur des points dont on ne parle pas souvent dans les autres livres sur les architectures SOA ou sur les services en général. Par exemple, le couplage provoqué par les solutions de data-binding. Même si des solutions existent pour le réduire, comme la classe ExtensionDataObject en WCF, le livre recommande des approches encore plus souples comme le pattern TolerantReader.

Un autre point sur le couplage entre les DTO et la signature : si vous voulez le réduire, il faut faire attention à limiter le nombre d’entités, et bien avoir des signatures très simples, avec juste une ou deux entités, et tout le temps les mêmes. Pas des versions réduites, ou alors carrément des URI.

Un peu plus loin en page 100, un rappel sur l’importance du “chunky, not chatty”, avec pour une fois une analyse des impacts sur la scalabilité, et la recommandation au final d’utiliser le pattern Data Transfer Object Collection.

La page 105 donne une approche du polymorphisme sur les DTO avec une référence XSD à un type abstrait dont je n’avais jamais entendu parler dans aucune autre ressource internet ou aucun livre. Ou plutôt, j’avais surtout entendu que c’était risqué, mais le livre montre (avec le code associé) comment faire de manière simple et efficace.

Service connectors

En page 171, j’ai trouvé une explication claire sur un sujet qui était nébuleux depuis longtemps. Nous savons tous qu’UDDI est mort, mais il y avait quand même un besoin derrière la création de cette norme, même s’il a été surchargé avec des tas de trucs inutiles sous lesquels elle s’est finalement écroulée. Alors, comment gérer de manière propre le besoin de ne pas avoir des proxies qui accèdent directement à des services ?

Les deux solutions proposées sont le Service Registry (connu) et le Virtual Service (dont c’est la première fois que j’entendais parler en tant que pattern reconnu). Il y a aussi le Service Gateway qui peut être utile dans les cas les plus complexes.

Pour ce qui est de l’approche routage, on peut utiliser WS-Routing, mais aussi un reverse-proxy, ou même passer par le DNS. Par contre, il y a des choses dans le registre de services qui peuvent être intéressantes en plus : les policies (WS-Policy), les règles d’appels (seulement pendant les heures ouvrées, par exemple), etc. Là encore, il faut faire un choix en fonction du niveau de fonctionnalité dont on a vraiment besoin, et ne surtout pas se retrouver à mettre en place un registry si c’est pour gérer un changement d’URL tous les deux sur des contrats à version unique…

Gestion des contrats

La page 177 contient des arguments REST intéressants contre les contrats formels. Venant plutôt du monde SOAP mais appréciant la simplification proposée par REST, je me disais que la perte de contrats formels restait gênante, et que des initiatives comme WADL étaient à étudier, mais je me suis rendu compte à la lecture de cette page et des suivantes qu’on pouvait se baser sur HTTP et toute sa richesse plutôt que de recourir à d’autres technologies.

Idempotence

Toute la partie sur l’idempotence est absolument excellente, et une des plus documentées que j’ai lues. En page 208, il y a une discussion sur le pattern Idempotent Retry, et l’utilisation du code HTTP 503 avec un header Retry-After qui n’est pas très connu. Attention, ce genre de comportement est surtout recommandable avec des services de type ressources, sinon on se retrouve avec une ambigüité sur l’exécution de la commande. Ce n’est pas parce qu’il y a idempotence qu’on peut se permettre de ne pas prévenir qu’il n’est inutile de relancer le service…

A propos d’idempotence, une astuce pour l’utilisation de la date de valeur de la commande, et qui servira pour l’historique sur l’entité, si elle est stockée : il vaut mieux utiliser la date du client plutôt que celle du serveur pour faciliter l’idempotence et éviter les effets dûs à l’asynchronisme. Après, il y a aussi des arguments pour utiliser celle du serveur (unification de l’ordre des entités, possibilité d’horodatage, etc.), mais il faut savoir les arguments des deux côtés pour bien choisir.

Le retour de ce genre de service sera typiquement un acknowledgement plus un Linked Service, qui pourra servir à surveiller si la commande a finalement abouti. Ceci permet de mettre en place un asynchronisme de manière simple.

Tests des contrats de services

Page 253, une rareté : des idées solides sur les tests. C’est suffisamment rare pour le souligner, que de voir parler de tests dans un livre dont ce n’est pas le sujet principal. En plus, la décomposition des tests est très claire, avec quatre points à tester : le contenu (auquel on pense en premier), le contexte d’exécution (plus rare), le comportement (codes de retour, headers, etc., souvent laissés de côté) et la qualité de service (dont on ne sait souvent pas quoi vraiment faire).

En page 257, un petit complément sur l’utilisation d’IIntegrationContext dans NUnit, pour configurer un client HTTP sur un fake de Service Connector.

Le bouquet final

Et pour finir, cinq pages extraordinairement complètes sur la façon dont les patterns qui ont été expliqués dans le livre peuvent améliorer ou au contraire dégrader la capacité d’évolution des services. Pour le coup, c’est la première fois que je vois une étude aussi approfondie sur ce sujet. D’habitude, les livres ou les articles se contentent d’expliquer les patterns, avec leurs point positifs et négatifs, mais ne creusent pas beaucoup sur leur mise en application, comment ils impactent le développement dans le long terme. Là, on sent que l’auteur a une longue expérience pour pouvoir juger de si un pattern a une influence sur l’évolution d’un service.

Conclusion

Si vous voulez vous instruire sur les architectures orientées services, Service Design Patterns est une lecture obligatoire.

Petite note additionnelle : si vous vous posez la question de l’extensibilité des contenus de services web, et que vous vous demandez pourquoi XML Schema a l’idée bizarre de ne pas considérer comme valide tout ce qui est supplémentaire au schéma, jetez un œil à Schematron.

Et une toute dernière astuce pour la route : si vous avez une équipe en charge des services, faites-lui réaliser aussi les APIs pour appeler ces services. Personne d’autre qu’elle ne saura mieux comment réaliser les requêtes, et vos clients ne passeront pas leur temps à générer des proxies sans savoir à quoi ils servent, ce qui génère du couplage technique.

About JP Gouigoux

Jean-Philippe Gouigoux est Architecte Logiciel, MVP Connected Systems Developer. Il intervient régulièrement à l'Université de Bretagne Sud ainsi qu'à l'Agile Tour. Plus de détails sur la page "Curriculum Vitae" de ce blog.
This entry was posted in Retours and tagged . Bookmark the permalink.

2 Responses to Quelques notes sur Service Design Patterns

  1. frinux says:

    Ca a l’air très intéressant, petite question avant que je ne me procure cet ouvrage : est-ce qu’il est complètement découplé (!) de la notion de technologie (SOAP, WS*…) ? Etant donné que mon environnement est plutôt RESTful, j’ai envie de creuser l’application de ces concepts sur cette tchnologie.

    Merci

    • JP Gouigoux says:

      Oui, pas de souci. Aucune adhérence à une techno, un protocole ou quoi que ce soit. Il y a autant de description des approches SOAP/WS-* que du REST/JSON, autant de code C# que de Java, etc. Mais si vous devez creuser sur REST, je me permets de vous recommander (en plus, pas en remplacement) l’excellent RESTful web APIs chez O’Reilly.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha Captcha Reload