# Dégradation logicielle

En informatique, la dégradation logicielle, nommée également érosion logicielle et érosion de l'architecture logicielle ou encore vieillissement logiciel — terme également utilisé pour faire allusion aux défaillances rencontrées dans un logiciel au fil du temps —, est le déséquilibre ou l'écart entre l'architecture logicielle 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.
L'architecture logicielle permet de décrire comment doit être conçu le logiciel pour répondre aux spécifications de celui-ci. L'implémentation logicielle doit correspondre au modèle d'architecture produit lors de la phase de conception. Dans la pratique, il n'est pas toujours évident de respecter cette règle. Les origines des décalages sont multiples : l'évolution logicielle, les erreurs d'implémentations, les contradictions dans l'architecture envisagée qui ne pouvaient être prévues avant le développement, etc. Il est possible de faire face à cette problématique en appliquant des concepts du génie logiciel et en utilisant divers moyens pour trouver où se situent ces points d'érosion et comment les contrer.

## Principe de base

Pour comprendre l'importance de l'architecture, il est nécessaire de connaître les différentes étapes à suivre lors de la réalisation d'un projet. Tout projet est issu d'un besoin. Pour satisfaire les futurs utilisateurs, il est nécessaire d'étudier leurs besoins avant de développer une solution. Grâce à cela, il sera possible de définir une architecture logicielle adaptée afin d'obtenir un résultat proche de celui escompté. Avec une architecture bien définie, l'implémentation de la solution sera facilitée et correspondra mieux aux attentes du client s'il n'y a pas de divergences entre les deux.

## Importance de l'architecture logicielle

L'architecture logicielle permet de réaliser entièrement le logiciel sous une forme théorique avant de le réaliser de manière pratique. Ceci permet de prévoir les contraintes techniques, d'envisager les évolutions de manière adaptée et de garantir la qualité du logiciel. Par conséquent, les coûts sont réduits et les logiciels sont sensiblement de meilleures qualités. L'architecture logicielle joue un rôle important dans les six aspects, ci-dessous, du développement logiciel :
* Elle simplifie notre capacité à comprendre les gros systèmes en les représentant par un niveau d'abstraction dans lequel une architecture de système haut niveau peut facilement être perçue.
* Elle favorise la réutilisation à multiples niveaux, des bibliothèques de composants aux framework.
* Elle permet la construction d'un plan pour le développement en indiquant les dépendances entre les différents composants.
* Elle facilite la mise en place des évolutions.
* Elle offre des nouvelles possibilités pour l'analyse telles que la vérification de la cohérence du système, la conformité des contraintes imposées par le style d'architecture, etc.
* Elle permet la bonne gestion de projets.

## Liaisons entre architectures et implémentations

Pour faire la liaison entre l'architecture et l'implémentation, il est nécessaire de définir un ensemble de règles. Celles-ci permettront de détecter lorsque l'implémentation sera en train de dévier de l'architecture.
Il est possible de distinguer deux types de règles: les règles structurelles et les règles d’interactions. Les règles structurelles concernent l'existence des mêmes entités et les relations qui les unissent tandis que les règles d’interactions concernent essentiellement la présence des appels de méthode dans le même ordre.
Avec cet ensemble de règles, lors de l'analyse il y a trois types de résultats possibles :
* Convergence : La relation implémentée correspond à celle définie dans l'architecture.
* Divergence : La relation implémentée diffère de celle définie dans l'architecture.
* Absence : La relation est présente dans l'architecture mais n'est pas implémentée.
Il suffit maintenant de traiter chaque divergence et absence une par une. La pratique la plus courante est de modifier le code pour qu'il corresponde à l'architecture. Néanmoins, il est possible de devoir modifier l'architecture du projet à cause de difficultés techniques lors du développement.

## Causes de dégradations logicielles

Les principales causes des dégradations logicielles sont les modifications apportées au code, à la documentation dans le non-respect des règles architecturales.

### Changement des besoins utilisateurs

L'une des principales causes des dégradations dans les architectures est l'évolution du besoin client. Le client n'est pas toujours conscient de ce qu'il attend jusqu'à ce qu'il ait une première version du produit. Il essaye alors d'apporter des modifications aux spécifications. Ce problème est également constaté lorsque les spécifications ne sont pas assez précises. Ces deux points définissent les deux principaux types de vieillissement logiciels : les défaillances causées par les modifications des propriétaires du produit à la suite des évolutions du besoin, et le résultat des modifications effectuées à la suite d'incompréhensions des deux parties (client/concepteur du logiciel) lors de la conception et du développement du produit.

### Évolution du matériel

Une autre cause de dégradations de logicielles est le matériel auquel se rattache le logiciel. Les architectures logicielles sont conçues dans le respect du matériel dont le logiciel dépend. Au fil du temps, le matériel est susceptible de changer et cela peut provoquer une instabilité et compromettre l'architecture prévue.

### Allocation mémoire

Les modifications apportées au logiciel durant sa durée de vie entraînent un problème d'allocation mémoire. En effet, plus il y a des changements dans le code, plus la taille du programme grandit, et plus la taille du programme grandit plus la mémoire demandée au système est conséquente. Il est difficile de prédéfinir la mémoire à allouer.

### Problèmes de connaissances
#### 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.
* Mauvaise appréciation de l'impact que peut avoir la non-utilisation d'un pattern.
* 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.
* Une documentation inexistante ou de mauvaise qualité entraînent un manque de compréhensibilité pour les personnes ne connaissant pas bien le projet.
* 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.
* 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.
** Par exemple, il se peut qu'il crée un objet directement alors qu'il devrait utiliser une factory prévue à cet effet.

#### Mauvaise utilisation

* L'abus du pattern Singleton crée un couplage extrêmement fort qui empêche d'être modifié facilement.
* Les développeurs sont parfois dans l'incapacité à adapter les patterns aux besoins du projet.
* Si l'on code avec une modularité faible ou inexistante, on risque d'empêcher les modifications possibles par la suite.
* Le code smell désigne plus ou moins les antipatterns et indique la présence de problèmes de conception.
** On peut retrouver comme exemple de code smell la god class qui désigne une classe à tout faire qui contient une grande partie du code d'un logiciel,
** ou encore spaghetti code qui représente du code fortement couplé et « emmêlé » comme son nom le suggère
* 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.

### Problèmes de réalisation
#### 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$^,$.
* Les suppositions erronées des développeurs dues au manque d'informations explicites sur l'architecture sont aussi source d'érosion.

#### Problèmes de continuité

* Les décisions architecturales oubliées ou non utilisées par les développeurs.
* 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.
* 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.
* 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.
* 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.

#### Problèmes de langage

* Les spécifications présentes dans l'architecture sont incompatibles avec la capacité réelle à exécuter ces spécifications dans l'environnement choisi.
** Par exemple, le langage choisi pour développer ne permet pas certaines choses prévues dans l'architecture.

### Problèmes de gestion
#### 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. 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. 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.
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.
* Si l'on prête peu d'attention à la conception de l'application lors de changements apportés à celle-ci.
* L'accumulation des décisions de conception différentes peuvent aussi la rendre difficile et chère à maintenir.
* La mauvaise compréhension de l'architecture de la part des développeurs est une cause principale de l'érosion d'un logiciel.
** 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.
* 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.
* Des problèmes de communication dans l'équipe peuvent engendrer du code redondant.
* La mauvaise planification ou estimation de l'impact d'un changement de l'architecture, peut engendrer des problèmes d'érosion.

#### 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.
* 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.
** Les contraintes de temps obligent les développeurs à bâcler les classes "middle-level" qui aident grandement à la maintenance du projet.
* La mauvaise estimation des ressources nécessaires à la réalisation d'un projet.
** Exemple : temps, personnel, ...
* Les refactorisations du projet trop peu effectuées dues à la sous-estimation du caractère inévitable de l'érosion architecturale..
** 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.
* 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.
** Le turnover du personnel induit une mauvaise compréhensibilité de l'architecture et son implémentation.
** De même, la distance géographique empêche une bonne intégration du système.

## 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

Pour faire face aux dégradations logicielles, il existe plusieurs solutions permettant de ralentir le vieillissement mais également de garantir la qualité tout en essayant de garder un équilibre entre l'architecture et l'implémentation. 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.
Certaines technologies permettent de faire face aux dégradations. Cependant il existe des éléments pratiques à mettre en place pour conserver la qualité des logiciels.

### Mise en place d'architectures adaptées

Le but de la phase de conception est de créer un design capable d'accepter des demandes de changements futurs.
Ceci est en contradiction avec l'itérative nature de nombreuses méthodes de développement (extrême pro- programming, le prototypage rapide, etc.) car ces méthodologies incorporent généralement de nouvelles exigences qui peuvent avoir un impact architectural, au cours du développement alors qu'une bonne conception nécessite des connaissances au sujet de ces exigences à l'avance.
Il reste donc important de prévoir des architectures s'adaptant aux changements mais également compatibles avec les méthodologies de développement utilisées. Ainsi, il semble possible de parler d'architectures agiles pour des développements agiles et l'appliquer pour mieux garantir la durée de vie du logiciel.

### Équilibre entre architecture, code, documentation lors des évolutions

Lorsqu'il y a des modifications à apporter au logiciel, il semble plus simple (moins cher) d'appliquer ces modifications dans le code. Pour pouvoir retarder le vieillissement, il est primordial de maintenir l'architecture et la documentation. En effet, il faut garantir à chaque changement dans le code que les règles d'architectures sont respectées et la documentation mise à jour. Ceci permet d'éviter les décalages pouvant subvenir entre l'implémentation et l'architecture logicielle.

### Maintenance

Une bonne maintenance logicielle permet d'allonger la durée de vie du logiciel. Les processus de maintenances se basent généralement sur l'amélioration itérative ou encore sur le modèle de réutilisation complète. La réutilisation permet de gagner du temps, réduire le coût mais peut s'avérer dangereux. Il est donc important de :
* Identifier les différents composants logiciels
* Analyser les composants (par rapport aux besoins du logiciel)
* Adapter les composants au contexte
* Effectuer l'intégration
Il est important lors de la maintenance, de respecter les règles architecturales, surtout, lors de l'intégration de nouveaux composants.

### 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é.
Exemples d'ADL : Acme (en), Darwin (en), ArchJava, Fractal, xADL, Rapide.
Il existe un standard IEEE 1471 (en) qui définit un ensemble de lignes directrices sur la manière dont une architecture logicielle devrait être documentée.
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.

##### 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.

##### 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.
* 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.

##### 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.

#### 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.
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.
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.
* 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.

##### 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.

#### 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. 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.

##### 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 :
* 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. 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.

##### 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.

### 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.
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.
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.

#### 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.
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.
Le processus typique de réparation d'un logiciel érodé se fait en trois phases:
* 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é.

#### 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.
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é.

#### 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.
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 localisé ces violations dans le code, les refactoriser pour rester en concordance avec cette architecture.

##### 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.

##### 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.
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.

##### Lignes de conduite pour le refactoring

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

Avantages et inconvénients des solutions contre l'érosion :
| Solutions | Avantages | Inconvénients |
| Processus pour la conformité à l'architecture | Efficace pour réduire l'érosion dès le début du cycle de vie d'un logiciel S'intègre bien avec les pratiques de gestion de projet | Sujette à la négligence humaine Manque de rigueur pendant la phase de maintenance |
| Gestion de l'évolution de l'architecture | S'assure que l'architecture et l'implémentation sont en concordance l'un avec l'autre tout en leur permettant d'évoluer indépendamment | Nécessite des ADL standardisés et des outils SCM qui intègrent ces ADL |
| Mise en application de conceptions d'architectures | Simple et pratique pour la plupart des applications Les Patterns et frameworks utilisent les meilleurs pratiques de conception connues | Pas de mécanismes permettant d'empêcher les violations des propriétés de l'architecture dans des systèmes en évolution |
| Architecture liée au code source | Assure une association continue entre l'architecture et son implémentation | L'architecture et l'implémentation forment généralement une seule et unique entité |
| Auto-adaptation | Permet à l'implémentation de se reconfigurer toute seule pour se conformer à son architecture | Suppose que l'architecture reste relativement constante tout au long de l'évolution du système |
| Processus de réparation | Certaines techniques ont été bien adoptée dans l'industrie logicielle comme étant des solutions viables pour étendre la durée de vie d'un logiciel Peut être utilisé en plus des techniques de prévention de l'érosion | L'architecture prévue au départ n'est pas toujours récupérable Aucune des techniques présentées sont capables d'extraire les raisonnements derrière les décisions sur l'architecture |

## Bonnes pratiques

Il existe des éléments pratiques, ci-dessous, permettant de garantir un équilibre entre l'architecture logicielle et son implémentation.
* Ne pas attendre la fin du développement avant d'effectuer des analyses de divergences entre l'architecture et le code car le refactoring sera plus complexe.
* Lors de la conception, prévoir une architecture décrivant le logiciel répondant aux besoins clients tout en laissant les possibilités de l'étendre; et lors de l'implémentation garder également ses possibilités tout en respectant les règles imposées par l'architecture.
* Maintenir la cohérence entre le code et la documentation.
* Trouver le bon compromis entre les stratégies d'efforts: minimal et optimal.
* S'efforcer de modulariser.
* Élaborer des architectures claires et expressives.
* Prévoir des architectures correspondantes aux méthodologies utilisées.
* Réutiliser ce qui est réutilisable, si et seulement si cela répond aux besoins.
* Utiliser le concept PDCA(Plan, Do, Check, Act).

## Technologies
### Card

Card a été développé par Claire Dimech et Dharini Balasubramaniam de l'École d'informatique de l'Université de St Andrews.
Card est un outil de vérification de conformité entre architecture et implémentation, il est intégré sous forme de plugin dans Eclipse. La vérification se fait statiquement entre une description d'architecture en UML et son implémentation en Java. Ce framework contient deux modules de prétraitement : l'un pour les diagrammes UML 2.0 et l'autre pour le code source Java. Card se charge de rechercher les fichiers UML et Java dans l'arborescence du projet Eclipse, ensuite utilise ses préprocesseurs pour l'extraction des propriétés architecturales. Ces propriétés sont stockées dans des structures de données adaptées pour l'analyse de conformité à effectuer.
Card se base sur le concept "Maître Esclave", architecture prescriptive (Maître) et architecture descriptive (Esclave), sur lesquelles se réfèrent les règles. Card permet un paramétrage par utilisateur sur trois niveaux d'exigences (High, Medium, Low), procède à une vérification des structures de données et affiche les violations en les renvoyant vers l'esclave. Les développeurs peuvent vérifier la conformité entre leur code et le model en mode static (offline) ou dynamiquement (ils peuvent le choisir dans les préférences).
Card a été testé sur de nombreux projets et n'a jamais fait ressortir de fausses violations ni d'oublis. Cependant, il n'y a pas de preuves formelles.

### SAVE

SAVE a été développé conjointement par Fraunhofer IESE (Institute for Experimental Software Engineering, Institut de recherche en ingénierie logicielle en Français) à Kaiserslautern en Allemagne et Fraunhofer Center Maryland (Center for Experimental Software Engineering, Centre de recherche en ingénierie logicielle en Français) à Maryland aux États-Unis.
SAVE est un outil de développement qui montre les convergences et divergences entre deux entités d'un projet de manière schématique. Cet outil est disponible sous la forme de plugin Eclipse et est donc complètement intégré à celui-ci. Il est utilisable sur les projets développés en Java, C/C++, et Delphi.
La version statique a été testé dans l'entreprise TESTO pendant une période de trois ans pour développer une douzaine de produits, et l'étude présente des résultats concluants.
Il existe également un plugin (LiFe) permettant d'effectuer la vérification au fur et à mesure que le code de l'application est écrit. Ce plugin a également été testé sur une promo d'étudiants où certains groupes avaient le plugin SAVE Life et le reste ne disposaient d'aucun outil de vérification. L'étude montre qu'après quelques semaines, les groupes d'étudiants qui développaient avec le plugin faisaient beaucoup moins d'erreurs d'implémentations. Finalement, le projet était plus proche du résultat attendu que celui des autres groupes.

### ArchJava

ArchJava est l'une des premières solutions développés afin de contrôler la cohésion entre l'architecture et l'implémentation. Cette solution a vu le jour en 2002 aux États-Unis.
ArchJava est un langage étendu de Java permettant la mise en place de contraintes architecturales lors de l'implémentation. Ces contraintes sont spécifiées explicitement dans le code en ajoutant des entités nommées port dans les classes. Ces ports permettent de définir quels objets peuvent communiquer entre eux et quelles sont les méthodes autorisées sur ce port.
Une étude a été menée pour vérifier les points suivants :
* Peut-on définir l'architecture d'un projet à grande échelle avec ArchJava ?
* Quel est le coup d'un refactoring d'un projet Java vers ArchJava ?
* ArchJava permet-il l'évolution logicielle ?
L'ensemble des points ont été vérifiés avec succès, et la compréhension du code du projet testé a été fortement améliorée car les communications ont été simplifiées.

## 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.