En développement orienté objet comme en développement à base de composants, l'utilisation d'un ensemble de composants
pour représenter les entités persistantes résidant sur une base de données partagée est devenue monnaie courante. De
nombreux services informatiques ont souvent choisi de recourir à un schéma de base de données unique pour tous les
éléments persistants utilisés dans l'entreprise. Si cette démarche a eu un succès limité pour certaines organisations,
de nombreuses autres n'ont pas développé ce schéma. Un grand nombre de raisons explique l'échec d'une telle approche,
dont beaucoup ne sont pas de nature technique, mais liées à la multiplicité des applications ; l'accès, le verrouillage
et la modification des données partagées posent des problèmes très difficiles à résoudre d'une frontière à l'autre de
l'organisation.
Dans ces instructions, nous allons aborder deux sujets étroitement liées : un service doit constituer une encapsulation
complète des données qu'il nécessite et seul le partage des informations entre services doit être réalisé par un
échange de messages.
Ces instructions donnent des détails supplémentaires sur l'identification des services guidée par les données.
L'un des termes les plus souvent utilisés lors de la description du développement orienté objet est l'encapsulation :
un objet doit encapsuler son état (données privées) et sa logique d'implémentation. Dans le monde des services, nous
distinguons nettement l' Artefact : Service (implémentation) de l'Artefact : Spécification de service. Cette section traite de la
nécessité d'encapsuler un état. D'abord documenté dans [HELLAND], puis plus récemment dans [SESSIONS], ce concept était
axé sur le développement de systèmes autonomes, donc plus facilement évolutifs.
L'analogie la plus courante [HELLAND] est celle de la compagnie d'assurance. Lorsque vous souhaitez souscrire une
nouvelle police d'assurance, vous recourez généralement à un agent. Cet agent est chargé de vous aider à remplir les
formulaires de demande de souscription et, pour ce faire, accède généralement à des données concernant les types de
police et les tarifs appliqués. L'agent d'assurance agit en tant que "représentant" ("emissary" chez Helland) pour le
compte du "territoire" ("fiefdom" chez Helland) de la compagnie d'assurance. Il se peut que la compagnie d'assurance
accepte uniquement les demandes de souscription de police provenant d'un agent agréé. Le territoire est quant à lui
chargé de distribuer aux agents les informations de formulaire, tarif et police, et de traiter les demandes de
souscription. Cependant, bien que le territoire ait fourni les informations de police à l'agent et que l'agent ait été
certifié par le territoire, la compagnie d'assurance doit tout d'abord valider entièrement la demande de souscription
(le territoire ne se fie pas encore au représentant).
Les sections suivantes détaillent plus précisément le rôle de ces deux éléments principaux. Bien qu'ils ne soient pas
présentés dans un pattern concret ou en tant qu'approche prescriptive, ces principes sont importants en matière de
solutions orientées services.
Rôle du territoire
Le territoire est un service autonome ; il n'autorise la communication qu'au moyen de messages, lesquels sont
généralement supposés provenir de représentants agissant pour le compte du client. Le territoire est sûr, autonome et
définit une frontière de données complète. Aucune source de données ou autre donnée persistante n'est partagée entre
les territoires, ni entre les territoires et d'autres éléments logiciels. Il se peut toutefois qu'un seul serveur de
base de données soutienne plusieurs services de persistance, mais l'existence de différents espaces table ou conteneurs
de bases de données pour chaque territoire assure l'intégrité des données, la sécurité, etc.
Ce pattern comporte un autre aspect fondamental : il faut s'assurer que le représentant peut se comporter en tant
qu'agent raisonnable, qu'il peut interagir avec le client en communiquant le moins possible avec le territoire et que
le territoire distribue des exemplaires de certaines données de référence aux représentants pour qu'ils puissent les
stocker et les utiliser en local. Ainsi, dans l'exemple ci-dessus, le catalogue des polices disponibles, leurs
critères, leurs restrictions et leurs tarifs sont régulièrement distribués aux agents. Il est bien sûr important que
l'agent soit en mesure d'utiliser ces informations, mais il doit également comprendre que ces informations sont une
copie des données, et pas nécessairement les données utilisées par le territoire, et qu'elles peuvent par conséquent
être périmées. Elles peuvent être mises à jour une fois par mois. S'il existe une mise à jour, le représentant peut ne
pas être en mesure de traiter de nouvelles demandes de souscription ou il peut être en mesure de les traiter en
fonction des anciennes données.
Comme nous l'avons expliqué, le fait qu'un représentant agisse pour le compte d'un territoire n'implique aucune
relation d'accréditation entre les deux parties. Pour s'assurer que le représentant n'a pas été usurpé, tous les
messages seront soumis à une validation de leur syntaxe, de leur sémantique et de leurs règles avant d'être acceptés.
Les responsabilités détaillées du territoire sont les suivantes :
-
Il gère et distribue les données de référence à tous les représentants, en identifiant clairement leurs dates de
prise d'effet.
-
Il gère l'état des données transactionnelles ; toutes les transactions sont entièrement gérées en interne.
-
Il valide toutes les communications avec les représentants.
Rôle du représentant
Le représentant a un rôle d'agent. Il peut s'agir d'un composant spécifique à un client, d'un composant fondé sur
Internet ou d'un composant déployé spécifiquement, mais il doit posséder une caractéristique fondamentale : il gère les
données de référence requises pour alimenter les messages qui seront traités par le territoire. Il doit également gérer
les copies locales des messages spécifiques à une transaction. Ainsi, par exemple, des clients peuvent déclarer avoir
déjà une police existante. Le représentant peut d'abord en consulter les données pour préremplir le formulaire, puis
mettre en cache cette copie de la police existante pendant la durée de la transaction consistant à remplir la demande
de souscription.
En général, un représentant entre en jeu lorsque la communication entre le territoire et le client constitue une
transaction complexe, au point d'être gérée plus efficacement de cette manière. Il peut s'agir par exemple de la
rédaction de requêtes complexes, comme dans notre exemple. Ce pattern se retrouve aujourd'hui dans de nombreuses
organisations, où le système d'exécution de commande, qui traite les commandes et planifie leur livraison, est souvent
un système mis en place depuis plusieurs années. Dans ces organisations, qui ont commencé à effectuer des ventes de
produits interactives sur le Web, l'application Web agit en tant que représentant qui dispose d'une copie locale du
catalogue de produits et aide le client à préparer sa commande. Bien entendu, l'application web ne traite pas la
commande ; elle se contente de l'envoyer au système existant. Comme le représentant remplit la commande à partir des
données de référence, nous pouvons raisonnablement nous attendre à ce que la commande ne soit pas rejetée comme étant
erronée. Cependant, comme nous l'avons indiqué plus haut, le système de commande existant validera la commande avant de
l'accepter.
Les responsabilités détaillées du représentant sont les suivantes :
-
Il joue le rôle d'agent, pour le compte du client, afin d'établir les messages et d'interagir avec le territoire.
-
Il gère, le cas échéant, une transaction logique, en interrogeant les données de référence, en établissant les
messages et en envoyant les informations pour le compte du client.
-
Il gère une copie locale des données de référence, en effectuant des mises à jour selon les instructions du
territoire.
-
Il gère les stratégies de gestion de mémoire cache concernant les données sensibles au temps, telles que le
territoire les a identifiées.
De nombreuses applications sont formées d'ensembles de composants intégrés verticalement (voir le concept Architecture orientée services pour plus d'informations). Ces applications
comportent souvent peu de points d'intégration naturels. En matière d'intégration, l'approche la plus couramment
adoptée, en grande partie pour son apparente facilité, consiste à utiliser un système de stockage des données commun à
deux applications ou plus. Ainsi, lorsque les applications Stock et Passation de commande partagent la notion de
"Produit", elles accèdent aux mêmes tables dans la base de données. Cette solution entraîne un certain nombre de
problèmes potentiels liés aux performances et à l'accès concurrent, et les nouvelles relations qui lient ces
applications influencent l'évolution de chacune et la capacité du métier à réhéberger, redévelopper ou tout simplement
changer l'une d'elles.
Pour le développement de solutions orientées services, nous vous recommandons de faire en sorte qu'un service gère un
modèle de données spécifique, délimité et cohérent. Ainsi, l'analyse de l'utilisation des deux applications illustrées
ci-dessus doit identifier l'utilisation qu'elles font des données et la manière dont elles peuvent être séparées pour
être gérées par deux services autonomes. Cette démarche ne signifie pas qu'il n'y a aucune interconnexion entre les
modèles de données lorsqu'ils sont séparés. Par exemple, les services Stock et Passation de commande nécessiteront tous
deux une définition commune des produits, ainsi que des lieux de stockage et des emplacements d'origine des commandes.
Il existe deux solutions possibles : créer un service tiers pour le concept partagé (en l'occurrence, un service de
catalogue de produits serait pertinent) ou gérer ce concept dans seulement l'un des nouveaux services. Par exemple,
l'emplacement serait géré logiquement par le service Stock. Les messages envoyés vers et issus de l'un de ces services
devront contenir l'identificateur des éléments partagés pour pouvoir être interrogés ou récupérés si besoin est. Par
exemple, dans le cas du stock, une requête concernant les produits actuellement gérés par un emplacement renverrait une
liste d'identificateurs produit (et probablement des quantités actuellement disponibles) ; si les détails des produits
sont nécessaires, ils sont récupérés par le service de catalogue de produits.
Le modèle de données est évidemment un produit clé dans l'analyse
des frontières de données. Il faut créer des modèles de données pour la base de données existante et veiller à bien les
séparer au niveau du modèle de données physiques, ou de préférence, au niveau du modèle de données logique.
Si toutes les données sont stockées uniquement dans le service et que l'accès est refusé à tous, hormis au service,
toute la communication doit s'effectuer au moyen de messages identifiés dans la spécification de service. Cependant, il
est toujours important de noter que ces messages représentent une requête et un renvoi de données depuis la base de
données vers le client, et sont par conséquent des copies spécifiques des données détenues par le service. En tant que
tels, ils peuvent représenter en réalité l'état temporaire du service. Par exemple, la requête concernant la quantité
actuellement disponible du produit "234" renvoie un message spécifiant que l'emplacement "562" comporte une quantité de
"12." Si un autre client retire huit articles du stock et que le client d'origine tente d'acquérir 12 articles,
l'opération échouera.
Ces problèmes sont en effet ceux que posent la conception et la gestion des transactions traditionnelles ; la gestion
de la portée et des frontières des transactions est rendue un peu plus complexe, ou du moins plus visible, par la
nature trop lâche des liens qui unissent les services et les clients des services. Par conséquent, les messages doivent
être considérés comme des vues de données, mais également comme des copies de données. Plusieurs documents, y
compris Architecture SOA, contiennent des conseils sur la manière dont les messages peuvent
identifier de manière spécifique leur durée de vie et leur applicabilité.
Cette transformation vers l'approche fondée sur les messages et propre aux solutions orientées services comporte une
autre conséquence : nous pouvons désormais passer d'un modèle de données commun pour les applications à un modèle de
message commun pour l'intégration. En pratique, les messages définis pour les spécifications de service reposent le
plus possible sur des structures communes, éventuellement séparées dans un schéma cohésif qui peut être réutilisé entre
les services. Il s'agit d'une approche à l'intégration beaucoup plus flexible, car elle correspond également à la
solution du couplage lâche entre les services. De plus, la plupart des technologies utilisées dans l'implémentation des
services comprend des technologies, des outils ou des moteurs d'exécution qui permettent la transformation des messages
en capacités lorsque les schémas de message ne correspondent pas exactement entre eux.
Pour plus d'informations, en particulier sur le "prêt" et la mise en cache des messages, voir la Tâche : Conception de messages.
[HELLAND] Fiefdoms and Emissaries, Pat Helland, Microsoft.
[SESSIONS] Software Fortresses: Modeling Enterprise Architectures, Roger Sessions, Addison Wesley, 2003.
|