Ingénierie des Modèles Transformations de Modèles Eric Cariou Université de Pau et des Pays de l'adour Département Informatique Eric.Cariou@univ-pau.fr 1
Plan Types de transformation Raffinement Projection Exécution de transformations Déclaratif vs impératif Techniques, outils Compilation, graphes, XSLT Standard QVT de l'omg Contrats de transformations de modèles 2
Transformations Une transformation est une opération qui Prend un modèle source en entrée Fournit un modèle cible en sortie Transformation endogène Dans le même espace technologique Les modèles source et cible sont conformes au même méta-modèle Transformation d'un modèle UML en un autre modèle UML Transformation exogène Entre 2 espaces technologique différents Les modèles source et cible sont conformes à des méta-modèles différents Transformation d'un modèle UML en programme Java Transformation d'un fichier XML en schéma de BDD 3
Model Driven Architecture Le MDA définit 2 niveaux de modèles PIM : Platform Independent Model Modèle spécifiant une application indépendamment de la technologie de mise en oeuvre Uniquement spécification de la partie métier d'une application PSM : Platform Specific Model Modèle spécifiant une application après projection sur une plate-forme technologique donnée 4
Model Driven Architecture Relation entre les niveaux de modèles Projection vers une architecture/ technologie génération de code PIM PSM Code Rétro-ingénierie Rétro-ingénierie Raffinement Raffinement 5
Model Driven Architecture Cycle de développement d'un logiciel selon le MDA Cycle en Y Plus complexe en pratique Plutôt un cycle en épi Logique métier (PIM) Code de l'application Technologie/ plate-forme (PDM) 6
Niveaux de Modèles Les niveaux PIM et PSM du MDA peuvent se généraliser dans tout espace technologique Modèles de niveau abstrait : indépendamment d'une plateforme de mise en oeuvre, d'une technologie Modèles de niveau concret : par rapport à une plateforme, technologie de mise en oeuvre Nécessité de modéliser une plateforme de mise en oeuvre PDM : Platform Deployment Model Peu de choses sur ce sujet... 7
Transformations en série Réalisation d'une application Processus basé sur une série de transformations de modèles Exemple 1. Modèle de l'application au niveau abstrait, avec un modèle de composant abstrait : modèle PIM 2. Projection du modèle vers un modèle de composant EJB : modèle PSM 3. Raffinement de ce modèle pour ajouter des détails d'implémentation : modèle PSM 4. Génération du code de l'application modélisée vers la plateforme EJB 8
Autre vision des transformations Depuis longtemps on utilise des processus de développement basé sur les transformations Rien de nouveau Adaptation à un nouveau contexte Exemple : compilation d'un programme C Programme C : modèle abstrait Transformation de ce programme sous une autre forme mais en restant à un niveau abstrait Modélisation, représentation différente du programme C pour le manipuler : transformation en un modèle équivalent Exemple : arbres décorés Génération du code en langage machine Avec optimisation pour une architecture de processeur donnée 9
Outils pour réaliser des transformations Outils de mise en oeuvre Exécution de transformations de modèles Nécessité d'un langage de transformation Qui pourra être défini via un méta-modèle de transformation Les modèles doivent être manipulés, créés et enregistrés Dans un repository (dépôt, référentiel) Doit pouvoir représenter la structure des modéles Via des méta-modèles Qui devront aussi être manipulés via les outils : on les stockera dans un repository Il existe de nombreux outils ou qui sont en cours de développement (industriels et académiques) Notamment plusieurs moteurs/langages de transformation 10
Relation modèles/méta-modèles/repository 11
Familles de techniques de transformations On peut classer en 3 grandes catégories les techniques de transformation Approche déclarative Recherche de certains patrons (d'éléments et de leurs relations) dans le modèle source Chaque patron trouvé est remplacé dans le modèle cible par une nouvelle structure d'élément Ecriture de la transformation «assez» simple mais ne permet pas toujours d'exprimer toutes les transformations facilement Approche impérative Proche des langages de programmation On parcourt le modèle source dans un certain ordre et on génère le modèle cible lors de ce parcours Ecriture transformation plus complexe mais permet de toutes les définir Approche hybride : à la fois déclarative et impérative 12
Techniques de transformations Techniques existantes et abouties Compilation Transformation de graphes Techniques récentes XSLT Transformations de fichiers XML en fichiers XML Approche déclarative Transformation de modèles de type UML ou génération de code à partir de modèles Spécialisation, adaptation des transformations au MDE En plein essor et développement Quelques exemples de langages de transformation Industriels : Langage interne de France Telécom,... Académiques : MTL (Rennes), ATL (Nantes), Mod-Transf (Lille)... 13
Repository Référentiel (repository) pour stocker modèles et méta-modèles Les (méta)modèles sont stockés selon le formalisme de l'outil XML par exemple pour les modèles Et DTD XML pour les méta-modèles Forme de stockage d'un modèle «instance» d'un méta-modèle, via la syntaxe abstraite Stocke la présence d'éléments et leurs relations L'affichage du modèle via une notation graphique est faite par l'agl Les référentiels peuvent être notamment basés sur XML Base de données relationnelle Codage direct dans un langage de programmation 14
Repository en Java pour diag. états public class StateMachine { protected Vector state = new Vector(); protected Vector transition = new Vector(); public void addstate(state s) { state.add(s); } public void addtransition(transition t) { transition.add(t); }... } public class Transition { protected State from, to; protected String event; public Transition(State from, to, String evt) { this.from = from; this.to = to; event = evt; } 15
Repository en Java pour diag. états public class State { protected String name; public State(String name) { this.name = name; } } Définition d'un modèle : instances et liaisons de ces 3 classes... StateMachine sm; State s1,s2;... sm = new StateMachine(); s1 = new State(''Ouvert''); s2 = new State(''Ferme''); sm.addstate(s1); sm.addstate(s2); sm.addtransition(new Transition(State.Initial, s1, '''')); sm.addtransition(new Transition(s1, s2, ''fermer'')); sm.addtransition(new Transition(s2, s1, ''ouvrir'')); 16
Transformations de modèles en Java Transformation de modèles Ajout de méthodes pour lire les éléments du modèle Ex. pour StateMachine : getstates(), gettransitions() Parcours du modèle via ces méthodes Approche impérative Utilisation possible du patron Visiteur Génération d'un nouveau modèle à partir de ce parcours En utilisant éventuellement des méthodes des différentes classes pour gérer la transformation des éléments un par un public class State {... public String toxml() { return new String(''<state>\n<name>\n''+name +''\n</name>\n</state>\n''); }... 17
Query/View/Transformation Un langage de transformation et de manipulation de modèles est en cours de normalisation à l'omg Query/View/Transformation ou QVT Query : sélectionner des éléments sur un modèle Le langage utilisé pour cela est OCL très légèrement modifié et étendu Avec une syntaxe différente et simplifiée View : une vue est une sous-partie d'un modèle Peut être définie via une query Une vue est un modèle à part, avec éventuellement un métamodèle restreint spécifique à cette vue Transformation : transformation d'un modèle en un autre 18
Transformations dans QVT Deux niveaux de transformations dans QVT Relations La spécification d'une transformation Éventuellement avec des parties non définies totalement Pour pouvoir réutiliser et adapter facilement une transformation dans différents contextes Relation est bi-directionnelle Mapping Relation générale entre 2 modèles Un mapping est le raffinement d'une relation dans un but d'exécution Définit complètement et totalement la transformation Mapping est généralement uni-directionnel Transformation d'un modèle en un autre 19
Langage de transformation QVT QVT propose un langage commun pour définir les relations et mappings Avec syntaxe graphique et textuelle Basé sur le pattern-matching Recherche de patrons : approche déclarative Exemple de transformation : syntaxe textuelle relation IncreasingWisdom { var n, a, w1; -- free vars domain Person {name = n, age = a, wisdom = w1} when a + 1 < 13 or a + 1 > 19; domain Person {name = n, age = a + 1, wisdom = w2}; when { w2 > w1 } } 20
Langage de transformation QVT Exemple : syntaxe graphique Partie non complétement définie w2 est supérieur à w1 Sera précisé dans le mapping 21
Langage de transformation QVT Mapping raffinant cette relation Spécifie l'augmentation du wisdom mapping IncreasingWisdomMapping(in person:person) : Person refines IncreasingWisdom guard match(n,a,w1) Person{name = n, age = a, wisdom = w1} when a + 1 < 13 and a + 1 > 19 } { name := n; p.age := a + 1; p.wisdom := w1 + 5; } 22
Langage de transformation QVT Transformation attributs d'une classe UML en XML Transformation entre 2 méta-modèles : Relation pour cette transformation : 23
Exécution/spécification Travaux actuels autour des outils et techniques de transformation Concerne quasiment uniquement que des problématiques d'exécution de transformation Mais doit aussi pouvoir spécifier les transformations Trois buts principaux Spécification et documentation Préciser ce que fait la transformation, dans quelles conditions on peut l'utiliser Validation et test Valider ou tester qu'un modèle peut bien être transformé ou est le résultat valide d'une transformation Validation de l'enchainement de transformation Enchainement de transformations est à la base de tout processus de développement basé sur le MDE 24
Spécification de transformation Mes travaux de recherche Spécification de transformations via des contrats de transformations Contrats : ensemble de contraintes sur un élément logiciel que s'engage à respecter l'élément (et l'utilisateur de l'élément) Spécifie ce que ce fait l'élément sans détailler comment il fait (ce qui correspond au code) Exemple du compte banquaire du cours sur OCL context Compte : débiter(somme : int) pre: somme > 0 post: solde = solde@pre - somme L'opération débiter s'engage à respecter la post-condition si l'élément appelant l'opération respecte la pré-condition Travaux actuels : essayer de spécifier en OCL ces contrats de transformations de modèles UML 25
Contrats de transformations Contrat de transformations de modèles : 3 ensembles de contraintes Contraintes que doit respecter un modèle source Contraintes que doit respecter un modèle cible Contraintes sur l'évolution des éléments du modèle source vers le modèle cible Deux premiers ensembles de contraintes Contraintes sur les modèles : s'expriment au niveau de leur méta-modèle Ils sont définis par spécialisation du méta-modèle UML Via des profils 26
Contrats de transformations Troisième ensemble de contraintes Spécifier en OCL via des pré et post-conditions l'opération de transformation définie au niveau du méta-modèle La pré-condition définit des contraintes avant la transformation : contraintes sur le modèle source La post-condition définit des contraintes après la transformation : contraintes sur le modèle cible Avec la construction @pre, on peut référencer dans la post-condition les éléments avant et après la transformation : peut spéficier contraintes sur l'évolution des éléments Problème de cette approche Les modèles cible et source doivent être conformes au même méta-modèle Pas de spécification de transformations exogènes Et pas toujours possible de spécifier toutes les transformations endogènes non plus (d'uml vers UML) 27
Contrats de transformations Autre approche plus générale pour spécifier opération de transformations Utiliser une opération qui prend en paramètre le modèle source (sous forme de package) et retourne le modèle cible (sous forme de package) Permet de définir des transformations avec méta-modèles source et cible différents Mais nécessite de définir une opération de mapping entre 2 éléments de modèles différents ens1 > mappedonto (ens2) elt1.mappedonto (elt2) 28
Exemple basique de transformation Privatisation des attributs Chaque attribut d'une classe devient privé et se voit associer une paire d'accesseurs Contraintes sur modèles sources : aucune Contraintes sur modèles cibles : attributs privés context Class inv: attributes > forall ( a : Attribute a.visibility = #private and a.owner.operation > exists (op : Operation op.name = get + a.name) and a.owner.operation > exists (op : Operation op.name = set + a.name)) 29
Exemple basique de transformation Troisième ensemble de contraintes Plusieurs façons d'avoir des modèles cibles valides Transformer les attributs publics en privés et ajout de getter/setter Supprimer tous les attributs ne respectant pas les contraintes On doit donc spécifier que tous les attributs sont conservés Utilise la première approche car les méta-modèles source et cible sont le méta-modèle UML (contraint pour le cible) context Class : :addaccessors() pre: -- none post: attributes@pre = attributes and attributes > forall ( a : Attribute a@pre.visibility = #public implies a.visibility = #private) 30
Exemple : ajout de proxy 31
Exemple : ajout de proxy Contraintes sur modèles source et cible Définition des profils UML Voir cours sur méta-modélisation pour plus de précisions Ces 2 profils sont contradictoires Le premier spécifie qu'un client doit être connecté à un serveur Le second spécifie qu'un client ne doit pas être connecté à un serveur 2 méta-modèles sont «incompatibles» bien que proches Utilise la deuxième approche pour spécification de l'évolution des éléments pendant la transformation Contrainte principale sur évolution des éléments Le proxy ajouté et associé à un client doit réaliser l'interface dont est dépendant ce client 32
Exemple : ajout de proxy context Package::proxyAddition(Package source) : Package pre: source.oclistypeof(profile) and source.name= ClientServer post: result.oclistypeof(profile) and result.name= ClientProxyServer and source.modelelement > select ( me me.ocliskindof(client)) -> mappedonto ( result.modelelement > select ( me me.iskindof(client))) and -- tous les clients sont conservés pendant la transformation result.modelelement > select ( me me.ocliskindof(client)) > forall ( cl cl.oclastype(client).dependson > forall ( i let sourceserver = (source.modelelement > select ( me me.ocliskindof(interface) and me.oclastype(interface) = i)) > first().oclastype(interface).isimplementedby in let server = (result.modelelement > select ( me me.mappedonto(sourceserver)) > first() in let proxy = self.newproxy() in server.oclistypeof(server) and proxy.implements > includes (i) and proxy.hasclassrefwith(cl) and proxy.hasclassrefwith(server) ) ) Peut simplifier ces contraintes avec les simplifications définies dans QVT 33