Garder un module autonome : repérer les dépendances qui compliquent les changements
Un module perd son autonomie quand ses règles et ses données se dispersent. Voici les signes à examiner et les moyens de garder des frontières compréhensibles.
Article
Une dépendance détermine quels modules devront changer ensemble. Un exemple de facturation pour choisir son sens, isoler les détails et éviter les cycles.
Changer de fournisseur de courriels devrait surtout modifier le code qui envoie les messages. Si cela oblige aussi à retoucher les règles de facturation, les deux parties sont trop liées. Pour éviter cette situation, il faut choisir ce que chaque module connaît des autres. Le plus souvent, les détails techniques doivent s'adapter aux besoins du métier, exprimés dans un contrat stable.
Prenons un module qui crée une facture après une vente. Il calcule les montants, applique les règles de taxe et enregistre le résultat. Un autre module prévient le client par courriel. Les deux participent au même service rendu, mais leurs raisons de changer sont différentes : une nouvelle règle de calcul d'un côté, un nouveau fournisseur de messagerie de l'autre.
Leur séparation sera utile si vous pouvez modifier l'envoi sans rouvrir le calcul des factures. C'est ce que le sens des dépendances aide à obtenir.
Un module dépend d'un autre lorsqu'il a besoin de connaître une partie de son fonctionnement pour faire son travail. Cette connaissance peut être le nom d'une opération, les données attendues ou le sens d'un message.
Dans un schéma, la flèche part du module qui utilise cette connaissance vers celui qui la fournit. La notation « A connaît B » signifie donc que A dépend de B.
Cette relation apparaît dans plusieurs échanges courants :
Le sens de circulation des données peut donc différer du sens de la dépendance. La facturation envoie un événement à la messagerie, mais c'est la messagerie qui doit connaître la signification de cet événement. La facturation peut ignorer quels modules le reçoivent.
Martin Fowler décrit cette différence : l'émetteur ne connaît pas les abonnés, tandis que chacun d'eux se conforme à l'interface de l'événement. Ajouter des événements réduit certaines dépendances ; le contrat du message reste à maintenir.
Un contrat décrit ce qu'un module accepte et promet en retour. Par exemple : les informations nécessaires pour envoyer une facture, le résultat de l'envoi et les erreurs possibles. Il permet à deux modules de travailler ensemble sans partager leur code interne.
Si le calcul des factures utilise directement les options propres à un fournisseur de courriels, changer de fournisseur peut l'obliger à changer aussi. Si ces options restent dans le module d'envoi, la modification reste localisée.
Cette séparation guide le découpage proposé par David Parnas en 1972 : identifier les décisions susceptibles de changer, puis les cacher derrière les interfaces des modules. Le fournisseur de messagerie est précisément une décision que la facturation n'a pas besoin de connaître.
Je recommande de partir des changements que vous voulez pouvoir faire séparément. La question devient concrète : si le fournisseur d'envoi change demain, quels fichiers et quels tests faudra-t-il reprendre ?
La première consiste à définir, du côté du métier, une interface qui exprime le besoin d'envoi. La facturation l'appelle ; le code propre au fournisseur la réalise. Le métier connaît le service attendu, mais ignore sa mise en œuvre technique.
C'est une application du principe d'inversion de dépendance, formulé par Robert C. Martin en 1996 : les règles de haut niveau et les détails techniques dépendent d'abstractions. L'interface permet ici de remplacer le fournisseur sans modifier les règles de facturation.
La seconde consiste à publier un événement lorsque la facture est créée. Le module de messagerie s'y abonne et prépare le courriel. Cette solution convient lorsque la facturation peut terminer son travail sans attendre l'envoi.
| Organisation | Ce que connaît la facturation | Conséquence d'un changement de fournisseur |
|---|---|---|
| Appel direct au fournisseur | Son interface et ses options | Le code de facturation peut devoir changer |
| Interface définie selon le besoin métier | Le contrat d'envoi | Le changement peut rester dans l'implémentation de cette interface |
| Publication d'un événement | Le fait métier qu'elle publie | Le changement peut rester dans le module abonné |
L'événement ajoute des questions de livraison et de suivi des échecs. Si le courriel n'arrive pas, un traitement doit pouvoir le détecter et le relancer. Inverser une dépendance n'oblige donc pas à adopter une messagerie asynchrone : une interface peut suffire.
Une boucle apparaît si A dépend de B et B dépend de A. Elle peut aussi passer par plusieurs modules : A utilise B, B utilise C et C utilise A. Chaque liaison semble raisonnable prise séparément ; leur combinaison complique les changements.
Si ces modules doivent être construits ou livrés indépendamment, la boucle risque de les obliger à évoluer ensemble. C'est le problème traité par le principe des dépendances acycliques de Martin. « Acyclique » signifie simplement « sans boucle ».
La portée de cette règle compte. Deux classes livrées dans un même module ne posent pas forcément le même problème que deux bibliothèques destinées à être distribuées séparément. Vérifiez les dépendances à l'échelle où vous avez besoin d'autonomie.
Pour chaque liaison entre modules, notez ce que le premier doit connaître du second et pourquoi. Puis essayez un changement plausible : remplacer un fournisseur, ajouter un destinataire ou modifier une règle métier.
Les quatre organisations de dépendances donnent plusieurs réponses possibles. Gardez toutefois un appel direct lorsqu'il exprime clairement la responsabilité et que son contrat convient : ajouter un intermédiaire sans changement à isoler peut compliquer le code sans faciliter son évolution.
Explorer
Choisis dans l’index d’après les étiquettes de cet article — les plus proches d’abord, hors de sa série. Rien n’est écrit à la main : un article publié demain avec les mêmes étiquettes y prendra place.
Un module perd son autonomie quand ses règles et ses données se dispersent. Voici les signes à examiner et les moyens de garder des frontières compréhensibles.
Une application peut se déployer en un bloc et garder des modules distincts. Exemple avec l’inscription et la facturation, leurs données et leurs échanges.
Une donnée absente ou ancienne ne bloque pas tous les usages. Choisir, opération par opération, quand attendre, limiter le service ou accepter un retard.
Laisser un commentaire
Votre commentaire sera relu avant d'être publié.