Vues et transformations de programmes pour la modularité des évolutions

Problème de la tyrannie de la décomposition dominante

Dans l’industrie environ 80% du coût de développement des logiciels est dépensé dans leur évolution [Erl00]. En effet, les grands projets logiciels ont une longue durée de vie et sont donc amenés à être continuellement adaptés. Ceci est formalisé par des lois d’évolution [BL71, Leh96], notamment :

Croissance continue. Le nombre de fonctionnalités du logiciel est toujours en croissance afin de garantir la satisfaction des besoins des utilisateurs.

Continuité des changements. Un logiciel doit être sans cesse adapté à son contexte d’application (qui change continument) pour rester satisfaisant aux besoins des utilisateurs.

Diminution de la qualité perçue. L’incertitude et les imprévus du monde réel peuvent diminuer la qualité perçue des logiciels. Ceci est dû au fait qu’un utilisateur peut voir d’autres logiciels qui sont plus satisfaisants que le sien. De ce fait l’utilisateur peut considérer son logiciel comme moins satisfaisant.

La facilité d’évolution des logiciels dépend de la façon dont ce logiciel est structuré. Ainsi, un programme écrit de manière monolithique sera plus difficile à faire évoluer qu’un programme qui est décomposé en des parties relativement indépendantes appelées modules [Par72]. Chaque module rassemble des éléments qui sont dépendants et communique avec les autres modules à travers une interface. Ceci permet d’opérer certaines maintenances de manière modulaires, c’est à dire en se limitant à la modification d’un module donné. La modularité facilite donc la maintenance et permet ainsi de réduire le coût de maintenance. La plupart des langages de programmation fournissent des supports à la modularité via des constructions syntaxiques et des vérifications statiques ou dynamiques, comme les méthodes/procédures/fonctions, les classes/objets en programmation objet, les bibliothèques, les paquetages, les traits [DNS+06], les mixins [BC90], les foncteurs [Ler00], les composants [Szy02] et les aspects [KH01].

La modularité d’un programme est le résultat des choix architecturaux lors de la conception. Toutefois, une autre loi d’évolution énonce la conséquence des évolutions successives sur la modularité d’un code source :

Augmentation de la complexité. La complexité des logiciels augmente si les actions successives d’évolutions ne sont pas guidées et contrôlées. Ainsi pour conserver les propriétés de modularité de l’architecture initiale, on doit implémenter les corrections tout en respectant cette architecture et non pas juste les implémenter pour faire au plus simple et au plus vite. On parle de dégénérescence de l’architecture.

Dans cet exemple de programme, la décomposition principale correspond au type de données. Dans chaque classe, le code des différentes fonctions est structuré par méthodes, qui sont elles aussi des entités modulaires. On a donc un second degré de décomposition, ou de modularité. Dans cette architecture, la modularité est favorisée sur l’axe de décomposition primaire, et, comme l’a montré l’exemple d’extension des fonctionnalités, défavorisée sur l’axe secondaire. C’est ce qu’on appelle la tyrannie de la décomposition dominante [TOHS99]. Notons qu’il ne suffit pas de choisir une bonne architecture pour se débarrasser de ce problème. Il n’existe pas d’architecture pour laquelle toutes les axes de maintenance seront modulaires. La tyrannie de la décomposition dominante est un problème général qui empêche l’évolution modulaire (extension et maintenance modulaire) sur toutes les préoccupations d’intérêt. Ce problème se manifeste sous une autre forme plus spécifique qui est l’Expression Problem. L’Expression Problem a été formulé la première fois par Wadler [Wad98] : « The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g no casts) » . L’Expression Problem a été étudié dans nombreuses propositions dont la plupart s’appuient sur des spécificités d’un langage particulier [ZO05, LH06, Erl00, Bru03, CMLC06, Gar98, Gar00, KFF98, PJ98, Tor04, ZO01]. Les solutions proposées pour résoudre l’Expression Problem restent toujours dans le contexte de l’extension modulaire (ajout d’un cas dans le type de données ou ajout d’une fonction) et ne traitent pas la maintenance modulaire (modification d’un cas ou d’une fonction) [CD10].

Transformation entre patrons à propriétés complémentaires 

Pour traiter le problème de la tyrannie de la décomposition dominante et l’Expression problem, nous ciblons deux patrons de conceptions à propriétés de modularité duales. Ces deux patrons sont le patron Composite et le patron Visiteur. Le passage entre ces deux patrons permet le changement de la propriété de modularité du programme ce qui lui offre deux axes de décomposition différents. L’automatisation et la réversibilité d’un tel passage permet au développeur de faire deux types de maintenances modulaires sur un même programme. Pour ceci, nous définissons deux algorithmes qui précisent la démarche à suivre pour passer de la structure Composite d’un programme vers sa structure Visiteur et vice-versa.

Formalisation de la transformation 

Les algorithmes que nous définissons pour la transformation réversible entre les patrons Composite et Visiteurs se basent sur la composition des opérations de refactoring. Dans le monde de refactoring, une opération de refactoring doit vérifier certaines préconditions pour qu’elle réussisse. Ceci n’est pas toujours vraie pour une séquence d’opérations de refactoring car les postconditions d’une opération peuvent être contradictoires par rapport aux préconditions de l’opération qui la suive, ce qui cause l’échec de la transformation. Pour éviter ceci, nous utilisons un système de calcul des préconditions de composition des opérations de refactoring. Notre contribution dans ce contexte se manifeste dans la définition de toutes les données nécessaires tels que des prédicats et des règles de calcul pour spécifier chaque opération de refactoring par rapport aux préconditions. Après la définition de ces données, nous les utilisons pour alimenter le système de calcul utilisé et nous générons ensuite la précondition minimale qui permet de garantir statiquement le bon déroulement de notre transformation en plus de sa validation.

Étude de l’impact des variations des patrons Composite et Visiteur sur la transformation

La transformation entre les patrons Composite et Visiteur est appliquée sur une version basique du patron Composite : des méthodes sans paramètres, sans types de retour, avec un seul niveau hiérarchique et avec une classe abstraite et non pas une interface. Après l’identification de quatre variations des deux patrons de conception en question, nous avons déduit que le changement de l’implémentation de ces deux patrons peut rendre cette transformation de base invalide. Les quatre variations que nous étudions sont : méthodes avec paramètres, méthodes avec types de retours différents, méthodes redéfinies aléatoirement sur plusieurs niveaux hiérarchiques et une interface au lieu d’une classe abstraite. Pour rendre la transformation de base valide sur ces quatre variations, nous adaptons les algorithmes de base et nous générons la précondition minimale qui assure la réussite de la transformation sur chaque variation .

Le rapport de stage ou le pfe est un document d’analyse, de synthèse et d’évaluation de votre apprentissage, c’est pour cela chatpfe.com propose le téléchargement des modèles complet de projet de fin d’étude, rapport de stage, mémoire, pfe, thèse, pour connaître la méthodologie à avoir et savoir comment construire les parties d’un projet de fin d’étude.

Table des matières

1 Introduction
1 Problème de la tyrannie de la décomposition dominante
2 Solution proposée
3 Contributions
4 Publications
2 État de l’art : vues et transformations de programmes
1 Solutions à la tyrannie de la décomposition dominante
2 Transformations de programmes
3 Transformation par composition des opérations de refactoring
4 Outillage pour la composition d’opérations de refactoring
5 Bilan
3 Transformation entre un patron Composite et un patron Visiteur
1 Le patron de conception Composite
2 Le patron de conception Visiteur
3 Dualité entre le patron Composite et Visiteur
4 Transformation d’une hiérarchie de classes vers un Visiteur (État de l’art)
5 Transformation réversible entre les patrons Composite et Visiteur
6 Bilan
4 Préconditions
1 Système de calcul des préconditions
2 Prédicats proposés
3 Formules logiques et rétro-descriptions
4 Description des opérations de refactoring de la transformation
5 Validation de la description des opérations de refactoring
6 Précondition pour la transformation entre un Composite et un Visiteur
7 Bilan
5 Variations
1 Méthodes avec paramètres
2 Méthodes avec des types de retour différents
3 Plusieurs niveaux hiérarchiques
4 Composite avec Interface au lieu d’une classe abstraite
5 Bilan
6 Validation par étude de cas réel
1 L’Étude de cas JHotDraw
2 Transformation de JHotDraw
3 Intérêt de la transformation de JHotDraw
4 Bilan
7 Introduction/Suppression du patron Singleton
1 Présentation du patron Singleton
2 La transformation du Singleton dans la littérature
3 Démarche suivie
4 Définitions et formalisation des opérations de refactoring utilisées
5 Transformation proposée du patron Singleton
6 Précondition minimale de la transformation introduction/suppression du Singleton
7 Bilan
8 Conclusion

Lire le rapport complet

Télécharger aussi :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *