Ingénierie Dirigée par les Modèles (IDM)
Cours complet sur ATL (ATLAS Transformation Language) : le mode “affiné” ATL
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-de-la-bonne-utilisation-des-regles-dans-le-langage-atl
nous avion abordé la bonne utilisation des règles dans le langage ATL. Voyons à présent le mode “affiné” ATL.
Le mode “affiné” ATL
Ce mode permet un refactoring (affinage) des transformations.
Les développeurs peuvent se concentrer sur leur code dédié à la génération des éléments modifies, les autres éléments (ceux qui restent inchangés entre les modèles source et cible), sont implicitement traités par le moteur ATL.
Ce mode est mis en place en remplaçant le mot clé from par le mot clé refining dans l’entête de la transformation.
Il est evident que ce mode ne fonctionne qu’avec les transformations dans lesquelles les modèles source et cible partagent le même métamodèle.
Exemple :
create OUT : ClassDiagram refining IN : ClassDiagram;
"Dans la balance de la destinée, le muscle ne pèse jamais autant que le cerveau."
James Russel Lowell
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/
Cours complet sur ATL (ATLAS Transformation Language) : De la bonne utilisation des règles dans le langage ATL
Dans l'article précédent :
nous avion abordé l’héritage des règles. Voyons à présent "la bonne utilisation des règles dans le langage ATL".
Comme le savez si vous avez jetez un œil sur les articles précédents, il y 3 types de règles déclaratives possibles :
- les règles de correspondance (matched rules) sont appliquées à chaque correspondance. Un ensemble d'éléments donnés ne peut être mis en correspondance que une seule règle standard.
- les règles paresseuses (lazy rules) sont appliquées autant de fois pour chaque correspondance dans laquelle la règle est référencée par une autre (potentiellement jamais pour certianes correspondances).
- les règles paresseuses uniques (unique lazy rules) are sont appliquées au moins une fois pour chaque correspondance, et seulement si elles référencées par d'autres règles.
Le tableau suivant résume le nombre d'application des règles suivant leur type :
Type de règle |
Nombre de références au pattern source |
Nombre de fois où les patterns cibles sont créés |
standard |
0 |
1 |
1 |
1 |
|
n > 1 |
1 |
|
lazy |
0 |
0 |
1 |
1 |
|
n > 1 |
n |
|
unique lazy |
0 |
0 |
1 |
1 |
|
n > 1 |
1 |
Recommandations :
- Préférez les règles déclaratives aux règles impératives. Utilisez seulement ces dernières seulement si c'est absolument nécessaire pour la transformation.
- Préférez la simplicité à la complexité :
- Utilisez le plus souvent quand c'est possible, les règles standards, autrement utilisez les "unique lazy rules", et "lazy rules" seulement en cas de nécessité.
- Utilisez "resolveTemp" seulement en cas de nécessité.
- Préférez les itérateurs (select, collect) à "iterate.
"Il suivait son idée. C'était une idée fixe, et il était surpris de ne pas avancer."
Jacques Prévert
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/
Cours complet sur ATL (ATLAS Transformation Language) : l’héritage des règles
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-regles-appelees-called-rules
nous avion abordé les règles appelées (Called Rules). Voyons à présent l’héritage des règles.
L’héritage des règles
Les 2 mots clés pour l’héritage des règles sont abstract et extends.
Exemple :
abstract rule A {
from [fromA]
using [usingA]
to [toA]
do [doA]
}
rule B extends A {
from [fromB]
using [usingB]
to [toB]
do [doB]
}
rule C extends B {
from [fromC]
using [usingC]
to [toC]
do [doC]
}
Vous auriez pu aussi écrire l’expression ci-dessous équivalente :
rule B {
from [fromB]
using [usingB]
to [toA.bindings union toB.bindings]
do [doB]
}
rule C {
from [fromC]
using [usingC]
to [toA.bindings union toB.bindings union toC.bindings]
do [doC]
}
ATL ne supporte pas l’héritage multiple (comme C++ par exemple) ainsi que les contraintes suivantes :
- Les pattern d’entrée (partie from) des sous règles (B ou C) doivent correspondre à un sous ensemble des super règles. Par exemple si vous avez une correspondance pour une classe particulière, vous devez avoir un filtre ou une correspondance plus restrictive dans la sous classe.
- Les variables des pattern d’entrée doivent avoir les même noms dans les super et sous règles
- Les noms des variables des pattern de sortie doivent être les même dans les super et sous règles pour les patterns de sortie dont vous voulez l’union.
Exemple complet, tous les éléments du modèle source sont copiés tel quel dans le modèle cible :
module Copy;
create OUT : MM from IN : MM;
rule CopyDataType extends CopyClassifier {
from
s : MM!DataType
to
t : MM!DataType
}
rule CopyEnumeration extends CopyClassifier {
from
s : MM!Enumeration
to
t : MM!Enumeration (
literals <- s.literals
)
}
rule CopyParameter extends CopyTypedElement {
from
s : MM!Parameter
to
t : MM!Parameter
}
rule CopyReference extends CopyStructuralFeature {
from
s : MM!Reference
to
t : MM!Reference (
isContainer <- s.isContainer,
opposite <- s.opposite
)
}
rule CopyTypedElement extends CopyModelElement {
from
s : MM!TypedElement
to
t : MM!TypedElement (
lower <- s.lower,
upper <- s.upper,
isOrdered <- s.isOrdered,
isUnique <- s.isUnique,
type <- s.type
)
}
rule CopyOperation extends CopyTypedElement {
from
s : MM!Operation
to
t : MM!Operation (
parameters <- s.parameters
)
}
rule CopyAttribute extends CopyStructuralFeature {
from
s : MM!Attribute
to
t : MM!Attribute
}
rule CopyEnumLiteral extends CopyModelElement {
from
s : MM!EnumLiteral
to
t : MM!EnumLiteral
}
rule CopyPackage extends CopyModelElement {
from
s : MM!Package
to
t : MM!Package (
contents <- s.contents
)
}
rule CopyClass extends CopyClassifier {
from
s : MM!Class
to
t : MM!Class (
isAbstract <- s.isAbstract,
supertypes <- s.supertypes,
structuralFeatures <- s.structuralFeatures,
operations <- s.operations
)
}
rule CopyClassifier extends CopyModelElement {
from
s : MM!Classifier
to
t : MM!Classifier
}
abstract rule CopyModelElement extends CopyLocatedElement {
from
s : MM!ModelElement
to
t : MM!ModelElement (
name <- s.name
)
}
rule CopyMetamodel extends CopyLocatedElement {
from
s : MM!Metamodel
to
t : MM!Metamodel (
contents <- s.contents
)
}
abstract rule CopyLocatedElement {
from
s : MM!LocatedElement
to
t : MM!LocatedElement (
location <- s.location
)
}
rule CopyStructuralFeature extends CopyTypedElement {
from
s : MM!StructuralFeature
to
t : MM!StructuralFeature (
subsetOf <- s.subsetOf,
derivedFrom <- s.derivedFrom
)
}
"Il faut toujours faire ce que l'on croit ne pas pouvoir faire."
Eleanor Roosevelt
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/
Cours complet sur ATL (ATLAS Transformation Language) : les règles appelées (Called Rules)
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-regles-paresseuses-lazy-rules
nous avion abordé les règles paresseuses (Lazy Rules). Voyons à présent les règles appelées (Called Rules).
Les règles appelées (Called Rules)
Elles permettent de générer explicitement des éléments de modèle cible à partir de code impératif. Excepté pour un “entrypoint”, une règle appelée doit explicitement être invoquée à partir d’un bloc impératif ATL.
Syntaxe :
[using {
var1 : var_type1 = init_exp1;
...
varn : var_typen = init_expn;
}]?
[to
out_var1 : out_type1 (
bindings1
),
out_var2 : distinct out_type2 foreach(e in collection)(
bindings2
),
...
out_varn : out_typen (
bindingsn
)]?
[do {
statements
}]?
}
Description, une règle appelée :
- est identifiée par un nom unique (inclus les nom des helpers), different de “main”
- peut optionnellement être déclarée dans l’entrypoint ATL.
Une transformation ATL peut inclure une seule règle appelée avec un entrypoint.
A la différence des autres règle appelées, celles avec entrypoint n’ont pas besoin d’être invoquées explicitement : elles le sont implicitement au début de l’exécution de la transformation une fois que la phase d’initialisation des modules est terminée.
Une règle appellee peut avoir des paramètres de la même manière que les helpers.
Elle est constituée de 3 sections optionnelles :
- using,
- to,
- do.
Par rapport à une règle de correspondance, une règle appellée n’a pas de section from et la section to est optionnelle.
La sémantique des sections disponibles est la même que pour les règles de correspondances :
- using permet de déclarer et d’initialiser des variables locales visibles du reste de la section using aussi bien que de la to et do;
- to section correspond au pattern cible. Elle contient plusieurs éléments de pattern cible. Contrairement aux règles de correspondances, il n’y a pas d’élément de modèle source qui doivent correspondre pour que les éléments de modèle cible soient initialisés;
- do permet de spécifier un bloc impératif d’instructions. Si une section to est spécifiée, le bloc imperative est execute une fois que le pattern cible est terminé d’être traité.
Exemple :
...
entrypoint rule Metamodel() {
to
t : KM3!Metamodel
do {
thisModule.metamodel <- t;
}
}
Cette règle appellée est définie dans le point d’entré de la transformation. Cela signifie qu’elle est exécutée entre l’initialisation et la phase de correspondance. Il génère un élément de métamodèle. Le code est spécifié à l’intérieur d’un bloc impératif avec une variable (metamodel) définie dans le contexte du module ATL, pointant sur cet élément de modèle. Cela signifie que le métamodèle généré reste accessible pour des futures traitements pendant la transformation.
"Tous les trésors de la terre ne valent pas le bonheur d'être aimé."
Pedro Calderón de la Barca
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/
Cours complet sur ATL (ATLAS Transformation Language) : les règles paresseuses (Lazy Rules)
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-matched-rules-la-section-bloc-imperatif-55
nous avion abordé les “Matched Rules” (les règles de correspondance) et la section bloc impératif. Voyons à présent les règles paresseuses (Lazy Rules).
Les règles paresseuses (Lazy Rules)
Appel d’une « lazy rules »
Exemple d’une « lazy rules » :
from
i: ecore!EObject
to
rel: metamodel!Relationship (
)
}
Appel à partir d’une « matched rule » (règle de correspondance) :
from
s : ecore!EObject
to
t : metamodel!Node (
name <- s.toString(),
edges <- thisModule.getCross(s)
)
}
Appel multiple :
from
s : ecore!EObject
to
t : metamodel!Node (
name <- s.
edges <- ecore!EClass.allInstancesFrom('yourmodel')->collect(e | thisModule.getCross(e))
)
}
Lazy Rules unique
Déclaration :
...
}
Quand une « lazy rules unique » est exécutée, elle renvoie toujours le même élément cible pour un élément source donné. L’élément cible est retrouvé en naviguant dans les liens de traçabilité internes.
Une « lazy rules non unique » ne navigue pas dans les liens traçabilité, et crée un nouvel élément cible à chaque exécution.
"Mieux vaut une conscience tranquille qu'une destinée prospère. J'aime mieux un bon sommeil qu'un bon lit."
Victor Hugo
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/
Cours complet sur ATL (ATLAS Transformation Language) : les “Matched Rules”, la section bloc impératif (5/5)
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-matched-rules-le-pattern-element-cible-45
nous avion abordé les “Matched Rules” (les règles de correspondance) et la section du pattern élément cible. Voyons à présent la section bloc impératif.
La section bloc impératif (5/5)
La dernière section d’une règle de correspondence ATL est la section optionnelle do.
Elle permet de specifier une séquence d’instructions impératives qui seront exécutées une fois que l’initialisation des éléments générés de modèle cible sera terminée.
Par exemple, on l’utiliser pour calculer des “id” pour les éléments de modèles générés.
Exemple :
...
rule Journal2Book {
from
j : Biblio!Journal
to
b : Biblio!Book (
...
)
do {
thisModule.id <- thisModule.id + 1;
b.id <- thisModule.id;
}
}
Une variable globale est définie dans le contexte du module ATL et initialisée à 0.
Pour avoir un id unique, le bloc impératif de la règle de correspondance incrémente la valeur de la variable globale et assigne cette valeur à l’élément généré.
"Tu me dis, j'oublie.
Tu m'enseignes, je me souviens.
Tu m'impliques, j'apprends."
Benjamin Franklin
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/
Cours complet sur ATL (ATLAS Transformation Language) : les “Matched Rules”, le pattern élément cible (4/5)
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-matched-rules-la-section-des-variables-locales-35
nous avion abordé les “Matched Rules” (les règles de correspondance) et la section des variables locales. Voyons à présent la section du pattern élément cible.
Le pattern élément cible (4/5)
La section "to" correspond au pattern cible de la règle, contenant les patterns des éléments cibles.
Cette section est obligatoire et possède au moins un pattern d’élément cible, séparés par une virgule s’il y en a plusieurs.
ATTENTION : le 1er pattern correspond au pattern par défaut de la règle.
Dans ATL, il existe 2 types de pattern d’élément cible : le simple et l’itératif (les patterns itératifs d’éléments sont obsolètes et sont remplacés par les “lazy rules”) .
Chaque pattern correspond à une variable déclarée par son nom ( out_vari) et son type ( out_typei).
Le pattern simple est spécifié comme un “set” de liens définissant la manière dont l’entité (les attributs ou les références) des éléments générés doivent être initialisés.
Syntaxe pour l’initialisation :
Le nom de l’entité initialisée doit se référer à une variable associée à un pattern d’élément cible.
L’expression ( exp) est une expression OCL.
S’il y a plusieurs liens, on les sépare par des virgules.
Il est fortement recommandé d’initialiser les entités plutôt que de se reposer sur le mécanisme par défaut qui peut varier suivant le gestionnaire de modèle utilisé pour accéder aux éléments de modèle.
Exemple complet :
from
j : Biblio!Journal
to
b : Biblio!Book (
title <- j.title + '_(' + j.vol + '):' + j.num,
authors <- j.articles
->collect(e | e.authors)->flatten()->asSet()
chapters <- j.articles,
pagesNb <- j.articles->collect(e | e.pagesNb)->sum()
)
}
Cettte règle génère un élément du modèle Book à partir d’un élément de modèle Journal. Elle initialise les entités title, authors, chapters et pagesNb de l’élément Book cible:
- Le “title” du “Book” correspond au “title” du “journal” concaténé avec “vol” et num;
- Le “chapters” du “Book” correspond aux éléments de modèle qui seront générés à partir de “articles” de “Journal”;
- L’entité “authors” de “Book” correspond à tous les “authors” des différents “articles” de “Journal” sans doublon;
- L’attribut “pagesNb” est initialisé avec la somme des nombres de page (pagesNb) de tous les articles du modèle source “Journal”.
3 cas d’assignation possible :
- Référence à un élément de modèle cible généré dans la règle courante;
- Référence à un élément par défaut de modèle cible d’une autre règle;
- Référence à un élément de modèle cible d’une autre règle.
Premier cas : la reference est simplement initialisée avec l’élément local correspondant à l’élément du modèle cible.
from
i : MM_A!ClassA
to
o_1 : MM_B!Class1 (
linkToClass2 <- o_2
),
o_2 : MM_B!Class2 (
...
)
}
Deuxième cas :
La reference doit être initialisée avec l’élément de modèle source correspondant à une autre règle. Dans l’exemple suivant, la règle Case2_R1 génère un élément de modèle cible ( o_1) qui a une référence à un élément de modèle cible correspondant au pattern cible par défaut ( o_1) de la règle Case2_R2., à condition que l’élément de modèle source correspondant à Case2_R1 possède une référence ( linkToClassB) à la classe MM_A!ClassB du e l’élément de modèle source :
from
i : MM_A!ClassA
to
o_1 : MM_B!Class1 (
linkToClass2 <- i.linkToClassB
)
}
rule Case2_R2 {
from
i : MM_A!ClassB
to
o_1 : MM_B!Class2 (
...
),
...
}
La reference est initialisée avec l’élément de modèle source correspondant à Case2_R2 quand l’élément de modèle cible MM_B!Class2 est générée.
3ème cas correspondant à initialiser une référence avec un élément de pattern cible non par défaut d’une autre règle.
On utilise alors l’opération resolveTemp() définie dans le context du module ATL. Cette operation permet d’accéder à des éléments de modèle cible associés à des éléments de pattern cible d’une autre règle.
Elle accepte 2 paramètres :
- l’élément de modèle source correspondant à l’autre règle pour générer l’élément de modèle cible
- et le nom de l’élément de pattern cible auquel il est associé.
Exemple :
from
i : MM_A!ClassA
to
o_1 : MM_B!Class1 (
linkToClass2 <- thisModule.resolveTemp(i.linkToClassB, 'o_n')
)
}
rule Case3_R2 {
from
in : MM_A!
to
o_1 : MM_B!Class3 (
...
),
...
o_n : MM_B!Class2 (
...
),
...
}
Quand plusieurs modèles de sortie sont conformes au même métamodèle alors le mot clé in permet de specifier le modèle de sortie.
Exemple :
to
o : MM_B!Class2 in OUT2
"Il est bien des choses qui ne paraissent impossibles que tant qu'on ne les a pas tentées."
André Gide
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/
Cours complet sur ATL (ATLAS Transformation Language) : les “Matched Rules”, la section des variables locales (3/5)
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-matched-rules-la-section-from-pattern-source-25
nous avion abordé les “Matched Rules” (les règles de correspondance) et la section “from” (pattern source). Voyons à présent la section des variables locales.
La section des variables locales (3/5)
La section optionnelles using permet de déclarer des variables locales utilisables dans cette section using (mais ne peuvent pas être invoquée avant cette déclaration) ainsi que dans les sections to et do. Chaque variable est identifiée par son nom (vari) et son type (var_typei) et doit être initialisée en utilisant une expression OCL.
Exemple :
c : GeometricElement!Circle
using {
pi : Real = 3.14;
area : Real = pi * c.radius.square();
}
"Le besoin de créer est dans l'âme comme le besoin de manger dans le corps."
Christian Bobin
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/
Cours complet sur ATL (ATLAS Transformation Language) : les “Matched Rules”, la section “from” (pattern source) (2/5)
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-les-matched-rules-les-regles-de-correspondance-presentation-15
nous avion abordé une présentation des “Matched Rules” (les règles de correspondance). Voyons à présent la section “from” (pattern source).
La section “from” (pattern source) (2/5)
La section “from” correspond au pattern source.
Ce pattern contient la variable de la source (in_var).
Cette déclaration spécifie le type de l’élément de modèle source défini par la règle (in_type).
Il peut contenir aussi (entre crochet) une expression booléenne (condition) permettant de d’extraire un sous ensemble des éléments du modèle source conforme au type source.
S’il n’y a pas de condition explicite alors tous les éléments du modèle souce conforme au type source seront en entrée de la règle.
Exemple :
p : MMPerson!Person (
p.name = 'Smith'
)
Autre exemple :
p : MMPerson!Person (
true
est equivalent à
p : MMPerson!Person
La partie declaration peut specifier le modèle d’entrée à partir duquel les éléments seront considérés pour la correspondance. Quand plusieurs modèles en entrée sont conformes au même métamodèle , le mot clé in permet de d’avoir seulement les éléments du nom de modèle spécifié.
Exemple :
Exemple où on ne considère que les éléments IN2 :
p : MMPerson!Person in IN2
"Il faut craindre que l'ambition ne soit la couverture de l'orgueil, mais que la modestie ne soit qu'un prétexte à la paresse."
Henri Monnier
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/
Cours complet sur ATL (ATLAS Transformation Language) : les “Matched Rules” (les règles de correspondance), présentation (1/5)
Dans l'article précédent :
https://www.urbanisation-si.com/cours-complet-sur-atl-atlas-transformation-language-le-code-imperatif-atl-linstruction-de-boucle-for
nous avion abordé le code impératif ATL et l’instruction de boucle : for. Voyons à présent une présentation des “Matched Rules” (les règles de correspondance).
Les “Matched Rules” (les règles de correspondance), présentation (1/5)
Elles permettent de spécifier comment les éléments de modèle cible sont générés à partir des éléments de modèle source.
Pour parvenir à cet objectif, une règle de correspondance doit spécifier :
- Quels éléments de modèle source doivent être mis en correspondance
- Le nombre et le type d’éléments générés de modèle cible
- La manière dont ces éléments de modèle cible doivent être initialisés à partir des éléments sources.
La spécification d’une règle de correspondance doit se conformer à la syntaxe suivante :
from
in_var : in_type [in model_name]? [(
condition
)]?
[using {
var1 : var_type1 = init_exp1;
...
varn : var_typen = init_expn;
}]?
to
out_var1 : out_type1 [in model_name]? (
bindings1
),
out_var2 : distinct out_type2 foreach(e in collection)(
bindings2
),
...
out_varn : out_typen [in model_name]? (
bindingsn
)
[do {
statements
}]?
}
- Chaque règle est identifiée par son nom ( rule_name).
- Le nom d’une règle de correspondance est unique dans une transformation ATL.
- Elle est composée de 2 sections obligatoires ( from et to ) et 2 optionnelles (using et do).
- Les variables déclarées dans la portée de la règle ( les patterns d’éléments sources et cibles et les variables ) ont un nom unique. Cette restriction ne s’applique pas aux expressions OCL contenues dans la règle.
"Il n'arrive que rarement de voir un individu, sous la pression d'événements exceptionnels, réviser l'image qu'il a de sa propre intelligence et de ses limites au point de s'ouvrir de nouvelles perspectives sur ce qu'il est capable d'apprendre."
Seymour Papert
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/