La modularité compte parmi les propriétés importantes d’un système d’information, car elle facilite d’autres caractéristiques très appréciables :
- L’évolutivité pour ajouter, supprimer, adapter ou remplacer une zone du SI de façon autonome, sans engager de changement radical sur l’ensemble du SI ou une grande partie (aussi connue comme refonte ou big bang)
- La modernisation – ou le traitement de l’obsolescence – pour remettre une zone du SI en conformité avec les exigences de maintien en condition opérationnelle indépendamment des autres zones.
Beaucoup de systèmes prétendent à être modulaire. Pourtant, ce n’est pas le cas en pratique. La raison est que l’on confond modularité avec découpage, classement ou encore cartographie. Être en mesure de ranger les applications dans des zones, quartiers ou îlots ne suffit pas à garantir la modularité.
La raison vient que les processus se croisent dans le plan applicatif (généralement la chaine de valeur est orthogonale à l’organisation des fonctions de l’entreprise) et de là nait un entremêlement qui va naturellement contre la modularité. La modularité n’est donc pas automatique et dépend d’un travail conscient de conception.
La traversée des applications par les processus se traduit par des flux. La modularité vient donc des caractéristiques issues de ces flux :
- Au niveau unitaire, la qualité du contrat de service, définissant les attendus et les contraintes applicables au flux
- Au niveau global, le niveau d’acyclicité dans le graphe des flux, c’est-à-dire la densité des dépendances circulaires.
Le bon contrat de service (MaRTiN)
Le flux contribue à la modularité du SI s’il répond à un contrat de service qui a de bonnes propriétés :
- Montée en charge (ou scalabilité) : le consommateur peut demander un accroissement du débit du flux à condition de respecter le capacity planning du producteur.
- Rétrocompatibilité : le consommateur du flux peut converser avec le producteur dans une version plus ancienne.
- Tolérance à la latence : la communication entre le producteur du flux et le consommateur du flux peut se faire avec des conditions larges de synchronicité (voir se faire en asynchrone).
- Nécessaire et suffisant : les données échangées sont nécessaires pour répondre au cas d’usage sans dévoiler plus que nécessaire l’encapsulation du producteur.
Un moyen mnémotechnique est de se demander si notre contrat de service est bien MaRTiN !
On peut se convaincre que ces propriétés sont bien utiles :
- La montée en charge est nécessaire pour supporter un cas d’usage qui s’ajoute ou se développe.
- La rétrocompatibilité permet de faire évoluer un composant sans propager les changements.
- La tolérance à la latence permet de localiser un composant plus ou moins près d’un autre avec qui il communique. On pourra penser aux contraintes posées par le Cloud hybride, l’Edge, …
- Enfin, la dernière propriété demande un effort particulier de conception : assez pour transmettre la charge utile d’information, pas trop pour ne pas compromettre l’encapsulation des applications.
Idéalement, les applications communiquent au travers de bons contrats de service. Hélas, ce n’est qu’un idéal. Il n’y a pas d’alignement d’intérêt entre les éditeurs d’applications et les intégrateurs d’applications : les premiers recherchent la valeur ajoutée fonctionnelle quand les seconds s’intéressent à la continuité du SI. Quand le SI est le produit d’un patchwork de logiciels, il n’y a donc pas de raison particulière que les flux suivent de bons contrats.
Casser les contrats pour faire évoluer le SI
Dans un monde concret, les contrats doivent être cassés pour permettre l’évolution du SI. Tout n’est pas perdu ! Si les flux respectent l’acyclicité, il est alors possible de casser les contrats sans déstabiliser le SI. On pourrait parler de modularité faible. Il est temps d’aborder la seconde caractéristique utile des flux : l’acyclicité.
Les flux correspondent à des flots de données allant des producteurs vers les consommateurs. Quand les flux vont dans le même sens, il est alors possible de casser les contrats dans le même ordre et d’avoir un SI cohérent à chaque étape. À l’inverse, quand les flux refluent et forment des cycles, casser le contrat amène au dilemme suivant : mettre à jour l’ensemble du cycle (et faire une opération généralement crainte de bonne raison, le big bang) ou accepter d’avoir un SI instable pendant une certaine période de temps. Les flux peuvent être organisées selon un Graphe Acyclique Dirigé (Directed Acyclic Graph, DAG), un graphe complet ou une situation intermédiaire entre ces deux cas extrêmes avec plus ou moins de dépendances circulaires.
Un moyen pour pouvoir évaluer la situation courante est de faire une analyse DSM (Dependency Structure Matrix) en considérant les flux de données entre les nœuds applicatifs. Les flux sont rangés dans une matrice. L’algorithme DSM vise à arranger l’ordre des nœuds applicatifs pour rendre la matrice aussi triangulaire que possible. Si elle est triangulaire, bravo, il n’y a pas de dépendance circulaire. Vous avez même deux enchainements possibles pour remanier le SI tout en ayant des étapes intermédiaires stables. À l’inverse, si la matrice est remplie, le SI est analogue à un sac de nœud (ou un big ball of mud, comme disent nos amis anglo-saxons).
Pour se convaincre de l’analogie entre la triangularisation de la matrice DSM et de l’absence de dépendance circulaire, prenons l’exemple suivant : l’application A envoie un flux vers l’application B ; B envoie un flux vers C et C renvoie un flux vers A. Toutes les applications émettent un flux vers elles-mêmes, naturellement. On constate un cycle de dépendance.
Maintenant, traduisons ce graphe dans une matrice de dépendance. On constate qu’on ne peut pas la triangulariser, c’est-à-dire faire que toutes les cases cochées soient au-dessus ou en dessous de la diagonale de la matrice. Si on casse le contrat de A vers B, alors l’impact concerne A, B, mais aussi C et doit être instruit simultanément pour maintenir la cohérence de l’ensemble.
Les surfaces des contrats de services sont plus grandes qu’on ne le pense.
Les surfaces de contact entre les applications sont souvent plus grandes qu’on ne le pense. C’est aussi une des raisons dans mon expérience qui explique le décalage entre la perception des acteurs sur la modularité de leur SI et la réalité. Il arrive que les accès aux données puissent se faire en dehors de la couche de service. Par exemple, une application tierce peut avoir un accès direct sur la base de donnée, rendant caduque son encapsulation au passage. Un cas plus subtil est quand l’application exporte sa base de données dans un lac de données, son contrat de service s’étend de facto au schéma de la base de données. Nous pouvons un cas combiné de surface large et de dépendance circulaire quand les applications ont un accès aux autres bases de données. Cette situation, très défavorable, n’est malheureusement pas rare. Elle s’explique souvent par une stratégie opportuniste dans la durée.
Conclusion
La modularité du SI est le produit de la qualité des contrats de service et de l’organisation des flux dans le SI. Elle dépend d’un travail soutenu de conception (et d’architecture !).
La modularité n’est jamais acquise : elle est fréquemment la première victime de l’entropie du SI. Bien souvent, la dégradation de la modularité se fait sans la prise de conscience des acteurs. À plusieurs reprises, j’ai vu des responsables être effarées par le sac de nœuds derrière un SI pourtant bien ordonné d’un point de vue externe : l’acceptation passe alors par les phases du deuil.
Accessoirement, l’analyse de la modularité d’un SI est le seul cas d’usage où j’ai fait appel à l’algèbre dans mes activités d’architecte. Rien que pour ça, cela méritait de s’y pencher !