urbanisation-si.com

urbanisation-si.com

Ingénierie Dirigée par les Modèles (IDM)


Cours complet sur ATL (ATLAS Transformation Language) : les collections

cours-complet-atl-atlas-transformation-language-les-collections.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-types-primitifs

nous avion abordé de manière quick and dirty les types primitifs ATL.

 

La suite logique est de voir les collections, qui sont en fait les 4 collections définies dans OCL :

  • Set : sans doublon et non ordonnée
  • OrderedSetsans doublon et ordonnée
  • Bag avec doublon possible et non ordonnée
  • Sequence avec doublon possible et ordonnée

Opérations sur les collection

  • size() renvoie le nombre d'éléments de la collection self
  • includes(o : oclAny) renvoie un booléen si l'objet o fait partie de la collection self
  • excludes(o : oclAny) renvoie un booléen si l'objet o ne fait pas partie de la collection self
  • count(o : oclAny) renvoie le nombre de fois ou l'objet o apparaît dans la collection self
  • includesAll(c : Collection) renvoie un booléen si tous les objets de la collection c sont contenus dans la collection self
  • excludesAll(c : Collection) renvoie un booléen si aucun des objets de la collection c sont contenus dans la collection self
  • isEmpty() renvoie un booléen si la collection self est vide
  • notEmpty() renvoie un booléen si la collection self n'est pas vide
  • sum() renvoie une valeur correspondant à l'addition de tous les éléments de la collection self. Les types des éléments doivent être supportés par l'opérateur + 

ATL défini des opérations supplémentaires par rapport à OCL :

  1. asBag() renvoie un bag contenant tous les éléments de la collection self. 
  2. asSequence() renvoie une sequence contenant tous les éléments de la collection self en introduisant un ordre pour un bag ou un set.
  3. asSet() renvoie un set contenant tous les éléments de la collection self en perdant l’ordre pour un sequence ou un orderedset.Les doublons d’un bag ou d’une sequence sont éliminés.

Les opérations sur les séquences

  1. union(c : Collection) renvoie une séquence composée de tous les éléments de self suivi de ceux de c
  2. flatten() renvoie une séquence contenant le fils de la collection interne contenu dans self
  3. append(o : oclAny) renvoie une copie de self avec les éléments de o ajoutés à la fin de la séquence
  4. prepend(o : oclAny) renvoie une copie de self avec les éléments de o ajoutés au début de la séquence
  5. insertAt(n : Integer, o : oclAny), renvoie une copie de self avec les éléments de o ajoutésau rang nde la séquence
  6. subSequence(lower : Integer, upper : Integer)  une sous séquence de self commençant à lower jusqu’à upper (tous les 2 inclus)
  7. at(n : Integer) renvoie l’élément du rang n de self
  8. indexOf(o : oclAny) renvoie le rang de la 1ère occurrence de o dans self
  9. first() renvoie le rang de la 1er élément de self (oclUndefined si self est vide);
  10. last()renvoie le rang de la dernier élément de self (oclUndefined si self est vide);
  11. including(o : oclAny) renvoie une copie de self avec les éléments de o ajoutés à la fin de la séquence
  12. excluding(o : oclAny) renvoie une copie de self avec toutes les occurrences de l’élément o supprimées.

Les opérations sur le type Set

  1. union(c : Collection) renvoie un set composé des éléments de self et de c avec les doublons
  2. intersection(c : Collection) renvoie un set composé des éléments qui apparaissent à la fois dans self et dans c
  3. operator - (s : Set) renvoie un set composé des éléments de self qui ne sont pas dans s
  4. including(o : oclAny), renvoie une copie de self avec les éléments de o s’ils ne sont pas présent dans self
  5. excluding(o : oclAny), renvoie une copie de self avec les éléments de o supprimés du set
  6. symetricDifference(s : Set) renvoie un set composé des éléments de self ou de s mais des 2

Les opérations sur le type OrderedSet

  1. append(o : oclAny) renvoie une copie de self avec l’élément o ajouté à la fin s’il n’existait pas déjà dans self
  2. prepend(o : oclAny) renvoie une copie de self avec l’élément o ajouté au début de l’orderedset s’il n’existait pas déjà dans self
  3. insertAt(n : Integer, o : oclAny), renvoie une copie de self avec l’élément o ajouté au rang n de l’orderedset s’il n’existait pas déjà dans self
  4. subOrderedSet (lower : Integer, upper : Integer) renvoie une sous séquence de self commençant au rang lower et finissant au rang upper (les 2 inclus)
  5. at(n : Integer) renvoie l’élément du rang n de self
  6. indexOf(o : oclAny) renvoie le rang de la 1ère occurrence de o dans self
  7. first()renvoie le 1er élément de self (oclUndefined si self est vide)
  8. last()renvoie le dernier élément de self (oclUndefined si self est vide)
  9. union(c : Collection) renvoie un orderedset composé des elements de self suivis des elements de c avec les doublons supprimés, ils apparaissent entre c et self
  10. flatten()renvoie un orderedset contenant directement le fils de la collection interne à la collection contenant self
  11. including(o : oclAny) renvoie une copie de self avec l’élément o ajouté à la fin de l’orderedset s’il n’apparaît pas déjà dans self
  12. excluding(o : oclAny) renvoie une copie de self avec l’élément o supprimé

Les opérations sur le type Bag

  1. including(o : oclAny) renvoie une copie de self avec l’élément o ajouté à la fin de l’orderedset s’il n’apparaît pas déjà dans self
  2. excluding(o : oclAny) renvoie une copie de self avec l’élément o supprimé
  3. flatten()renvoie un orderedset contenant directement le fils de la collection interne à la collection contenant self  

Itérer sur les collections

La principale difference entre une operation classique et une expression iterative sur les collections est que l’itérateur accepte une expression comme parameter.

  1. La collection itérée est celle dont on fait reference comme source
  2. Les variables d’itération déclarées dont on fait référence comme itérateurs
  3. L’expression passée comme parameter de l’opération dont on fait reference dans le corps de l’itérateur

source->operation_name(iterators | body)

ATL supporte les expression itératives suivantes

  1. exists(body) renvoie une valeur booléenne suivant qu’il existe au moins un élément de source dans le body
  2. forAll(body) renvoie une valeur booléenne suivant que body est évalué à vrai pour tous les éléments de source
  3. isUnique(body) renvoie une valeur booléenne suivant que body est évalué à une valeur différente pour chaque élément de source
  4. any(body) renvoie un élément de source pour laquelle body est évalué à vrai. Si body n’est jamais évalué à vrai, l’opération renvoie OclUndefined;
  5. one(body) renvoie une valeur booléenne s’il existe exactement un élément de source pour laquelle body est évalué à vrai
  6. collect(body) renvoie une collection d’éléments resultant de l’application de body à chaque élément de la collection source
  7. select(body) renvoie un sous ensemble de la collection source pour laquelle body est évalué à vrai
  8. reject(body) renvoie un sous ensemble de la collection source pour laquelle body est évalué à faux (équivalent à select(not body));
  9. sortedBy(body) renvoie une collection ordonnée suivant body à partir de la plus petite valeur jusqu’à la plus grande. Les éléments de la collection source doivent avoir l’opérateur < défini  

OCL spécifie un itérateur encore plus générique appelé iterate() dont l’expression posséde un iterator, un accumulator et un body. L’accumulator correspond à une variable initialiée. Le body est une expression qui utilise iterator et accumulator. La valeur renvoyée par iterate() correspond à la valeur de la variable accumulator une fois que la dernière iteration s’est exécutée.

source->iterate(iterator; variable_declaration = init_exp |

        body

)

Exemples

  1. declaration d’une sequence d’entiers : Sequence(Integer)
  2. une sequence d’entiers : Sequence{1, 2, 3}
  3. declaration d’un ensemble de sequence de String : Set(Sequence(String))
  4. un ensemble de sequence de String : Set{Sequence{'monday'}, Sequence{'march', 'april', 'may'}}
  5. test si un bag est vide : Bag{1, 2, 3}->isEmpty()
    1. false
    2. Set{1, 2, 3}->includes(1)
      1. true
    3. Set{1, 2, 3}->includesAll(Set{3, 2})
      1. true
    4. Sequence{1, 2, 3}->size()
      1. 3
      2. ATTENTION : Set{3, 3, 3}->size() est évalué à 1 car un set élimine les doublons
    5. OrderedSet{1, 2, 3}->first()
      1. 1
    6. Sequence{1, 2, 3}->union(Sequence{7, 3, 5})
      1. Sequence{1, 2, 3, 7, 3, 5}
    7. Set{1, 2, 3}->union(Set{7, 3, 5})
      1. Set{1, 2, 3, 7}
    8. Sequence{Sequence{1, 2}, Sequence{3, 5, 2}, Sequence{1}}->flatten()
      1. Sequence{1, 2, 3, 5, 2, 1}
    9. Sequence{Sequence{1, 2}, Sequence{3, 5, 2}, Sequence{1}}->subSequence(2, 3)
      1. Sequence{ Sequence{3, 5, 2}, Sequence{1}}
    10. Sequence{5, 15, 20}->insertAt(2, 10)
      1. Sequence{5, 10, 15, 20}
    11. Set{1, 2, 3}->intersection(Set{7, 3, 5})
      1. Set{3}
    12. Set{1, 2, 3}->symetricDifference(Set{7, 3, 5})
      1. Set{1, 2, 7, 5}
    13. Sequence{1, 2, 3, 4, 5, 6}->select(i | i <= 3)
      1. Set{1, 2, 3}
    14. Récupérer tous les noms des classes du MOF : MOF!Class.allInstances()->collect(e | e.name)
    15. Vérifier que tous les éléments d’une séquence sont plus grand que 2 : Sequence{12, 13, 12}->forAll(i | i > 2)
      1. true
    16. Vérifier s’il y a un unique élément d’une séquence plus grand que 2 :  Sequence{12, 13, 12}->one(i | i > 2)
      1. false
    17. Vérifier s’il existe un nombre dans la séquence plus grand que 2 :   Sequence{12, 13, 12}->exists(i | i > 2)
      1. evaluates to true
    18. Sequence{8, -1, 2, 2, -3}->iterate(e; res : Integer = 0 |
      if e > 0
      then res + e
      else res
      endif
      )
      1. 12;
      2. équivalent à Sequence{8, -1, 2, 2, -3}->select(e | e > 0)->sum()

 
"Si mon esprit peut le concevoir, et mon cœur peut le croire, alors je peux le réaliser."
Muhammad Ali

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


29/09/2015
0 Poster un commentaire

Cours complet sur ATL (ATLAS Transformation Language) : les types primitifs

cours-complet-atl-atlas-transformation-language-les-types-primitifs.jpg

 

Dans l'article précédent :

https://www.urbanisation-si.com/ingenierie-dirigee-par-les-modeles-idm-cours-complet-sur-atl-atlas-transformation-language-les-types-atl

nous avion commencé à aborder les types ATL, voyons maintenant de manière quick and dirty les types primitifs ATL.

Ils sont  largement basés sur OCL (voir l’article : ) qui défini 4  types primitifs de base :

  • Boolean  true ou false;
  • Integer  (1, -5, 2, 34, 26524, ...);Real  (1.5, 3.14, ...);
  • String ('Les 2 choses les plus difficiles à dire sont bonjour pour la première fois et au revoir pour la dernière', ...). Caractère d’échappement \. Pour les geeks Javaiste, gourous du C++ ou Prolog, en OCL un caractère est codé comme une chaîne de 1 et les caractères d’une chaîne sont numérotés à partir de 1 jusqu’à la taille de chaîne.

Les operations sur des types booléens

  • and, or, xor, not;
  • implies(b : Boolean) renvoie false is self est true et b est false et renvoie true dans les autres cas.
  • Cas de 2 expressions reliées par un and :
    if (exp1 and exp2) 
    then ...
    else ...
    endif
    Contrairement aux autres langages, si la 1ère expression est fausse, la 2ème est quand même évaluée
    Attention donc aux pièges :
    if (self.attributes->size() > 0 and self.attributes->first().attr)
    Même si la 1ère expression est fausse, la 2ème est appellee sur “attr” qui n’est pas défini, ce qui provoque naturellemnt une erreur !

Les operations sur les chaînes de caractères

  • size() renvoie le nombre de caractères de la chaîne self;
  • concat(s : String) renvoie la chaîne représentant la concatenation de self +“s'
  • substring(lower : Integer, upper : Integer) renvoie la sous-chaîne de self commençant à lower jusqu’à upper;
  • toInteger() et toReal().
  • comparison operators: <, >, >=, <=;
  • la concatenation de chaînes (+) identique à concat()
  • toUpper(), toLower() renvoie une copie de self en majuscule ou minuscule
  • toSequence() renvoie une sequence de caractères correspondant à self
  • trim() renvoie une chaîne sans les espaces au début et à la fin (' ', '\t', '\n', '\f', '\r') sont omis
  • startsWith(s : String), endsWith(s : String) renvoie true si self commence/se termine avec s
  • indexOf(s : String), lastIndexOf(s : String)  renvoie l’index (entier) de la 1ère occurrence de s qui apparaît dans self
  • split(regex : String) éclate self en function de l’expression régulière regex (Java regular expressions) et renvoie une séquence de chaîne
  • replaceAll(c1 : String, c2 : String) renvoie uen copie de self dans laquelle chaque occurrence du caractère c1 est remplacé par le caractgère c2. Attention, c1 et c2 sont types comme des chaînes OCL, mais seuls le premier caractère de c1 et c2 sont considérés.
  • regexReplaceAll(regex : String, replacement : String) renvoie une copie de self  dans laquelle chaque sous-chaîne qui correspond à l’expression régulière regex est remplacé avec la chaîne replacement.
  • writeTo(fileName : String) écrit la chaîne self dans un fichier fileName. (path complet)
  • println() écrit self dans la console Eclipse

Qu’en est il des opérations sur les types numériques ?

  • <, >, >=, <=;
  • *, +, -, /, max(), min();
  • abs().
  • ATTENTION : l’opérateur de signe – défini dans OCL, n’est pas défini dans ATL. Une solution de contournement est de faire 0-x
  • opérations sur les entiers : div(), mod();
  • opérations sur les réels : floor(), round().
  • toString() est disponible pour les entiers et les réels. Ils peuvent être converti en long avec longValue()
  • cos(), sin(), tan(), acos(), asin();
  • toDegrees(), toRadians();
  • exp(), log(), sqrt().

Vous voulez du concret ?

  • 'test'.oclIsTypeOf(OclAny)

    •  false

  • 'test'.oclIsKindOf(OclAny)

    • true

  • true or false

    • true

  • 'test'.substring(2, 3)

    • 'es'

  •  'test'.toUpper()

    • 'TEST'

  • 'test'.toSequence()

    • Sequence{'t', 'e', 's', 't'}

  • 'test'.endsWith('ast')

    • false

  • 'test'.lastIndexOf('t')

    • 4

  •  'test'.replaceAll('t', 'o')

    • 'oeso'

  • 'aaabaftaap'.regexReplaceAll('a*', 'A')

    • 'AbAftAp'

  • 23 div 2 or 23."div"(2)

    • 11

  • 23/2

    • 11.5

 

"Les choses ne changent pas, change ta façon de les voir, cela suffit."
Lao Tseu

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


26/09/2015
0 Poster un commentaire

Ingénierie Dirigée par les Modèles (IDM) : cours complet sur ATL (ATLAS Transformation Language) : les types ATL

cours-complet-ATL-atlas-transformation-language-les-types-atl.png

 

Dans l'article précédent :

https://www.urbanisation-si.com/ingenierie-dirigee-par-les-modeles-idm-cours-complet-sur-atl-atlas-transformation-language-librairie-atl

nous avion abordé la dernière unité ATL, la librairie.

 

Abordons maintenant les outils sur les types mis à notre disposition par ATL.

L'appel à des opérations (méthodes) se fait comme en OCL, c'est à dire à partir du contexte d'une instance d'un type spécifique. ATL reprend le même mot clé self qu'en OCL pour se référer à cette instance de contexte.

 

Les opérations de la classe OclType

Cette classe OCL correspond à la définition des types d'instances.

  • allInstances() : renvoi l'ensemble des instances du type de l'instance courante self
  • allInstancesFrom(model : String) : retourne l'ensemble des instances de type self définies dans le modèle identifié par le paramètre model
  • opérateur de comparaison : =, <>;
  • oclIsUndefined() renvoie vrai si self n'est pas défini
  • oclIsKindOf(t : oclType)  renvoie vrai si self est soit une instance de t ou d'un des sous-type de t
  • oclIsTypeOf(t : oclType) renvoie vrai si self est soit une instance de t 
  • toString() renvoie self sous forme de chaîne de caractères
  • oclType() renvoie le oclType de self
  • asSequence(), asSet(), asBag() renvoie une sequence, un set ou un bag contenant self. Ces opérations sont redéfinies pour les types collection
  • output(s : String) écrit sur la console Eclipse, à utiliser obligatoirement dans les blocs  impératifs ATL 
  • debug(s : String) renvoie la valeur de self et écrit la chaîne "s : self_value" dans le console Eclipse
  • refSetValue(name : String, val : oclAny)  opération réflexive permettant d'affecter à l'instance self identifiée par name la valeur val. Renvoie self
  • refGetValue(name : String) opération réflexive renvoyant la valeur de self identifié par name
  • refImmediateComposite() opération réflexive renvoyant le composite (conteneur) de self
  • refInvokeOperation(opName : String, args : Sequence) opération réflexive permettant d'invoquer une opération de self nommée opName avec les paramètres contenus dans la séquence args

 

"Rien ne vous emprisonne excepté vos pensées. Rien ne vous limite excepté vos peurs. Et rien ne vous contrôle excepté vos croyances."
Marianne Williamson

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


24/09/2015
3 Poster un commentaire

Ingénierie Dirigée par les Modèles (IDM) : cours complet sur ATL (ATLAS Transformation Language) : librairie ATL

cours-complet-ATL-atlas-transformation-modele-presentation-librairies.jpeg

 

Dans l'article précédent :

https://www.urbanisation-si.com/ingenierie-dirigee-par-les-modeles-idm-cours-complet-sur-atl-atlas-transformation-language 

nous avion abordé les 2 modes d'exécution d'ATL :

  • mode normal
  • mode affiné

La dernière unité ATL est la librairie.

Le développement d'une librairie, comme dans tous les langages, permet de définir un ensemble de helpers pouvant être appelé à partir de différentes unités.

Une librairie ATL peut inclure, comme les autres unités, une section import. 

Contrairement à un module ATL, il n'existe pas d'éléments de module par défaut pour les librairies ATL. Par conséquent, il est impossible de déclarer des helpers définis dans le contexte par défaut du module. Cela signifie que tous les helpers définis à l'intérieur d'une librairie doivent explicitement être associés à un contexte donné.

De même, contrairement aux modules, une librairie ATL ne peut pas être exécutée indépendamment. En d'autre terme, une librairie n'est associé à aucune étape d'initialisation pendant l'exécution. De ce fait, des attributs de helper ne peuvent pas être définis dans une librairie ATL.

 

"Il existe trois types de personnes : Celles qui créent les choses, celles qui observent les choses se créer et celles qui se demandent ce qui vient de se passer."
Mary Kay Ash

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


23/09/2015
0 Poster un commentaire

Ingénierie Dirigée par les Modèles (IDM) : cours complet sur ATL (ATLAS Transformation Language)

cours-complet-ATL-atlas-transformation-modele-presentation-librairies.jpeg

 

Dans l'article précédent :

https://www.urbanisation-si.com/ingenierie-dirigee-par-les-modeles-idm-documentation-atl-atlas-transformation-language-vous-saurez-tout-ou-presque-sur-les-modules 

nous avion abordé les modules ATL.

Examinons maintenant les 2 modes d'exécution d'ATL :

  • mode normal
  • mode affiné

Le mode normal est le mode par défaut. Il utilise le mot clé from dans le header du module. Dans ce mode, le développeur doit spécifier soit par "matched" ou "called rules", la manière dont va être généré les éléments du modèle cible. Ce mode convient dans les cas les plus fréquents ou le modèle cible est radicalement différent du modèle cible.

Le mode affiné correspond plus à un héritage, où on ne redéfinirait seulement quelques éléments de la cible. Ainsi le développeur peut se concentrer sur les règles de transformation spécifiques. Les éléments inchangés du source sont implicitement copiés vers la cible. Le mot clé refining doit être précisé dans le header. Le développeur spécifie comment générer un élément dés que la transformation modifie un attribut ou une référence. Par contre, l'avantage, c'est qu'il ne précise rien pour tout ce qui concerne les éléments inchangés et directement copiés. L'avantage est l'économie en terme de code.

 

"Ce n'est pas l'ignorance, mais le savoir qui est la mère de l'émerveillement."
Joseph Wood Krutch

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


23/09/2015
0 Poster un commentaire

Ingénierie Dirigée par les Modèles (IDM) : documentation ATL (ATLAS Transformation Language), vous saurez tout ou presque sur les modules

cours-atl-atlas-transformation-model-metamodele-author.png

 

cours-atl-atlas-transformation-model-metamodele-person.png

 

cours-atl-atlas-transformation-model-metamodele-book.png

 

Un module ATL correspond à une transformation de modèles, voir les articles :

https://www.urbanisation-si.com/ingenierie-dirigee-par-les-modeles-idm-tutoriel-atl-atlas-transformation-language-le-da-vinci-code-de-la-transformation-atl

et

https://www.urbanisation-si.com/model-driven-engineering-mde-modeles-metamodeles-metametamodeles-meta

ATL permet de produire un ensemble de modèles cibles à partir d'un ensemble de modèles sources. 

Le modèles sources et cibles doivent être des instances de leurs métamodèles respectifs.

Un module ATL est composé des sections :

  1. header
  2. import
  3. helpers
  4. rules

1) La section "Header"

Elle définie le nom de la transformation et les noms  des variables correspondant aux modèles sources et cibles.

module module_name; create output_models [from|refining] input_models;

De manière similaire à Java, le nom du fichier ATL ( .atl ) doit avoir exactement le même nom que le module.

Le mot clé create précise le modèle source et from ( en mode normall ) et refining ( dans le cas où on raffine la transformation ) pour le modèle source.

La déclaration multiple de modèles, séparés par des virgules, en entrée/sortie est possible.

module Book2Publication; create OUT : Publication from IN : Book;

2) La section Import

Elle est facultative et permet de déclarer des librairies ATL.

uses extensionless_library_file_name;

3) La section Helpers

C'est vraiment l'équivalent des helpers Java, ils offrent la possibilité de factoriser du code.

helper context Integer def : max(x : Integer) : Integer = ...;

4) La section Rules

3 types de règles :

"Matched rules" : constituent la partie déclarative de la transformation. On doit spécifier :

  • pour quels types d'éléments sources, des éléments cibles doivent être générés.
  • la manière dont les éléments cibles sont initialisés

Une "matched rule" est identifiée par son nom. Elle correspond à un type d'élément du modèle source et génère un ou plusieurs éléments du modèle cible.

rule Author {
   from
      a : MMAuthor!Author
   to
      p : MMPerson!Person (
         name <- a.name,
         surname <- a.surname
      )
}

Cette règle "Author", a pour but de transformer les éléments du modèle source Author ( à partir du métamodèle source MMAuthor ) en éléments du modèle cible Person ( MMPerson ) . Elle ne contient pas de filtres ce qui signifie que toutes les classes de MMAuthor correspondent au pattern.

La règle concernant le pattern cible contient un simple pattern qui instancie la classe Person de MMPerson du métamodèle cible pour chaque éléments source correspondant au pattern source.

Lazy rules ne sont appliquées seulement lorsqu'elles sont appelées par une autre règle.

Called rules permet au développeur de programmer de manière impérative ( à la manière d'un langage classique d'un langage de programmation Java, C++, C#, ... ).

Gardons en peu pour les prochains articles.

 

"N'oublie pas que chaque nuage, si noir soit-il, a toujours une face ensoleillée, tournée vers le ciel."
Friedrich Wilhelm Weber

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


20/09/2015
0 Poster un commentaire

Ingénierie Dirigée par les Modèles : présentation MDA ( Model Driven Architecture ), mais est ce utilisé dans la vraie vie ?

ingenierie-dirigee-par-les-modeles-presentation-MDA.jpg

 

Partir d'un modèle de concepts métier et transformer ce modèle en d'autres modèles s'affinant progressivement pour arriver finalement à un modèle de code source.

 

En 2015 l'homme devra encore se plier à la machine.

Depuis longtemps on nous promet pour les applications informatiques de gestion de commencer par modéliser les concepts métier : les processus, les entités, les règles et les éléments d'IHM, puis d'indiquer l'architecture cible et laisser la technique générer le code source Java, .NET, Web, ....

Les enjeux sont de taille. Cela permet de se concentrer sur les aspects métier, l'optimisation et la flexibilité des processus par la mise en place de BPM (Business Management Process), de capitaliser les connaissances comme les règles métier avec un BRMS (Business Rules Management System), de pérenniser le modèle de données métier avec une modélisation optimisée avec UML (Unified Modeling Language).

Aujourd'hui de nombreuses applications vieillotes réalisées à l'ancienne sont rajeunies en changeant les techniques d'IHM, en relookant les écrans dans un style tendance à la Facebook, en développant de nouveaux domaines dans les technologies adoptées par l'industrie IT comme Java ou .NET. Et puis dans 10 ans, on changera tout à nouveaux pour les dernières architectures à la mode.

Quelque soit la plateforme cible (Java, .NET, Web, Google, Mainframe, ...), l'architecture est toujours la même avec les couches : présentation, contrôleur, services métier, injection de dépendances, persistances, SGBDR, moniteur transactionnel, ...

Et pourtant dans chaque projet, on recommence par concevoir et valider l'architecture, à mettre en place la pile de framework correspondant aux couches précédentes et on refait toujours la même chose. Les consultants facturent cher un travail qu'ils ont déjà fait car les solutions sont bien connues et pourraient être automatisées. N'importe quel architecte sait qu'il doit mettre en place par exemple dans une architecture Java classique la persistance avec Hibernate, le workflow écran, l'injection de dépendance, les transactions, les batchs avec Spring, les IHM avec HTML/Javascript/JSF/GWT/ ... etc, etc.

Pourtant fin des années 90 début 2000, les grands éditeurs comme IBM, Sun (racheté par Oracle), Borland (racheté par Micro Focus), Oracle, ... et les organismes de normalisation comme l'OMG (Object Management Group) ont mis au point des solutions. Une des plus prometteuse est MDA (Model Driven Architecture) constituée d'un nombre impressionnant d'autres normes comme UML (Unified Modeling Language), OCL (Object Constraint Language), MOF (Meta Object Facility), XMI (XML Metadata Interchange), QVT (Query View Transformation), ASL (Action Semantics Language), etc, etc.

 

ingenierie-dirigee-par-les-modeles-presentation-MOF.gif
 

On part de la vraie vie c'est à dire les objets (par exemple la facture du 26/01 du client Martin), puis on remonte d'un niveau d'abstraction, au niveau modèle (la classe Facture et Client) puis encore plus abstrait avec le méta modèle (on modélise le modèle : Classe, Attribut, Association, ...) puis enfin ça se termine avec le méta méta modèle (tout est objet : Classe).

Depuis des décennies les grands acteurs IT parlent d'outils, de normes et de framework dans le but de générer un maximum de codes.

L'idée la plus alléchante étant à partir d'un modèle métier et indépendant de la technique (CIM Computation Independent Model), de génèrer un autre modèle indépendant d'une plateforme de développement (PIM Plateform Indépendent Model), puis génére un modèle spécifique à une plateforme (PSM Plateform Specific Model) comme Java, .NET, SQL, ... Puis enfin génèrer un modèle de code qui pourra être traduit directement dans un langage informatique standard.

Pour pouvoir transformer des modèles, il faut pouvoir manipuler le méta modèle (MOF) avec un langage (QVT).

Dans l'architecture MDA tout est piloté par les modèles, on trouve aussi la réciproque ADM (Architecture Driven Model) permettant de faire du reverse engineering c'est à dire que les modifications métier (ajout d'un attribut métier par exemple) vont se retrouver dans les modèles PSM, PIM et CIM. On parle alors de round trip (autoriser les transformations inverses).

Tout ceci est très joli sur la papier. L'OMG ne fait que des normes et ne s'occupe pas des implémentations. Elle recherche du reste souvent des partenaires et sponsors pour réaliser ses normes.

Dans la communauté IT pour se démarquer de l'OMG, on utilise souvent l'acronyme MDE (Model Driven Engineering), c'est le seul qui n'a pas été déposé comme marque par l'organisme de normalisation !

Pour que ça marche réellement et que ce ne soit pas juste de la simple génération de code, il faut avoir le méta modèle du PIM avec les classes métier, les services, les éléments d'IHM (liste déroulante, ...), ..., le méta modèle du PSM facilement réalisable par les architectes techniques car il suffit de modéliser les nombreuses instances d'architectures existantes et enfin un transformateur de PIM en PSM.

 

ingenierie-dirigee-par-les-modeles-presentation-transformation-de-modeles.jpg

 

MDA ne fournit pas d'implémentation qui est complexe, coûteuse et risquée à réaliser. Il faut les méta modèles du PIM et PSM et un transformateur de ces modèles.

Alors serait ce le Saint Graal ?

Apparement non car les gros projets ne l'utilisent pas du tout. Les raisons sont multiples. D'abord le coût d'appropriation des concepts et donc le retour sur investissement. La conjoncture actuelle ne se prête pas à de la recherche et développement. Les solutions proposées par les éditeurs ou par les open sources sont trop variées sans réelles pérennités. Les projets sont contraints par les délais et le budget de plus en plus serré. On a tendance à utiliser les bonnes vieilles méthodes. Le source est déporté sur le PIM qui doit être correctement modélisé et c'est là qu'il y a le principal risque. Comment gérer les itérations lorsqu'on modifie les sources ? Faut il faire des transformations inverses ? Faut il régénérer à partir du PIM ? Quelles sont les réels retours d'expérience avec leur ROI et non pas de la simple génération de codes ou de mise en place de template de codes.

Encore une fois la boucle est bouclée. Les normes sont intéressantes sur la papier, les éditeurs commencent des implémentations prometteuses mais incomplètes et attendent que les grands comptes s'y mettent mais comme il n'y  a rien de consistant, sans retours d'expérience et en ces temps économiques non propices aux investissements personne ne veut payer pour les autres. La génération automatique d'applications informatiques à partir de modèles applicatifs n'est pas pour demain, les architectes techniques et les développeurs ont encore de beaux jours devant eux.

 

"La vie est toujours en devenir, mais il ne faut jamais oublier de la vivre au présent."
Jacques Salomé

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


17/09/2015
0 Poster un commentaire

Ingénierie Dirigée par les Modèles : le saint graal de la génération de code

ingenierie-dirigee-par-les-modeles-generation-de-code-2.png

Où en est-on sur la génération de code ? L'OMG (Object Management Group) a depuis plus de 10 ans spécifié des normes sur la transformation de modèles permettant en théorie de générer un modèle de code (PSM Plateform Specific Model) à partir d'un modèle décrivant des processus et des objets métier (PIM Plateform Independant Model).

 

Seulement voilà, comme à son habitude, l'OMG laisse le soin à d'autres de réaliser les outils conforment à ses spécifications . Plus facile à dire qu'à faire ! Quelques organisations open source ou commerciales s'y sont essayées en respectant plus ou moins les normes et de tout de manière sans succès, personne ne voulant investir sans avoir une garantie sur le retour sur investissement. Les solutions propriétaires existent depuis encore plus longtemps souvent intégrées dans leur AGL (Atelier de Génie Logiciel) sans plus de succès. 
Alors faut il intégrer de la génération de code dans les projets ? Et si oui, à quelle dose ? 
En 2004 j'avais participé à l'élaboration de l'urbanisation du SI d'un organisme de santé. L'organisation était très "IBMisée" et avait misé sur les outils Rational (racheté par IBM). La stratégie reposait en partie sur la génération de code à partir de modèles UML. Les problèmes sont arrivés lorsque l'équipe d'une dizaine de développeurs ont voulu modifier le code Java généré. RSA (Rational Software Architecture) était censé gérer le round trip, c'est à dire la mise à jour du code en cas de modification des modèles et réciproquement. Malheureusement lorsque plusieurs développeurs faisaient des changements sur les mêmes parties de code, les modèles étaient modifiés que partiellement. Suite à notre plainte, IBM nous a répondu que le bug était répertorié et qu'un patch nous serait livré dans 6 mois! Les raisons de ne pas utiliser les générateurs viennent essentiellement de la faible fiabilité, de la complexité de la mise œuvre, des contraintes imposées, de l'impossibilité de modifier ou de comprendre le code généré ou bien encore que le développeur passe plus de temps à paramétrer l'outil qu'à se concentrer sur la partie métier. Se lancer dans un générateur de code serait bien la dernière chose à faire. Cela paraît peut être trivial mais certains développeurs se laisseraient bien emporter par leur passion dans un tourbillon infini. 
Alors faut il définitivement ranger la génération de code aux oubliettes ? Évidement que non car la bonne question à se poser relève une fois encore de la méthodologie c'est à dire : que dois-je générer et par quels moyens ? Les parties de code répétitives, représentent les patterns de conception, l'implémentation des différentes couches d'architecture, les squelettes du modèle métier, les règles métier et tout ce qui relève de la présentation (écrans, rapports, ...). 
Parmi les dernières tendances de méthode agile comme Accelerated Delivery Platform de Cap Gémini, la génération de codes repose sur des templates et des stéréotypes de Use Case. Dans une application de gestion, on fait toujours la même chose : des recherches, créations, modifications, suppressions, ... d'entités métier. On peut identifier des types de use case comme : <<search>>, <<create>>, ... L'étape suivante est la traditionnelle modélisation du domaine métier avec un diagramme de classe UML. On associe par exemple le use case "rechercher un contrat" de stéréotype <<search>> à la classe "Contrat". Un générateur MDA (Model Driven Architecture) open source comme Tobago MDA permet l'importation du modèle. Le template ( modèle de code) se conçoit à partir d'un bloc de code répétitif dans lequel on remplace les entités à variabiliser par des tags. Le template est positionné dans des structures de boucles ou conditionnelles du générateur et les valeurs à remplacer dans les tags seront récupérées du diagramme de classe UML. Le squelette de code peut être emprunté à la couche présentation ou à toute autre de l'architecture applicative et technique. 
Cette manière efficiente de générer du code est entièrement intégrée à la méthode agile ADP et utilise les bonnes pratiques et c'est assez rare pour qu'on le cite les norme UML et MDA. Cela démontre bien que les normes peuvent être utilisées et contribuer au retour sur investissement à condition de viser le pragmatisme et d'oser le changement dans la méthodologie de gestion de projet car rien ne vaut le changement pour dynamiser et motiver une équipe.

 

"- Qu'est-ce que vous faites ?
- Je m'amuse à vieillir. C'est une occupation de tous les instants."
Paul Léautaud

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


15/09/2015
1 Poster un commentaire

Ingénierie Dirigée par les Modèles : l'orienté but avec KAOS

ingenierie-dirigee-par-les-modeles-metamodel-KAOS.jpg

L’ingénierie des exigences basée sur les buts considère l’organisation et les objectifs des acteurs comme la source des exigences (fonctionnelles et non fonctionnelles).

Avant de travailler à l’élicitaton des exigences, il convient de se concentrer sur l’élicitation des buts. Les GOREs modélisent donc les buts.

Ces derniers peuvent être vus comme les propriétés désirées du système qui ont été exprimées par les utilisateurs. En outre, ils peuvent être spécifiés à différents niveaux d’abstraction, couvrant les préoccupations stratégiques à haut-niveau et à un niveau inférieur les problèmes techniques

L’approche KAOS, est un processus complet d’ingénierie des besoins allant de la spécification jusqu’au développement et prenant en compte les influences du domaine et de l’environnement.

Cinq méta-modèles sont présentés :

  • métamodèle des buts,
  • méta-modèle d’agent,
  • méta-modèle d’opération,
  • méta-modèle d’objet
  • méta-modèle de comportement.

Le méta-modèle de buts présente le raffinement des buts en besoins et attentes en tenant compte du contexte du domaine afin d’écarter les obstacles à la réalisation de ces derniers.

Un but peut être soft (réalisé par la satisfaction d’un ou plusieurs critères) ou comportemental (réalisé par un changement d’états à travers les opérations : achieve, avoid, maintain).

Les attentes sont affectées aux agents tandis que les besoins sont sous la responsabilité des agents logiciels qui assurent la réalisation de ces buts à travers l’opérationnalisation des besoins.

KAOS présente différents types de raffinement notamment AND, OR, milestone (ordonné), etc.

 

"Socrate disait: “Je sais que je ne sais rien”, donc chacun de nous en sait plus que Socrate, puisque nous savons au moins que Socrate ne savait rien."
Jean Amadou

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


15/09/2015
0 Poster un commentaire

Didacticiel ( tutoriel ) Eclipse Sirius ( Obeo Designer Community ) : on peaufine l'éditeur de diagramme

didacticiel-tutoriel-sirius-relation-creation-instance.png

 

Dans l'article précédent :

https://www.urbanisation-si.com/didacticiel-tutoriel-eclipse-sirius-obeo-designer-community-le-digne-successeur-de-gmf-le-framework-le-plus-complexe-du-monde

on a vu comment concevoir un nouvel éditeur de diagramme basé sur un métamodèle ecore.

Ce nouvel éditeur est un plugin Eclipse utilisant le nouveau framework Sirius remplaçant avantageusement le calamiteux GMF ( Graphical Modeling Framework ).

Nous avions créé un "viewpoint" contenant un objet "representation" de type diagram.

Le mapping est lié à la classe basicfamily.Man et le style des carrés sur fond bleu clair et les libellés en marrons.

Je vous propose d'améliorer le style.

Premièrement, ajoutons des images :

                                                                    didacticiel-tutoriel-sirius-woman32.png                                   didacticiel-tutoriel-sirius-man32.png

  • Clic droit sur ManNode - New Style - Workspace Image - téléchargez, stockez et sélectionnez les images ci-dessus dans la vue Properties - General -Workspace Path.
  • Dans l'onglet Label de Properties désélectionnez Show icon pour avoir 2 images sur chaque noeud.
Ajoutez un second noeud "WomanNode" en procédant de la même manière que dans l'article précédent.
  • Id* : WomanNode
  • Domain Class* : basicfamily.Woman
  • Semantic Candidates Expression : feature:members

Sauvegardez le fichier .odesign, le diagramme courant est automatiquement mis à jour reflètant les changements.

Ajoutez une une relation de base :
  • Clic droit Default - New Diagram Element -  Relation Based Edge 
  • Dans la vue Properties saisissez Source et Target :
  • Source Mapping : ManNode, WomanNode
  • Target Mapping : ManNode
  • Target Finder Expression : featurefather

Editez le style de la relation :

  • Sous fatherEdge, sélectionnez Edge style solid - Color - blue

Créez une 2ème relation mother de couleur purple.

Sauvegardez, rafraîchissez le diagramme et faites Arrange All.

Créez un outil d'édition de diagramme, ajoutez une palette. 
  • Clic droit sur Default - New Tool - Section

La palette est composée d'outils permettant de créer des objets.

Pour créer de nouvelles instances de votre domaine métier, ajoutez un "Node Creation" à la "Section" :
  • Clic droit sur la Section - New Element Creation - Node Creation
  • Dans Properties - General :
  • Id : createMan
  • Node Mapping : ManNode
  • Force Refresh : coché
  • Precondition :
  • Expected return type: a boolean.
  • Available variables: : container: ecore.EObject | the container.
Definir l'action exécutée par l'outil Create Node

Clic droit Begin - Change Context

  • Dans Properties - General - Browse Expression : varcontainer
  • Clic droit sur Change Context varcontainer - New Operation - Create Instance
  •  Dans Properties - General :
  • Reference Name : members
  • Type Name : basicfamily.Man
  • Variable Name : instance

Quand vous allez dans le diagramme, la palette contient une section createMan.

Sélectionnez, drag and drop dans le diagramme, éditez les propriétés du nouvel homme !

 

"La civilisation est une multiplication indéfinie de besoins dont on n'a pas besoin."
Samuel Mark

 

Voir aussi :  

 

http://urbanisation-si.wix.com/blog

http://urbanisme-si.wix.com/blog

http://urbanisation-si.wix.com/urbanisation-si

http://urbanisation-si.over-blog.com/

http://rhonamaxwel.over-blog.com/

http://urbanisation-des-si.blogspot.fr/

http://bonnes-pratiques-si.eklablog.com/

http://urbanisation-si.eklablog.com/


14/09/2015
0 Poster un commentaire