Principe des dépendances acycliques
Objectif de la décomposition en packages
Le but de la décomposition en packages est de temporiser la propagation des changements dans l'application : les changements d'une classe impactent immédiatement les autres classes du package, mais elles n'impactent les packages qui en dépendent que lorsqu'une nouvelle version du package est livrée :
|
Les modifications d'une classe de A n'est propagée aux packages B et C que lorsque ceux-ci décident d'utiliser une nouvelle version de A, et aux packages D et E que lorsque ceux-ci décident d'utiliser une nouvelle version de C. |
Les packages introduisent donc des points de synchronisation des changements dans l'application. La propagation des changements étant guidée par les dépendances entre packages, l'organisation de ces dépendances forme un élément fondamental de l'architecture de l'application.
Effet d'un cycle dans le graphe de dépendances
Le principe des dépendances acycliques stipule que les dépendances entre packages doivent former un graphe acyclique orienté.
Considérons en effet l'impact d'un cycle dans le graphe de dépendances :
|
En cas de rupture d'interface d'une classe de A, la recompilation de A peut être rendue impossible du fait que B utilise l'ancienne version de la classe modifiée. Il faut donc recompiler (ou même modifier) B avant de compiler A, donc A et B doivent évoluer ensemble. On peut alors considérer que A et B forment un unique package. |
Le même raisonnement s'applique à des cycles plus larges :
|
Pour compiler le package A, il faut utiliser une version de E qui s'appuie sur la version courante de A : A et E doivent donc être compilés en même temps. Le même raisonnement s'applique à C. Résultat : il faut compiler et livrer A, C et E en même temps. Le package D utilise le package C, et de proche en proche les packages A et E. Les packages A, C et E peuvent donc être considérés comme un seul et même package. |
Pour tirer parti de l'effet de temporisation de la décomposition en packages, il faut donc éviter tout cycle dans le graphe de dépendances.
Technique d'inversion des dépendances
La technique d'inversion de dépendances est celle présentée dans le principe d'inversion des dépendances, et repose sur l'introduction d'une classe d'interface :
Dans l'exemple de gauche, une classe A du package A utilise une classe B du package B. Le package A dépend donc du package B. Pour inverser la dépendance, on introduit une classe d'interface I dans le package A, I représentant l'interface de B utilisée par A. B est ensuite définie comme dérivant de I (ou implémentant l'interface I), et A utilise B via son interface I. Résultat : B dérive de I, donc B utilise I, donc le package B dépend du package A.
Il faut par contre ajouter un mécanisme qui permette d'enregistrer l'instance de B auprès de A. Ce mécanisme sera placé dans le package B ou un package tiers qui aura une visibilité sur A et B.
_____
Article original : http://www.objectmentor.com/publications/stability.pdf
Voir également AcyclicDependenciesPrinciple
sur Wiki


