Érosion de l'architecture logicielle
En informatique, l'érosion d'un logiciel est l'écart entre l'architecture prévue initialement pour ce logiciel et son implémentation. Elle désigne également le phénomène où l'architecture d'un système logiciel ne permet plus de changements à celui-ci, à cause des changements continus introduits dans le système et qui le rend donc non maintenable[1].
Il existe divers moyens pour trouver où se situent ces points d'érosion et comment les contrer.
Causes de l'érosion
Les causes liées à l'érosion de l'architecture logicielle peuvent être catégorisées comme suit :
Ignorance
- La mauvaise connaissance d'une API et l'incompréhension d'un pattern de la part des développeurs peuvent entraîner sa mauvaise utilisation et affecter fortement la probabilité de non-respect de l'architecture prévue[2].
- Le manque d'expérience personnelle technique de la part des développeurs diminue aussi la maintenabilité et augmente le taux d'apparition de défauts[3].
- Une documentation inexistante ou de mauvaise qualité entraînent un manque de compréhensibilité pour les personnes ne connaissant pas bien le projet[3].
- Utiliser des notations non expressives (ex : nom de variables, de fonctions ou de classes ne signifiant rien comme "a", "b", "object", etc) entraînent une perte de la traçabilité des décisions de conception pour l'application[3].
- Dans le cas où un développeur manque de connaissances du système développé, il peut ne pas utiliser correctement les moyens mis à sa disposition par l'architecture qui a été prévue[4].
Mauvaise utilisation
- L'abus du pattern Singleton crée un couplage extrêmement fort qui empêche d'être modifié facilement[2].
- Si l'on code avec une modularité faible ou inexistante, on risque d'empêcher les modifications possibles par la suite[2].
- Le code smell désigne plus ou moins les antipatterns et indique la présence de problèmes de conception[5].
- La programmation procédurale dans un environnement orienté-objet entraîne une non-utilisation du polymorphisme dans une hiérarchie d'objets ce qui va à l'encontre du paradigme orientée objet[2].
Problèmes d'exactitude
- Les changements fréquents des prérequis ou des technologies ou bien des prérequis imprécis entrainent une réduction de la maintenabilité du système[3] - [2].
- Les suppositions erronées des développeurs dues au manque d'informations explicites sur l'architecture sont aussi source d'érosion[2].
Problèmes de continuité
- Les décisions architecturales oubliées ou non utilisées par les développeurs[2].
- Les erreurs dans la compréhension de l'architecture posent des problèmes pour l'implémentation du logiciel conforme à l'architecture de départ[2].
- Si l'on ne donne pas de directives sur la manière d'effectuer les changements à venir dans le système on risque de le rendre non maintenable[3].
- De même que s'il manque de bons exemples de conception ou bien que les développeurs manquent d'entraînement dans la révision de la conception ou sa documentation[3].
- Si l'on ne connait pas l'histoire d'un logiciel, lorsque l'on rencontre une incertitude à propos de l'évolution du logiciel, cela entraîne une perte de logique au niveau de l'architecture du logiciel[3].
Problèmes de langage
Problèmes de décisions
Il est inévitable pour un logiciel de s'éroder au point d'envisager la solution qu'est de recommencer le développement logiciel à zéro[6]. On parle généralement d'érosion dans la phase de maintenance d'un projet mais les recherches récentes prouvent que l'érosion peut apparaître dans la phase de développement due aux mauvaises décisions d'architecture prises. Il faut minimiser ces mauvaises décisions à la phase de développement pour obtenir un système final résistant aux changements et ainsi, retarder l'érosion du logiciel[2]. Quelles que soient les décisions prises, le logiciel finira par s'éroder. La bonne qualité des décisions prises permettant seulement de retarder l'inévitable[6].
La conception d'une application consiste à choisir son architecture.
- Si l'architecture est au départ incorrecte ou bien que les décisions pour la conception sont non optimales, le système peut être difficile, voire impossible à maintenir[3].
- Si l'on prête peu d'attention à la conception de l'application lors de changements apportés à celle-ci[3].
- L'accumulation des décisions de conception différentes peuvent aussi la rendre difficile et chère à maintenir[3].
- La mauvaise compréhension de l'architecture de la part des développeurs est une cause principale de l'érosion d'un logiciel[7].
- En effet, à force de complexifier une application dans le but de la rendre plus flexible, celle-ci devient beaucoup plus difficile à comprendre, ce qui engendre d'autres mauvaises décisions dans la conception[7].
- L'adoption d'outils ou de méthodes de développement inadéquates sont un mauvais support pour le développement et la maintenance du système[3].
- Des problèmes de communication dans l'équipe peuvent engendrer du code redondant[2].
- La mauvaise planification ou estimation de l'impact d'un changement de l'architecture, peut engendrer des problèmes d'érosion[2].
Problème de gestion de projet
Il y a deux stratégies dans la conception : optimale et minimaliste. Les logiciels industriels ne peuvent généralement pas se permettre d'utiliser la stratégie optimale par manque de temps ou d'argent et doivent se rabattre sur la minimaliste, ce qui engendre encore une fois l'érosion du logiciel[8].
- Le développement à la hâte pour respecter les dates limites et la correction rapide des bugs peuvent entraîner des régressions dans le système[3].
- Les contraintes de temps obligent les développeurs à bâcler les classes "middle-level" qui aident grandement à la maintenance du projet[2].
- La mauvaise estimation des ressources nécessaires à la réalisation d'un projet[2].
- Exemple : temps, personnel, ...
- Les refactorisations du projet trop peu effectuées dues à la sous-estimation du caractère inévitable de l'érosion architecturale[2]..
- Il est nécessaire à un certain moment d'allouer du temps et des ressources afin d'inverser la dégénération de l'architecture. Cependant, les développeurs peinent souvent à trouver des arguments en faveur de la réalisation de ce processus étant donné que celle-ci n'apportera rien à l'utilisateur final puisqu'il ne verra rien de tout cela. Il existe donc une mesure définie aidant à mieux quantifier le besoin nécessaire d'arrêter la dégénération logicielle[9].
- L'organisation d'un projet est aussi parfois l'une des causes de son érosion logicielle. En effet, un environnement organisationnel malsain entraîne un mauvais travail[3].
- Le turnover du personnel induit une mauvaise compréhensibilité de l'architecture et son implémentation[3].
- De même, la distance géographique empêche une bonne intégration du système[3].
Conséquences
Il est aussi important de comprendre les enjeux derrière ce contrôle de l'érosion logicielle pour en comprendre la nécessité.
Systèmes plus difficiles à maintenir
Les systèmes érodés sont difficiles à maintenir. Localiser un bug ou tester des parties de code, à l'aide de tests unitaires par exemple, est beaucoup plus difficile et prend plus de temps à réaliser sur un logiciel avec une forte érosion.
Systèmes plus chers à maintenir
Qui dit « temps » dit « argent », et si les développeurs passent plus de temps à modifier l'application ou corriger ses bugs, il va de soi que cela revient plus cher à sa maintenance.
Logiciel non économique
Un logiciel non économique est un logiciel qui coûte plus cher à maintenir qu'à recoder de zéro. C'est le pire scénario d'érosion qui puisse arriver.
Solutions
Les solutions apportées pour contrôler l'érosion de l'architecture logicielle sont diverses et peuvent se compléter entre elles. Aucune approche utilisée seule ne fournit une solution entièrement efficace pour contrôler l'érosion[10].
Minimiser : limiter l'impact de l'érosion
Il est possible de limiter l'impact de l'érosion à l'aide de quelques méthodes. Ces solutions peuvent se diviser en trois catégories.
Processus pour la conformité avec l'architecture
Cette catégorie comprend un ensemble de processus qui permettent d'assurer la conformité avec une architecture pendant les phases de développement et de maintenance.
Techniques de documentation
La documentation sur le design de l'architecture, sur les raisonnements et les décisions qui ont mené à cette architecture se doit d'être assez détaillée pour comprendre complètement les besoins mais doit en plus avoir un certain niveau d'abstraction et ne doit pas trop rentrer dans les détails pour des soucis de compréhension par les développeurs. L'une de ces techniques est le "4+1 view model (en)". Les techniques informelles qui manquent de définition précise et qui amènent à une mauvaise compréhension, donc à l'érosion sont fortement répandues. Celles-ci peuvent être palliée par l'utilisation d'un ADL (Architecture description language (en)) qui permet de fournir une certaine formalité[11].
Exemples d'ADL : Acme (en), Darwin (en), ArchJava, Fractal, xADL, Rapide[11].
Il existe un standard IEEE 1471 (en) qui définit un ensemble de lignes directrices sur comment une architecture logicielle devrait être documentée[11].
Les techniques de documentation sur les décisions architecturales ne sont pas très répandues. C'est pour cela qu'il existe également des systèmes qui permettent de retracer les raisonnements qui ont abouti à des décisions sur une architecture grâce à l'analyse de patterns particuliers trouvés dans cette architecture[11].
Méthodes d'analyse de l'architecture
Il existe plusieurs méthodes dont le but est de localiser les points faibles ou sensibles d'une architecture, d'où l'érosion peut démarrer. La SAAM (en) a vu le jour au milieu des années 1990 et a été la première méthode d'analyse de l'architecture à être documentée. Elle a servi de précurseur à la ATAM (en). Enfin, il existe également une technique qui utilise les réseaux de Petri colorés afin de valider les attributs de qualités clés d'une architecture[11].
Surveillance sur la conformité avec l'architecture
Deux techniques fournissent les moyens de savoir et de contrôler la conformité d'une implémentation avec son architecture originelle tout au long des phases de développement de maintenance :
- Technique des modèles réflexifs : cette techniques consiste à choisir un modèle d'un système, d'en déduire une hypothétique implémentation et de le comparer avec le modèle réellement implémenté. Cela permet de localiser les points de dérivation ou d'omissions par rapport à l'architecture de base[11].
- Technique des modèles réflexifs inversés : le modèle est considéré comme acquis et non hypothétique. Le modèle réellement implémenté est comparé à ce modèle acquis de manière répétitive. Cette technique est donc plus utilisée pour vérifier la conformité avec l'architecture voulue, et non pour retrouver l'architecture voulue, comme c'est le cas pour la technique non inversée[11].
Analyse des dépendances
La source la plus commune d'érosion d'une architecture provient de dépendances incorrectes entre les entités de cette architecture. Plusieurs outils commerciaux permettent de localiser ces points d'érosion potentiels grâce à une visualisation des dépendances. En voici des exemples : SonarJ (en), Structure101, Klocwork Architect, Coverity (en) et JDepend[12].
Gestion de l'évolution de l'architecture
L'évolution d'une architecture peut être contrôlée grâce à des outils de gestion de configuration, dits SCM (Sofware management configuration). Ceux-ci regroupent également les logiciels de gestion de versions qui sont généralement plus connus. Concrètement, les outils SCM se chargent de minimiser l'érosion d'une architecture logicielle en gérant la coévolution continuelle de l'architecture et de son implémentation[13].
Il existe deux sous-catégories d'outils dans ce domaine :
SCM centré sur l'architecture
Le logiciel de gestion de configuration joue le rôle central en définissant l'architecture logicielle en son sein[13].
Exemples :
- ArchEvol permet de surveiller l'évolution parallèle des spécifications de l'architecture et de son implémentation, et ainsi de faciliter la collaboration entre les architectes et les développeurs[13].
- ArchAngel surveille la conformité du code source avec l'architecture au moyen de modèles de dépendances définis par un architecte. Il se charge de "parser" le code source et d'identifier les relations entre les différents packages. Il compare ensuite ces relations avec celles prévues par l'architecte pour identifier les violations de dépendances[13].
Architecture centrée sur SCM
Le logiciel de gestion de configuration devient une partie intégrante de l'architecture. Des exemples d'outils sont Mae et Molhado[13].
Mise en application de conceptions d'architectures
Cette mise en vigueur regroupe un ensemble d'outils et de méthodes qui permettent la transformation de modèles d'architecture en implémentations organisées. Cela permet de minimiser fortement l'érosion logicielle si cette mise en vigueur est appliquée correctement[14]. L'ensemble de ces méthodes sont repris dans les trois catégories suivantes :
Génération de code
Les outils de génération de code permettent de générer du code source à partir de la définition d'une architecture. Ces outils ne fournissent généralement pas un code source utile sans l'intervention ultérieure d'un programmeur. Il est cependant possible, en théorie, de générer des implémentations complètes à partir de modèles UML. Il existe quelques (ADL (en)), tel que l'environnement ArchStudio, qui permettent la génération de code à partir des spécifications architecturales définies[14].
Patterns d'architecture
Les patterns d'architecture sont similaires aux patterns de conception dans le sens où ils fournissent des solutions bien établies, testées et documentées à des problèmes récurrents dans la conception d'une architecture logicielle. Il est commun également de garder une trace des décisions sur l'architecture ainsi que le raisonnement qui a mené à cette décision. Les points positifs de cette méthode sont multiples[14] :
- S'ils sont correctement appliqués, ces patterns d'architecture réduisent fortement la possibilité de violer des principes de conception.
- L'existence des traces des décisions sur l'architecture permettent de minimiser l'érosion car les programmeurs peuvent ainsi complètement comprendre ces décisions et laisser peu de place à l'interprétation.
Le point négatif principal est le fait que ces règles peuvent facilement être transgressées par les programmeurs qui ne sont pas sensibilisés sur l'importance de celles-ci[14]. Le pattern d'architecture le plus connu est probablement le MVC. Il en existe d'autres tels que le Pipe and Filter (en), ou le Blackboard model[14].
Frameworks d'architecture
Les fraweworks d'architecture fournissent un ensemble de services qui guident les développeurs dans l'implémentation d'une architecture définie. Certains frameworks peuvent détecter quand l'implémentation diverge de l'architecture prévue. Les exemples suivants font partie des frameworks les plus connus : Spring et Struts[15].
Empêcher : éradiquer l'érosion
Cette partie aborde les moyens pour empêcher l'érosion d'un système dès sa création.
Architecture liée au code source
Il existe des mécanismes qui associent ou encapsulent les modèles d'architecture dans le code source et qui supportent le monitoring de la conformité avec l'architecture à l'exécution.
Un exemple est ArchJava, qui permet de coder en Java dans la spécification de l'architecture même. Le fait que l'architecture soit décrite dans le même langage que son implémentation permet de régler le problème principal qui survient dans les autres langages ADL, à savoir l'incapacité à assurer complètement l'obéissance des contraintes architecturales et plus particulièrement les communications entre les composants décrits dans l'architecture. Ceci est dû au fait qu'il ne sont pas décrits dans le même langage, et donc ne peuvent exprimer correctement certaines subtilités d'un langage particulier. Ils s'en remettent alors à la bonne volonté des développeurs de suivre des lignes directrices afin de respecter les communications entre les composants de l'architecture[16].
Il existe également la plateforme Archium qui est une extension à Java et un framework qui est chargé de vérifier les propriétés de l'architecture à l'exécution[16].
Enfin, ArchWare est lui aussi une plateforme mais qui vise essentiellement les architectures dynamiques. Pour cela, il fusionne complètement le modèle de l'architecture et son implémentation, ce qui permet une coévolution complètement simultanée[16].
Auto-adaptation
Cette technique permet aux systèmes de se reconfigurer afin de s'aligner sur leur architecture après qu'un changement dans l'implémentation ait été effectué. L'hypothèse établissant que l'être humain et sa tendance à ne pas respecter les lignes de directrices définies dans une architecture lorsqu'il doit réaliser un changement, est à l'origine des systèmes auto-adaptatifs. Typiquement, ces systèmes fonctionnent à l'aide de trois acteurs : des capteurs qui surveillent et capturent les changements survenus, des comparateurs qui comparent ces changements avec les règles définies au départ, et des actionneurs qui se chargent d'effectuer les changements nécessaires au système[17].
Un exemple de système auto-adaptatif est Rainbow.
Réparer : réconcilier l'implémentation avec l'architecture
Il est nécessaire de planifier correctement le processus de réparation pour éliminer au mieux l'érosion. Ce processus ne peut fonctionner que si le système n'est pas trop détérioré. Il est donc conseillé de combiner les techniques de réparation avec d'autres mécanismes de prévention de l'érosion décrits ci-dessus[17].
Le processus typique de réparation d'un logiciel érodé se fait en trois phases[18]:
- Il faut d'abord récupérer l'architecture qui a été implémentée.
- Réparer l'architecture récupérée en se conformant à l'architecture voulue au départ,
- Réconcilier cette nouvelle architecture réparée avec l'implémentation.
Il est nécessaire que ces trois phases soient fortement liées entre elles pour réparer efficacement un logiciel érodé[18].
Récupération de l'architecture
Cette phase consiste à extraire l'architecture implémentée à partir du code source. Il existe un nombre important d'outils pour effectuer cette tâche. Une grande partie d'entre eux utilisent la technique des modèles réflexifs. Ces modèles sont souvent agrémentés d'une technique de regroupement qui consiste à rassembler les entités d'un logiciel entre elles pour former un niveau d'abstraction supplémentaire. En plus de cette technique de regroupement, les modèles peuvent également comporter une fonctionnalité de filtrage qui permet de supprimer les entités non nécessaires à ce niveau d'abstraction[18].
Exemples d'outils et méthodes : Bunch, Architecture Reconstruction Method (ADM), Architecture Query Language (AQL).
Découverte de l'architecture
Dans le cas où il n'existe pas d'architecture de départ, la phase de découverte d'une architecture consiste en des techniques qui permettent de déduire une architecture à partir des propriétés d'un système et de ses cas d'utilisation. Cette architecture prévue au départ est absolument nécessaire pour réparer correctement un système érodé[19].
Réconciliation de l'architecture
Cela désigne le processus durant lequel l'architecture implémentée est rendue conforme à l'architecture voulue au départ qui a été obtenue soit à la suite de la méthode de récupération soit à la suite de la méthode de découverte décrite précédemment. Le refactoring est la solution la plus utilisée pour effectuer cette réconciliation[19].
Les deux grandes étapes d'un processus de refactoring consistent premièrement à localiser dans le code source des décisions d'implémentation qui représentent des violations à l'architecture décrite au départ puis, après avoir localiser ces violations dans le code, les refactoriser pour rester en concordance avec cette architecture[20].
Refactorisation du code à l'aide des outils d'un IDE
Pour éviter d'avoir un écart trop grand entre le logiciel et son architecture initialement prévue à mesure que le développement d'un logiciel avance, il est important de faire régulièrement de la refactorisation. La plupart des IDE contiennent des outils d'aide à la refactorisation. Mais ce procédé est souvent réalisé de manière peu organisée, sans tenir compte de l'architecture[20].
Langages de contrainte d'architecture
Pour localiser dans le code source des décisions d'implémentation qui représentent des violations de l'architecture décrite au départ, il existe des langages spécifiques ou des outils d'analyses qui permettent de localiser ces violations dans un code source, comme par exemple le langage DCL[20].
L'outil appelé SAVE (Software Architecture Visualization and Evaluation) permet également d'effectuer la connexion nécessaire entre le développeur et l'architecture d'un logiciel. En définissant une architecture visée et en spécifiant l'architecture actuelle, il fournit au développeur un outil visuel lui montrant les violations commises dans l'implémentation du logiciel par rapport à l'architecture visée[21].
Lignes de conduite pour le refactoring[20]
Des lignes de conduites fournies automatiquement permettraient d'aider le développeur et de lui fournir la méthode adéquate à appeler en fonction du contexte dans lequel il se trouve.
Prenons par exemple le cas de refactorisation où il faut remplacer l'appel d'un constructeur d'une classe par l'appel à une méthode d'une factory appropriée. Le problème du développeur dans ce cas peut être le fait qu'il n'ait pas assez de connaissance du système pour savoir quelle méthode de quelle factory appeler à la place. Il lui serait donc automatiquement recommandé quelle méthode utiliser.
Ce système a pour but de fournir des recommandations pour supprimer les violations détectées par le langage DCL. Le processus est le suivant : on utilise le code source et les contraintes de dépendances fournies par l'architecte logiciel pour produire les violations détectées par le langage DCL, puis on utilise ce résultat pour fournir des recommandations adaptées.
Ce procédé contient une vingtaine de recommandations résultantes de violations de contraintes cannot du langage DCL. Ces recommandations sont également valables pour les contraintes de type only can et can only car il est possible de les exprimer sous forme de cannot au moyen de diverses opérations logiques. Les recommandations sont classées en fonction de leur importance. On retrouve en haut du classement la recommandation dictant l'utilisation d'une factory à la place du constructeur d'une classe si cette classe se situe dans un module différent de celui où on l'appelle. La recommandation permet même de générer une factory dans le cas où aucune autre factory ne correspond aux spécificités demandées. D'autres exemples de recommandations disent que le type d'une variable doit être la plus abstraite possible ou bien qu'il faut éviter de répandre trop loin la gestion d'une exception afin de diminuer le couplage.
Ce système est néanmoins récent, et nécessite d'être testé sur des projets plus importants avant d'être utilisé en environnement de production.
Comparatif des différentes solutions
Solutions | Avantages | Inconvénients |
---|---|---|
Processus pour la conformité à l'architecture |
|
|
Gestion de l'évolution de l'architecture |
|
|
Mise en application de conceptions d'architectures |
|
|
Architecture liée au code source |
|
|
Auto-adaptation |
|
|
Processus de réparation |
|
|
Conclusion
Il est clairement établi partout dans la littérature que l'érosion de l'architecture logicielle est un problème réel, récurrent, et surtout, inévitable. Les études menées autour de l'érosion logicielle partent toutes de ce postulat et cherchent donc à comprendre les raisons derrière ce caractère inévitable et établissent des solutions pour réduire tant bien que mal l'impact que peut avoir l'érosion sur les systèmes informatiques d'aujourd'hui. L'objectif est donc de repousser au maximum le moment critique où un logiciel est jugé plus coûteux à maintenir qu'à redévelopper de zéro.
Pour cela, diverses solutions ont été présentées mais aucune d'entre elles ne permet d'éliminer complètement l'érosion. Une potentielle solution a cependant été émise. Ce serait une “révolution” similaire à celle que fut la création de l'orienté-objet, successeur de la programmation procédurale et qui consisterait en de nouveaux modèles de programmation capables de spécifier et de se tenir à des propriétés architecturales[23].
Références
- Riaz 2009
- Lavallée 2011, p. 69
- Riaz 2009, p. 122
- Terra 2012, p. 335
- Lavallée 2011, p. 62
- Van Gurp 2002, p. 105
- Van Gurp 2002, p. 106
- Van Gurp 2002, p. 106-107
- Lindvall 2002, p. 77–86
- De Silva 2012, p. 132
- De Silva 2012, p. 136
- De Silva 2012, p. 137
- De Silva 2012, p. 138
- De Silva 2012, p. 139
- De Silva 2012, p. 140
- De Silva 2012, p. 141
- De Silva 2012, p. 142
- De Silva 2012, p. 143
- De Silva 2012, p. 144
- Terra 2012
- Lindvall 2008
- De Silva 2012, p. 147-148
- De Silva 2012, p. 149
Bibliographie
- (en) Mehwish Riaz, Muhammad Sulayman et Husnain Naqvi, « Architectural Decay during Continuous Software Evolution and Impact of ‘Design for Change’ on Software Architecture », Proceedings of the International Conference on Advanced Software Engineering and Its Applications. Springer, vol. 59, , p. 119–126 (ISBN 978-3-642-10619-4, ISSN 1865-0929, DOI 10.1007/978-3-642-10619-4_15)
- (en) Mathieu Lavallée et Pierre N. Robillard, « Causes of premature aging during software development », Proceedings of the 12th International Workshop on Principles of Software Evolution and the 7th annual ERCIM Workshop on Software Evolution, , p. 61-70 (ISBN 978-1-4503-0848-9, DOI 10.1145/2024445.2024458)
- (en) Ricardo Terra, Marco Tulio Valente, Krzysztof Czarnecki et Roberto S. Bigonha, « Recommending Refactorings to Reverse Software Architecture Erosion », 16th European Conference on Software Maintenance and Reengineering, , p. 335-340 (ISBN 978-0-7695-4666-7, DOI 10.1109/CSMR.2012.40)
- (en) Jilles Van Gurp et Jan Bosch, « Design erosion: problems and causes », Journal of Systems and Software, vol. 61, no 2, , p. 105–119 (ISSN 0164-1212, DOI 10.1016/S0164-1212(01)00152-2)
- (en) Mikael Lindvall, Roseanne Tesoriero Tvedt et Patricia Costa, « Avoiding architectural degeneration: An evaluation process for software architecture », Proceedings of the 8th International Symposium on Software Metrics. IEEE, , p. 77–86 (ISBN 0-7695-1339-5, DOI 10.1109/METRIC.2002.1011327)
- (en) Mikael Lindvall et Dirk Muthig, « Bridging the software architecture gap », Computer, vol. 41, no 6, , p. 98-101 (ISSN 0018-9162, DOI 10.1109/MC.2008.176)
- (en) Lakshitha De Silva et Dharini Balasubramaniam, « Controlling software architecture erosion: A survey », Journal of Systems and Software, vol. 85, no 1, , p. 132–151 (ISSN 0164-1212, DOI 10.1016/j.jss.2011.07.036)
- (en) Jonathan Aldrich, Craig Chambers et David Notkin, « ArchJava: connecting software architecture to implementation », Proceedings of the 24th International Conference on Software Engineering, , p. 187–197 (ISBN 1-58113-472-X, DOI 10.1145/581339.581365)