SlideShare una empresa de Scribd logo
1 de 18
Descargar para leer sin conexión
Refractoring Java Generics by Inferring Wildcards, In
Practic
Michel Mathieu, Nadarajah Mag-Stellon
2014/2015
Table des mati`eres
1 Introduction 2
2 D´efinition de la variance 3
2.1 Pr´emisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Variance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2.1 La covariance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2.2 La contravariance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3 Cas concret d’utilisation 6
4 Le fonctionnement de l’outil 8
4.1 La syntaxe de la variance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.2 L’analyse de l’influence des types . . . . . . . . . . . . . . . . . . . . . . . 9
4.2.1 Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4.2.2 L’algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
5 Les Applications de l’outil 14
6 Conclusion 17
Chapitre 1
Introduction
Ce rapport est un r´esum´e de l’article intitul´e ”Refactoring Java Generics by Inferring
Wildcards, In Practice” ´ecrit par John Altidor et Yannis Smaragdakis. Cet article traite
d’un outil, un algorithme, permettant de renommer et inf´erer des types plus g´en´eriques
d’instances de g´en´eriques Java en utilisant des Wildcards. Des statistiques ont montr´e que
sur les six principales librairies Java utilisant les g´en´eriques, 34% des d´eclarations valables
de signatures de type variant peuvent ˆetre g´en´eralis´ees, c’est `a dire avec des types wildcard
plus g´en´eraux. Or, pour une g´en´eralisation, il faut en moyenne mettre `a jour 146 autres
d´eclarations. Cela montre qu’il est tr`es fastidieux de le faire `a la main .
C’est dans cette perspective que nous allons ´etudier les principes de cet outil et voir
quelques exemples o`u celui ci pourrait am´eliorer notre code. Nous ´etudierons dans un
second temps sa s´emantique, ainsi que les principes de g´en´eralisations avec ses probl`emes
et les solutions apport´ees. Nous analyserons ensuite son algorithme pour enfin terminer
par ses applications.
Chapitre 2
D´efinition de la variance
2.1 Pr´emisse
La maintenance, la s´ecurit´e et la fiabilit´e des programmes Java augmentent quand les
librairies sont r´enomm´ees pour d´efinir des classes g´en´eriques. En effet, les g´en´eriques per-
mettent `a l’utilisateur d’indiquer au compilateur le type des ´el´ements dans une collection
et donc d’augmenter la s´ecurit´e en ´eliminant les cast douteux. Seulement, les g´en´eriques
restreignent le sous typage comme nous le verrons dans un exemple ci-dessous.
Le m´ecanisme de variance dans les langages de programmation modernes essaie de r´esoudre
le probl`eme en autorisant deux instanciations d’un g´en´erique qui est sous type d’un autre.
Le syst`eme de typage java utilise lui, le concept de ”wildcard”. C’est `a dire, lors de l’uti-
lisation d’une classe, nous pouvons choisir de sp´ecifier si elle r´ef`ere `a une ”covariante”
”contravariante” ou ”invariante” version de la classe.
2.2 Variance
Afin de mieux comprendre les principes de l’outil, il est n´ecessaire de comprendre la
notion de variance. Prenons un exemple, en regardant la diff´erence entre les tableaux et
les listes Java. Commen¸cons par les tableaux :
Number [ ] nombre = new Number [ 3 ] ;
nombre [ 0 ] = new Integer (10) ;
nombre [ 1 ] = new Double (3.14) ;
nombre [ 2 ] = new Byte (0) ;
On peut voir ici qu’un tableau peut contenir des ´el´ements de type T et de n’importe
quel sous type de celui-ci. Java fait ´egalement ´etat qu’un tableau S[] est un sous type de
T[] si S est sous type de T. On peut alors ´ecrire :
Integer [ ] e n t i e r s = {1 ,2 ,3 ,4};
Number [ ] nombre = e n t i e r s ; // correct car Integer est sous type de Number
En revanche, avec les listes, cela soul`eve des probl`emes :
2.2 Variance 4
List<Integer > e n t i e r s = new ArrayList<Integer >() ;
e n t i e r s . add (1) ;
e n t i e r s . add (2) ;
List<Number> nombres = e n t i e r s ; // erreur de compilation
Il y a un probl`eme avec les types g´en´eriques. Le compilateur nous interdit formellement
de faire ¸ca. Tout ceci affecte le pouvoir du polymorphisme en java. La solution est d’utiliser
les outils des g´en´eriques java : la covariance et la contravariance.
2.2.1 La covariance
Ici, au lieu d’utiliser un type T comme argument de notre type g´en´erique, on utilise
une ”wildcard” <?extendsT > :
List <? extends Number> maliste = new ArrayList<Integer >() ;
List <? extends Number> maliste = new ArrayList<Float >() ;
List <? extends Number> maliste = new ArrayList<Double >() ;
Avec la covariance, nous pouvons lire des ´el´ements d’une structure, mais rien n’´ecrire
dedans. Ainsi, ”Number n = maliste.get(0) ;” est autoris´e.
En revanche ”maliste.add(3.14) ;” est refus´e. En effet, le compilateur ne peut d´eterminer le
type exact de l’objet dans la structure g´en´erique. Cela peut ˆetre n’importe quoi qui ´etend
Number, mais le compilateur ne peut en ˆetre certain. Ainsi, toute tentative de retrouver
une valeur g´en´erique est consid´er´ee comme une op´eration non sˆure et est donc rejet´ee
imm´ediatement par le compilateur.
2.2.2 La contravariance
Ici, on utilise une wildcard diff´erente : <?superT >. La contravariance nous permet de
faire l’op´eration oppos´ee. Nous pouvons lire dans une structure mais pas ´ecrire.
List<Object> myObjs = new List<Object () ;
myObjs . add ( ” Hello ” ) ;
myObjs . add ( ”World” ) ;
List <? super Number> nombres = myObjs ;
nombres . add (10) ;
Dans ce cas, nous pouvons bien ajouter un Number dans la liste nombres car Number
a pour ancˆetre Object. En revanche, ”Number n = nombres.get(0) ;” produit une erreur de
compilation. En effet nous ne sommes pas sˆurs `a 100% d’avoir un Number. Si le compilateur
laissait passer cela, nous pourrions avoir `a l’ex´ecution une ClassCastException. En somme,
nous utilisons la covariance quand nous voulons seulement lire une valeur g´en´erique dans
une structure et la contravariance quand on veut ´ecrire dedans. Un dernier exemple pour
illustrer :
2.2 Variance 5
public s t a t i c void copy ( List <? extends Number> source ,
List <? super Number> destiny ) {
f or (Number number : source ) {
destiny . add (number) ;
}
}
List<Integer > myInts = asList (1 ,2 ,3 ,4) ;
List<Object> myObjs = new ArrayList<Object >() ;
copy ( myInts , myObjs) ;
Tous les types g´en´eriques sont ´etiquet´es comme inh´erents `a la covariance, contrava-
riance, bivariant ou invariant au type de leurs param`etres. Cette inh´erence peut donc ˆetre
employ´ee `a tous les types g´en´eriques.
Par exemple, nous pouvons changer de mani`ere raisonnable toutes les occurences de Iterator <
T > en Iterator <?extendsT > ou bien Comparator < T > en Comparator <?superT >.
Des chercheurs ont alors d´evelopp´e un outil afin d’am´eliorer cette g´en´eralisation. Il poss`ede
diff´erentes fonctionnalit´es :
1. Pour aider le programmeur `a utiliser la variance en Java, il permet de r´e´ecrire
automatiquement le code en un code avec des wildcards plus g´en´erales.
2. Cependant, tous les types ne peuvent pas ˆetre r´e´ecris, (ex : s’ils sont d´eclar´es dans
une tierce autre librairie o`u le code source n’est pas disponible). Ainsi l’utilisateur
peut choisir de ne pas r´e´ecrire le code, si garder un type sp´ecifique est pr´ef´erable
pour une future mise `a jour.
3. L’outil respecte la s´emantique Java et pr´eserve le comportement du programme.
Chapitre 3
Cas concret d’utilisation
Apr`es avoir les principes de la covariance et la contravariance, nous allons voir main-
tenant un exemple d’utilisation de l’outil pour renommer des entit´es d’un programme.
Prenons le programme suivant :
c l a s s WList<E> {
private List<E> elems = new LinkedList<E>() ;
void add (E elem ) {
addAll ( C o l l e c t i o n s . s i n g l e t o n L i s t ( elem ) ) ;
}
void addAll ( List<E> source ) {
addAndLog( source . i t e r a t o r () , t h i s . elems ) ;
}
s t a t i c <T> void addAndLog( Iterator <T> itr , List<T> dest ) {
while ( i t r . hasNext () ) {
T elem = i t r . next () ;
log ( elem ) ;
dest . add ( elem ) ;
}
}
De mani`ere g´en´erale, l’interface List est invariante. c’est `a dire qu’elle autorise la lecture
et l’´ecriture d’un ´el´ement. Or dans la m´ethode addAndLog, pour la liste dest rien n’est
lu. On ne fait qu’ajouter un ´el´ement avec add. On peut alors se limiter `a une version
contravariante de List en faisant un List <?superT > dest. Pour source, la seule m´ethode
invoqu´ee est iterator() qui retourne un Iterator < E >. Or Iterator est covariant comme
nous l’avons vu pr´ec´edemment. On peut alors de mani`ere sˆure inf´erer le type de source en
List <?extendsT >. Cependant, si on ne changeait que le type de source, le programme
ne compilerait pas. En effet, la m´ethode addLog attend un Iterator < T > mais on lui
fournit maintenant un Iterator <?extendsT > avec source. Une analyse du programme
est alors n´ecessaire pour savoir si la g´en´eralisation d’un type entraˆıne le changement de
type d’autres d´eclarations. Ce flot d’analyse doit prendre en compte les d´ependances entre
7
chaque. Ici, nous pouvons alors changer le type de itr en Iterator <?extendsT >. Nous
obtenons alors :
c l a s s WList<E> {
private List<E> elems = new LinkedList<E>() ;
void add (E elem ) {
addAll ( C o l l e c t i o n s . s i n g l e t o n L i s t ( elem ) ) ;
}
void addAll ( List <? entends E> source ) {
addAndLog( source . i t e r a t o r () , t h i s . elems ) ;
}
s t a t i c <T> void addAndLog( Iterator <? extends T> itr , List <? super T> dest )
{
while ( i t r . hasNext () ) {
T elem = i t r . next () ;
log ( elem ) ;
dest . add ( elem ) ;
}
}
Apr`es avoir vu un exemple de son utilisation, nous allons maintenant ´etudier son fonc-
tionnement.
Chapitre 4
Le fonctionnement de l’outil
4.1 La syntaxe de la variance
L’outil de refractoring permet d’inf´erer la variance des types rencontr´es dans un pro-
gramme.
La variance dans le langage Java est implicite. En effet, il n’y pas de syntaxe pour que le
programmeur puisse d´efinir la variance d’un type.
Contrairement, au langage Scala o`u il est possible de d´efinir la covariance et la contrava-
riance par, respectivement, les annotations + et -. En Scala, par d´efaut, un ´el´ement est
invariant.
L’outil de refractoring va donc se baser sur un ensemble de r`egles et s’inspirer de la syntaxe
de Scala pour la d´efinition de la variance.
Intuitivement, la variance d’un ´el´ement est contraint par l’utilisation qu’on en fait. Par
exemple, le type des param`etres d’une m´ethode est g´en´eralement contravariant et le type
de retour d’une m´ethode est g´en´eralement covariant.
Ainsi, notons vx la variance de la variable X. Et, essayons de d´eterminer la variance de
quelques ´el´ements sur un exemple plutˆot simple :
i n t e r f a c e RList<X> { X get ( int i ) ; }
i n t e r f a c e WList<Y> { void set ( int i , Y y) ; }
i n t e r f a c e IList <Z> { Z setAndGet ( int i , Z z ) ; }
Dans l’interface RList, on remarque que la variable X est covariante car elle est le retour
de la m´ethode get. On note cela vx = + et se lit X est covariant dans RList.
Dans l’interface WList vY = - (contravariant) car Y est un des param`etres de la m´ethode
set.
Dans l’interface IList vz = o (invariant) car Z est `a la fois covariant et contravariant.
4.2 L’analyse de l’influence des types 9
C’est de cette mani`ere que l’on peut d´eterminer la variance d’un ´el´ement `a partir d’une
d´efinition g´en´erique.
Apr`es avoir inf´erer une g´en´eralisation pour un type donn´e T, l’outil de refractoring permet
de remplacer le type T par sa g´en´eralisation.
En prenant l’exemple ci-dessous, l’outil de refractoring effectue les substitutions suivantes :
i n t e r f a c e RList<X> { X get ( int i ) ; }
i n t e r f a c e WList<Y> { void set ( int i , <? super Y> y) ; }
i n t e r f a c e IList <Z> { Z setAndGet ( int i , Z z ) ; }
4.2 L’analyse de l’influence des types
4.2.1 Le principe
Le fait de g´en´eraliser les types d’un programme implique de nombreux compromis. En
effet, plusieurs probl`emes apparaissent lors de la g´en´eralisation d’un type :
1. G´en´eraliser une List < String > par une List <? extends String > pose un certain
probl`eme. C’est un exemple qui montre qu’en Java, il est impossible de red´efinir
La classe String. Il faut donc se poser la question des classes, des m´ethodes ...
immuables en Java.
2. La red´efinition de m´ethode est possible uniquement si les param`etres de la m´ethode
du fils sont identiques `a celle du p`ere. Ainsi, lorsque l’on g´en´eralise les types des pa-
ram`etres d’une m´ethode fils, Java ne consid`ere plus cette m´ethode comme red´efinition
de m´ethode de la m´ethode p`ere. Or, on voudrait que ¸ca soit le cas.
3. La g´en´eralisation d’un type peut amener `a g´en´eraliser d’autres ´el´ements qui sont
plus ou moins d´ependant de ce type. L’outil de refractoring ne doit pas ajouter
d’erreur de compilation et ne doit pas modifier la s´emantique du programme.
Ces probl`emes sont r´esolus en r´ealisant un graphe orient´e des influences sur les d´eclarations
dans le programme.
Ainsi, l’outil de refractoring construit un graphe d’influence ; Pour chaque d´ependance entre
les entit´es (variable, signature de m´ethode ...) A et B, il existe une arˆete qui lie les nœuds
correspondant aux entit´es A et B dans ce graphe.
Par la suite, lorsque l’on g´en´eralise l’entit´e A, on parcourt le graphe d’influence en g´en´eralisant
les noeuds connexe au noeud de l’entit´e A.
Pour pallier aux soucis 1, l’outil de refractoring d´ecide quels ´el´ements ne peuvent pas
ˆetre g´en´eralis´es.
Concernant le probl`eme 2, l’outil va consid´erer que la signature des param`etres de la
4.2 L’analyse de l’influence des types 10
m´ethode m du fils est fortement d´ependante de la signature de la m´ethode m du p`ere.
Dans le graphe d’influence, on va donc ajouter une arˆete entre la signature de la m´ethode
p`ere et celle du fils.
Pour donner une exemple clair au probl`eme 3, si on g´en´eralise le type de retour d’une
m´ethode M alors les variables qui sont affect´ees par la valeur du r´esultat de la m´ethode M
doivent ˆetre g´en´eralis´es. Il y aura donc un chemin dans le graphe d’influence qui va lier la
m´ethode M et les variables affect´ees par la valeur de M.
Prenons, un autre exemple, si l’on g´en´eralise les param`etres p1 et p2 d’une m´ethode M. Et
si dans le corps de cette m´ethode M, un objet O fait un appel `a la m´ethode O.m(p1, p2).
Alors il faudra g´en´eraliser la signature de la m´ethode O.m. Il existe donc un chemin dans
le graphe d’influence entre l’objet O et les param`etres p1 et p2.
4.2.2 L’algorithme
Les noeuds du graphe d’influence poss`ede la syntaxe abstraite suivante :
Figure 4.1 – Syntaxe du graphe d’influence
FieldDeclaration est la repr´esentation des variables de classes ou d’objet.
V ariableDeclaration correspond `a la d´eclaration de variables locales.
ParameterDeclarations correspond aux param`etres des m´ethodes ou des constructeurs.
MethodDecl correspond au type de retour d’une m´ethode.
On va ´egalement d´efinir un langage pour d´ecrire les programmes Java. Ce langage nous
permettra de d´efinir des fonctions qui nous seront utiles pour l’algorithme d’analyse de l’in-
fluence des types et permet d’abstraire la complexit´e de la repr´esentation d’un programme
Java.
4.2 L’analyse de l’influence des types 11
Figure 4.2 – Mini langage
Avec cette syntaxe, on va pouvoir expliciter la variance des types par v ou w. Et, le
et T sont respectivement la d´enotation du mot cl´e extends de Java et d’un tableau de
T1, T2, ...Tn
D´efinissons les r`egles des fonctions nodesAffectingType(e) et destinationNode(e) en
utilisant ce langage :
Figure 4.3 – Fonctions utilis´es par l’algorithme
4.2 L’analyse de l’influence des types 12
Explicitons ces fonctions.
nodesAffectingType(e) permet de retrouver l’ensemble des d´eclarations accesibles dans e
qui peut modifier le type de e. Et, destinationNode(e) donne l’ensemble des d´eclarations
d´ependant de e. Ces fonctions seront tr`es utilis´ees dans l’algorithme.
Pour chacune de ces fonctions, on a d´efini trois r`egles. Par exemple, la r`egle N-MonoMethod
d´eclare que si le retour de la m´ethode m ne d´epend pas de e alors seule la d´eclaration de
m peut affecter le type < T > m < e >.
Parlons de l’algorithme de cr´eation du graphe d’influence. L’algorithme effectue trois pas-
sages sur le programme pour analyser :
1. Les appels de m´ethode : pour chaque appel de m´ethode < T > m < e > , on va
retrouver les d´eclarations de e dans le programme. On va ´egalement retrouver les
m´ethodes qui prennent exactement e en param`etre. Et, on va rajouter une arˆete
entre e et les param`etres des m´ethodes trouv´ees pr´ec´edement.
2. Les expressions : pour chaque expression e , on cherche les d´eclarations D qui sont
affect´ees par e. Et, pour chaque d´eclaration N qui est accessible par e et qui peut
affecter e, on relie dans le graphe d’influence N et D.
3. Les d´eclarations de m´ethode : pour chaque d´eclaration de m´ethode M, on va trouver
les m´ethodes M qui red´efinissent ou sont r´ed´efinies par M. On va ajouter une arˆete
dans le graphe entre les param`etres des methodes M et M .
L’ensemble de ces r`egles permettent de construire le graphe d’influence d’un programme
Java Voici un pseudo code de l’algorithme :
4.2 L’analyse de l’influence des types 13
Figure 4.4 – Pseudo code de l’algorithme du graphe d’influence
Chapitre 5
Les Applications de l’outil
Apr`es avoir vu comment fonctionnait l’outil, nous pouvons voir que plus le nombre de
d´eclarations augmente dans le graphe, et plus le nombre de d´eclarations immuables fait
de mˆeme. Ainsi, moins de d´eclarations seront r´e´ecrites parce qu’il existera plus d’arˆetes
o`u les r´e´ecritures sont interdites dans le graphe. Pour palier ce probl`eme, les chercheurs
ont pens´e qu’il fallait que l’analyse du programme ignore les d´eclarations qui ne peuvent
ˆetre aff´ect´ees par la g´en´eralisation, c’est `a dire ne pas les mettre dans le graphe. Voyons
certains exemples de types que le flot d’analyse ignore :
1. Les types primitifs tels que les int, char, boolean ainsi que les types monomorphiques
comme String et Object. Ces types ne peuvent pas ˆetre modifi´es avec des wildcards.
2. Les types param´etriques qui sont sp´ecifi´es bivariant ( ¡ ?¿ ). Ces types ne peuvent
pas ˆetre plus g´en´eralis´es qu’ils ne le sont d´ej`a.
L’outil permet donc de g´en´eraliser des classes en s´el´ectionnant quelles d´eclarations
parmi les variables locales, les arguments ou retour de m´ethodes lesquels sont `a renommer.
Des travaux pr´ec´edents ont montr´e que 53% des interfaces et 37% des classes peuvent ˆetre
g´en´eralis´ees. Ceci montre alors l’impact que pourrait avoir cet outil si toutes ces d´eclarations
´etaient r´e´ecrites. Il aiderait ´egalement les utilisateurs qui n’ont pas de grandes notions de
variance `a am´eliorer les performances de leur code. Afin d’´evaleur le potentiel de cet outils,
des statistiques ont permis de calculer combien de d´eclarations de types param´etriques
pouvaient ˆetre r´e´ecrites. L’outil `a ´et´e test´e sur six librairies java. Nous n’en montrerons
que trois ici :
15
Figure 5.1 – Statistiques des r´e´ecritures de toutes les d´eclarations pour les types
g´en´eriques
Prenons ici l’exemple des interfaces java, il existe 170 interfaces avec des types pa-
ram´etr´es. Parmi celles l`a, 148 peuvent ˆetre r´e´ecrites. Apr`es le passage de l’outil, 34 ont ´et´e
r´e´ecrites, soit 20%. Sur l’ensemble des six librairies test´ees, nous obtenons un total 12% de
r´e´ecritures en prenant compte les classes et les interfaces, sur un potentiel de 73%. Cela
repr´esente tout de mˆeme 2220 sur 18259 r´e´ecritures.
16
Figure 5.2 – Statistiques des r´e´ecritures de toutes les d´eclarations pour les types variant
Pour les types variant, nous voyons que nous obtenons de bien meilleures performances.
Sur l’ensemble des six librairies, on obtient un total de 34% de renommage.
De plus, la r´e´ecriture seule de JDK ne prend que deux minutes pour 198 milles lignes de
code.
Chapitre 6
Conclusion
En conclusion, apr`es avoir vu quelques exemples d’utilisations ainsi que son fonctionne-
ment, nous pouvons voir que cet outil complexe nous permet d’am´eliorer les perfermances
de notre code en g´en´eralisant le plus possible les types param´etriques `a l’aide de wildcards.
Cependant, en regardant les statistiques sur le pourcentage de renommage apr`es le pas-
sage de l’outil sur les six principales librairies Java, 34% des g´en´eriques ont pu ˆetre plus
sp´ecifiques avec des wildcards plus g´en´eralis´ees. Nous pouvons alors penser que cet outil
peut encore ˆetre am´elior´e. Des travaux futurs ont ´et´e evoqu´e dans ce sens.

Más contenido relacionado

La actualidad más candente (7)

Slides octave1
Slides octave1Slides octave1
Slides octave1
 
test doc
test doctest doc
test doc
 
INF120 - Algo DUT SRC1 - Cours 2
INF120 - Algo DUT SRC1 - Cours 2INF120 - Algo DUT SRC1 - Cours 2
INF120 - Algo DUT SRC1 - Cours 2
 
Cours de JAVA de base
Cours de JAVA  de baseCours de JAVA  de base
Cours de JAVA de base
 
Cours java
Cours javaCours java
Cours java
 
Chapitre1: Langage Python
Chapitre1: Langage PythonChapitre1: Langage Python
Chapitre1: Langage Python
 
Chapitre 2 classe et objet
Chapitre 2   classe et objetChapitre 2   classe et objet
Chapitre 2 classe et objet
 

Similar a Refractoring java generics by inferring wildcards

Javascript : que fait ce code?
Javascript : que fait ce code?Javascript : que fait ce code?
Javascript : que fait ce code?
Ruau Mickael
 
Real Time Meta Events
Real Time Meta EventsReal Time Meta Events
Real Time Meta Events
kerush
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logicielle
cyrilgandon
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
guest6e3bed
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
JS Bournival
 

Similar a Refractoring java generics by inferring wildcards (20)

Introduction java
Introduction javaIntroduction java
Introduction java
 
575
575575
575
 
Structure de Contrôle
Structure de Contrôle Structure de Contrôle
Structure de Contrôle
 
POO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdfPOO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdf
 
Les tests-unitaires-en-java
Les tests-unitaires-en-javaLes tests-unitaires-en-java
Les tests-unitaires-en-java
 
Chap1lla génèricité.pptx
Chap1lla génèricité.pptxChap1lla génèricité.pptx
Chap1lla génèricité.pptx
 
Javascript : que fait ce code?
Javascript : que fait ce code?Javascript : que fait ce code?
Javascript : que fait ce code?
 
Real Time Meta Events
Real Time Meta EventsReal Time Meta Events
Real Time Meta Events
 
Apprentissage du java
Apprentissage du javaApprentissage du java
Apprentissage du java
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logicielle
 
introJavaScript.ppt
introJavaScript.pptintroJavaScript.ppt
introJavaScript.ppt
 
Généralités sur la notion d’Algorithme
Généralités sur la notion d’AlgorithmeGénéralités sur la notion d’Algorithme
Généralités sur la notion d’Algorithme
 
cours d'algorithmique et programmation 3sc final .pdf
cours d'algorithmique et programmation 3sc final .pdfcours d'algorithmique et programmation 3sc final .pdf
cours d'algorithmique et programmation 3sc final .pdf
 
Cours java script
Cours java scriptCours java script
Cours java script
 
UML : Diagrammes de cas d'utilisation -- modele detaille -- 15
UML : Diagrammes de cas d'utilisation -- modele detaille -- 15UML : Diagrammes de cas d'utilisation -- modele detaille -- 15
UML : Diagrammes de cas d'utilisation -- modele detaille -- 15
 
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
Fork / Join, Parallel Arrays, Lambdas : la programmation parallèle (trop ?) f...
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 
Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016Retours sur java 8 devoxx fr 2016
Retours sur java 8 devoxx fr 2016
 
Librairies Java qui changent la vie
Librairies Java qui changent la vieLibrairies Java qui changent la vie
Librairies Java qui changent la vie
 

Refractoring java generics by inferring wildcards

  • 1. Refractoring Java Generics by Inferring Wildcards, In Practic Michel Mathieu, Nadarajah Mag-Stellon 2014/2015
  • 2. Table des mati`eres 1 Introduction 2 2 D´efinition de la variance 3 2.1 Pr´emisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Variance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2.1 La covariance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.2.2 La contravariance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 3 Cas concret d’utilisation 6 4 Le fonctionnement de l’outil 8 4.1 La syntaxe de la variance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 4.2 L’analyse de l’influence des types . . . . . . . . . . . . . . . . . . . . . . . 9 4.2.1 Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.2.2 L’algorithme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 5 Les Applications de l’outil 14 6 Conclusion 17
  • 3. Chapitre 1 Introduction Ce rapport est un r´esum´e de l’article intitul´e ”Refactoring Java Generics by Inferring Wildcards, In Practice” ´ecrit par John Altidor et Yannis Smaragdakis. Cet article traite d’un outil, un algorithme, permettant de renommer et inf´erer des types plus g´en´eriques d’instances de g´en´eriques Java en utilisant des Wildcards. Des statistiques ont montr´e que sur les six principales librairies Java utilisant les g´en´eriques, 34% des d´eclarations valables de signatures de type variant peuvent ˆetre g´en´eralis´ees, c’est `a dire avec des types wildcard plus g´en´eraux. Or, pour une g´en´eralisation, il faut en moyenne mettre `a jour 146 autres d´eclarations. Cela montre qu’il est tr`es fastidieux de le faire `a la main . C’est dans cette perspective que nous allons ´etudier les principes de cet outil et voir quelques exemples o`u celui ci pourrait am´eliorer notre code. Nous ´etudierons dans un second temps sa s´emantique, ainsi que les principes de g´en´eralisations avec ses probl`emes et les solutions apport´ees. Nous analyserons ensuite son algorithme pour enfin terminer par ses applications.
  • 4. Chapitre 2 D´efinition de la variance 2.1 Pr´emisse La maintenance, la s´ecurit´e et la fiabilit´e des programmes Java augmentent quand les librairies sont r´enomm´ees pour d´efinir des classes g´en´eriques. En effet, les g´en´eriques per- mettent `a l’utilisateur d’indiquer au compilateur le type des ´el´ements dans une collection et donc d’augmenter la s´ecurit´e en ´eliminant les cast douteux. Seulement, les g´en´eriques restreignent le sous typage comme nous le verrons dans un exemple ci-dessous. Le m´ecanisme de variance dans les langages de programmation modernes essaie de r´esoudre le probl`eme en autorisant deux instanciations d’un g´en´erique qui est sous type d’un autre. Le syst`eme de typage java utilise lui, le concept de ”wildcard”. C’est `a dire, lors de l’uti- lisation d’une classe, nous pouvons choisir de sp´ecifier si elle r´ef`ere `a une ”covariante” ”contravariante” ou ”invariante” version de la classe. 2.2 Variance Afin de mieux comprendre les principes de l’outil, il est n´ecessaire de comprendre la notion de variance. Prenons un exemple, en regardant la diff´erence entre les tableaux et les listes Java. Commen¸cons par les tableaux : Number [ ] nombre = new Number [ 3 ] ; nombre [ 0 ] = new Integer (10) ; nombre [ 1 ] = new Double (3.14) ; nombre [ 2 ] = new Byte (0) ; On peut voir ici qu’un tableau peut contenir des ´el´ements de type T et de n’importe quel sous type de celui-ci. Java fait ´egalement ´etat qu’un tableau S[] est un sous type de T[] si S est sous type de T. On peut alors ´ecrire : Integer [ ] e n t i e r s = {1 ,2 ,3 ,4}; Number [ ] nombre = e n t i e r s ; // correct car Integer est sous type de Number En revanche, avec les listes, cela soul`eve des probl`emes :
  • 5. 2.2 Variance 4 List<Integer > e n t i e r s = new ArrayList<Integer >() ; e n t i e r s . add (1) ; e n t i e r s . add (2) ; List<Number> nombres = e n t i e r s ; // erreur de compilation Il y a un probl`eme avec les types g´en´eriques. Le compilateur nous interdit formellement de faire ¸ca. Tout ceci affecte le pouvoir du polymorphisme en java. La solution est d’utiliser les outils des g´en´eriques java : la covariance et la contravariance. 2.2.1 La covariance Ici, au lieu d’utiliser un type T comme argument de notre type g´en´erique, on utilise une ”wildcard” <?extendsT > : List <? extends Number> maliste = new ArrayList<Integer >() ; List <? extends Number> maliste = new ArrayList<Float >() ; List <? extends Number> maliste = new ArrayList<Double >() ; Avec la covariance, nous pouvons lire des ´el´ements d’une structure, mais rien n’´ecrire dedans. Ainsi, ”Number n = maliste.get(0) ;” est autoris´e. En revanche ”maliste.add(3.14) ;” est refus´e. En effet, le compilateur ne peut d´eterminer le type exact de l’objet dans la structure g´en´erique. Cela peut ˆetre n’importe quoi qui ´etend Number, mais le compilateur ne peut en ˆetre certain. Ainsi, toute tentative de retrouver une valeur g´en´erique est consid´er´ee comme une op´eration non sˆure et est donc rejet´ee imm´ediatement par le compilateur. 2.2.2 La contravariance Ici, on utilise une wildcard diff´erente : <?superT >. La contravariance nous permet de faire l’op´eration oppos´ee. Nous pouvons lire dans une structure mais pas ´ecrire. List<Object> myObjs = new List<Object () ; myObjs . add ( ” Hello ” ) ; myObjs . add ( ”World” ) ; List <? super Number> nombres = myObjs ; nombres . add (10) ; Dans ce cas, nous pouvons bien ajouter un Number dans la liste nombres car Number a pour ancˆetre Object. En revanche, ”Number n = nombres.get(0) ;” produit une erreur de compilation. En effet nous ne sommes pas sˆurs `a 100% d’avoir un Number. Si le compilateur laissait passer cela, nous pourrions avoir `a l’ex´ecution une ClassCastException. En somme, nous utilisons la covariance quand nous voulons seulement lire une valeur g´en´erique dans une structure et la contravariance quand on veut ´ecrire dedans. Un dernier exemple pour illustrer :
  • 6. 2.2 Variance 5 public s t a t i c void copy ( List <? extends Number> source , List <? super Number> destiny ) { f or (Number number : source ) { destiny . add (number) ; } } List<Integer > myInts = asList (1 ,2 ,3 ,4) ; List<Object> myObjs = new ArrayList<Object >() ; copy ( myInts , myObjs) ; Tous les types g´en´eriques sont ´etiquet´es comme inh´erents `a la covariance, contrava- riance, bivariant ou invariant au type de leurs param`etres. Cette inh´erence peut donc ˆetre employ´ee `a tous les types g´en´eriques. Par exemple, nous pouvons changer de mani`ere raisonnable toutes les occurences de Iterator < T > en Iterator <?extendsT > ou bien Comparator < T > en Comparator <?superT >. Des chercheurs ont alors d´evelopp´e un outil afin d’am´eliorer cette g´en´eralisation. Il poss`ede diff´erentes fonctionnalit´es : 1. Pour aider le programmeur `a utiliser la variance en Java, il permet de r´e´ecrire automatiquement le code en un code avec des wildcards plus g´en´erales. 2. Cependant, tous les types ne peuvent pas ˆetre r´e´ecris, (ex : s’ils sont d´eclar´es dans une tierce autre librairie o`u le code source n’est pas disponible). Ainsi l’utilisateur peut choisir de ne pas r´e´ecrire le code, si garder un type sp´ecifique est pr´ef´erable pour une future mise `a jour. 3. L’outil respecte la s´emantique Java et pr´eserve le comportement du programme.
  • 7. Chapitre 3 Cas concret d’utilisation Apr`es avoir les principes de la covariance et la contravariance, nous allons voir main- tenant un exemple d’utilisation de l’outil pour renommer des entit´es d’un programme. Prenons le programme suivant : c l a s s WList<E> { private List<E> elems = new LinkedList<E>() ; void add (E elem ) { addAll ( C o l l e c t i o n s . s i n g l e t o n L i s t ( elem ) ) ; } void addAll ( List<E> source ) { addAndLog( source . i t e r a t o r () , t h i s . elems ) ; } s t a t i c <T> void addAndLog( Iterator <T> itr , List<T> dest ) { while ( i t r . hasNext () ) { T elem = i t r . next () ; log ( elem ) ; dest . add ( elem ) ; } } De mani`ere g´en´erale, l’interface List est invariante. c’est `a dire qu’elle autorise la lecture et l’´ecriture d’un ´el´ement. Or dans la m´ethode addAndLog, pour la liste dest rien n’est lu. On ne fait qu’ajouter un ´el´ement avec add. On peut alors se limiter `a une version contravariante de List en faisant un List <?superT > dest. Pour source, la seule m´ethode invoqu´ee est iterator() qui retourne un Iterator < E >. Or Iterator est covariant comme nous l’avons vu pr´ec´edemment. On peut alors de mani`ere sˆure inf´erer le type de source en List <?extendsT >. Cependant, si on ne changeait que le type de source, le programme ne compilerait pas. En effet, la m´ethode addLog attend un Iterator < T > mais on lui fournit maintenant un Iterator <?extendsT > avec source. Une analyse du programme est alors n´ecessaire pour savoir si la g´en´eralisation d’un type entraˆıne le changement de type d’autres d´eclarations. Ce flot d’analyse doit prendre en compte les d´ependances entre
  • 8. 7 chaque. Ici, nous pouvons alors changer le type de itr en Iterator <?extendsT >. Nous obtenons alors : c l a s s WList<E> { private List<E> elems = new LinkedList<E>() ; void add (E elem ) { addAll ( C o l l e c t i o n s . s i n g l e t o n L i s t ( elem ) ) ; } void addAll ( List <? entends E> source ) { addAndLog( source . i t e r a t o r () , t h i s . elems ) ; } s t a t i c <T> void addAndLog( Iterator <? extends T> itr , List <? super T> dest ) { while ( i t r . hasNext () ) { T elem = i t r . next () ; log ( elem ) ; dest . add ( elem ) ; } } Apr`es avoir vu un exemple de son utilisation, nous allons maintenant ´etudier son fonc- tionnement.
  • 9. Chapitre 4 Le fonctionnement de l’outil 4.1 La syntaxe de la variance L’outil de refractoring permet d’inf´erer la variance des types rencontr´es dans un pro- gramme. La variance dans le langage Java est implicite. En effet, il n’y pas de syntaxe pour que le programmeur puisse d´efinir la variance d’un type. Contrairement, au langage Scala o`u il est possible de d´efinir la covariance et la contrava- riance par, respectivement, les annotations + et -. En Scala, par d´efaut, un ´el´ement est invariant. L’outil de refractoring va donc se baser sur un ensemble de r`egles et s’inspirer de la syntaxe de Scala pour la d´efinition de la variance. Intuitivement, la variance d’un ´el´ement est contraint par l’utilisation qu’on en fait. Par exemple, le type des param`etres d’une m´ethode est g´en´eralement contravariant et le type de retour d’une m´ethode est g´en´eralement covariant. Ainsi, notons vx la variance de la variable X. Et, essayons de d´eterminer la variance de quelques ´el´ements sur un exemple plutˆot simple : i n t e r f a c e RList<X> { X get ( int i ) ; } i n t e r f a c e WList<Y> { void set ( int i , Y y) ; } i n t e r f a c e IList <Z> { Z setAndGet ( int i , Z z ) ; } Dans l’interface RList, on remarque que la variable X est covariante car elle est le retour de la m´ethode get. On note cela vx = + et se lit X est covariant dans RList. Dans l’interface WList vY = - (contravariant) car Y est un des param`etres de la m´ethode set. Dans l’interface IList vz = o (invariant) car Z est `a la fois covariant et contravariant.
  • 10. 4.2 L’analyse de l’influence des types 9 C’est de cette mani`ere que l’on peut d´eterminer la variance d’un ´el´ement `a partir d’une d´efinition g´en´erique. Apr`es avoir inf´erer une g´en´eralisation pour un type donn´e T, l’outil de refractoring permet de remplacer le type T par sa g´en´eralisation. En prenant l’exemple ci-dessous, l’outil de refractoring effectue les substitutions suivantes : i n t e r f a c e RList<X> { X get ( int i ) ; } i n t e r f a c e WList<Y> { void set ( int i , <? super Y> y) ; } i n t e r f a c e IList <Z> { Z setAndGet ( int i , Z z ) ; } 4.2 L’analyse de l’influence des types 4.2.1 Le principe Le fait de g´en´eraliser les types d’un programme implique de nombreux compromis. En effet, plusieurs probl`emes apparaissent lors de la g´en´eralisation d’un type : 1. G´en´eraliser une List < String > par une List <? extends String > pose un certain probl`eme. C’est un exemple qui montre qu’en Java, il est impossible de red´efinir La classe String. Il faut donc se poser la question des classes, des m´ethodes ... immuables en Java. 2. La red´efinition de m´ethode est possible uniquement si les param`etres de la m´ethode du fils sont identiques `a celle du p`ere. Ainsi, lorsque l’on g´en´eralise les types des pa- ram`etres d’une m´ethode fils, Java ne consid`ere plus cette m´ethode comme red´efinition de m´ethode de la m´ethode p`ere. Or, on voudrait que ¸ca soit le cas. 3. La g´en´eralisation d’un type peut amener `a g´en´eraliser d’autres ´el´ements qui sont plus ou moins d´ependant de ce type. L’outil de refractoring ne doit pas ajouter d’erreur de compilation et ne doit pas modifier la s´emantique du programme. Ces probl`emes sont r´esolus en r´ealisant un graphe orient´e des influences sur les d´eclarations dans le programme. Ainsi, l’outil de refractoring construit un graphe d’influence ; Pour chaque d´ependance entre les entit´es (variable, signature de m´ethode ...) A et B, il existe une arˆete qui lie les nœuds correspondant aux entit´es A et B dans ce graphe. Par la suite, lorsque l’on g´en´eralise l’entit´e A, on parcourt le graphe d’influence en g´en´eralisant les noeuds connexe au noeud de l’entit´e A. Pour pallier aux soucis 1, l’outil de refractoring d´ecide quels ´el´ements ne peuvent pas ˆetre g´en´eralis´es. Concernant le probl`eme 2, l’outil va consid´erer que la signature des param`etres de la
  • 11. 4.2 L’analyse de l’influence des types 10 m´ethode m du fils est fortement d´ependante de la signature de la m´ethode m du p`ere. Dans le graphe d’influence, on va donc ajouter une arˆete entre la signature de la m´ethode p`ere et celle du fils. Pour donner une exemple clair au probl`eme 3, si on g´en´eralise le type de retour d’une m´ethode M alors les variables qui sont affect´ees par la valeur du r´esultat de la m´ethode M doivent ˆetre g´en´eralis´es. Il y aura donc un chemin dans le graphe d’influence qui va lier la m´ethode M et les variables affect´ees par la valeur de M. Prenons, un autre exemple, si l’on g´en´eralise les param`etres p1 et p2 d’une m´ethode M. Et si dans le corps de cette m´ethode M, un objet O fait un appel `a la m´ethode O.m(p1, p2). Alors il faudra g´en´eraliser la signature de la m´ethode O.m. Il existe donc un chemin dans le graphe d’influence entre l’objet O et les param`etres p1 et p2. 4.2.2 L’algorithme Les noeuds du graphe d’influence poss`ede la syntaxe abstraite suivante : Figure 4.1 – Syntaxe du graphe d’influence FieldDeclaration est la repr´esentation des variables de classes ou d’objet. V ariableDeclaration correspond `a la d´eclaration de variables locales. ParameterDeclarations correspond aux param`etres des m´ethodes ou des constructeurs. MethodDecl correspond au type de retour d’une m´ethode. On va ´egalement d´efinir un langage pour d´ecrire les programmes Java. Ce langage nous permettra de d´efinir des fonctions qui nous seront utiles pour l’algorithme d’analyse de l’in- fluence des types et permet d’abstraire la complexit´e de la repr´esentation d’un programme Java.
  • 12. 4.2 L’analyse de l’influence des types 11 Figure 4.2 – Mini langage Avec cette syntaxe, on va pouvoir expliciter la variance des types par v ou w. Et, le et T sont respectivement la d´enotation du mot cl´e extends de Java et d’un tableau de T1, T2, ...Tn D´efinissons les r`egles des fonctions nodesAffectingType(e) et destinationNode(e) en utilisant ce langage : Figure 4.3 – Fonctions utilis´es par l’algorithme
  • 13. 4.2 L’analyse de l’influence des types 12 Explicitons ces fonctions. nodesAffectingType(e) permet de retrouver l’ensemble des d´eclarations accesibles dans e qui peut modifier le type de e. Et, destinationNode(e) donne l’ensemble des d´eclarations d´ependant de e. Ces fonctions seront tr`es utilis´ees dans l’algorithme. Pour chacune de ces fonctions, on a d´efini trois r`egles. Par exemple, la r`egle N-MonoMethod d´eclare que si le retour de la m´ethode m ne d´epend pas de e alors seule la d´eclaration de m peut affecter le type < T > m < e >. Parlons de l’algorithme de cr´eation du graphe d’influence. L’algorithme effectue trois pas- sages sur le programme pour analyser : 1. Les appels de m´ethode : pour chaque appel de m´ethode < T > m < e > , on va retrouver les d´eclarations de e dans le programme. On va ´egalement retrouver les m´ethodes qui prennent exactement e en param`etre. Et, on va rajouter une arˆete entre e et les param`etres des m´ethodes trouv´ees pr´ec´edement. 2. Les expressions : pour chaque expression e , on cherche les d´eclarations D qui sont affect´ees par e. Et, pour chaque d´eclaration N qui est accessible par e et qui peut affecter e, on relie dans le graphe d’influence N et D. 3. Les d´eclarations de m´ethode : pour chaque d´eclaration de m´ethode M, on va trouver les m´ethodes M qui red´efinissent ou sont r´ed´efinies par M. On va ajouter une arˆete dans le graphe entre les param`etres des methodes M et M . L’ensemble de ces r`egles permettent de construire le graphe d’influence d’un programme Java Voici un pseudo code de l’algorithme :
  • 14. 4.2 L’analyse de l’influence des types 13 Figure 4.4 – Pseudo code de l’algorithme du graphe d’influence
  • 15. Chapitre 5 Les Applications de l’outil Apr`es avoir vu comment fonctionnait l’outil, nous pouvons voir que plus le nombre de d´eclarations augmente dans le graphe, et plus le nombre de d´eclarations immuables fait de mˆeme. Ainsi, moins de d´eclarations seront r´e´ecrites parce qu’il existera plus d’arˆetes o`u les r´e´ecritures sont interdites dans le graphe. Pour palier ce probl`eme, les chercheurs ont pens´e qu’il fallait que l’analyse du programme ignore les d´eclarations qui ne peuvent ˆetre aff´ect´ees par la g´en´eralisation, c’est `a dire ne pas les mettre dans le graphe. Voyons certains exemples de types que le flot d’analyse ignore : 1. Les types primitifs tels que les int, char, boolean ainsi que les types monomorphiques comme String et Object. Ces types ne peuvent pas ˆetre modifi´es avec des wildcards. 2. Les types param´etriques qui sont sp´ecifi´es bivariant ( ¡ ?¿ ). Ces types ne peuvent pas ˆetre plus g´en´eralis´es qu’ils ne le sont d´ej`a. L’outil permet donc de g´en´eraliser des classes en s´el´ectionnant quelles d´eclarations parmi les variables locales, les arguments ou retour de m´ethodes lesquels sont `a renommer. Des travaux pr´ec´edents ont montr´e que 53% des interfaces et 37% des classes peuvent ˆetre g´en´eralis´ees. Ceci montre alors l’impact que pourrait avoir cet outil si toutes ces d´eclarations ´etaient r´e´ecrites. Il aiderait ´egalement les utilisateurs qui n’ont pas de grandes notions de variance `a am´eliorer les performances de leur code. Afin d’´evaleur le potentiel de cet outils, des statistiques ont permis de calculer combien de d´eclarations de types param´etriques pouvaient ˆetre r´e´ecrites. L’outil `a ´et´e test´e sur six librairies java. Nous n’en montrerons que trois ici :
  • 16. 15 Figure 5.1 – Statistiques des r´e´ecritures de toutes les d´eclarations pour les types g´en´eriques Prenons ici l’exemple des interfaces java, il existe 170 interfaces avec des types pa- ram´etr´es. Parmi celles l`a, 148 peuvent ˆetre r´e´ecrites. Apr`es le passage de l’outil, 34 ont ´et´e r´e´ecrites, soit 20%. Sur l’ensemble des six librairies test´ees, nous obtenons un total 12% de r´e´ecritures en prenant compte les classes et les interfaces, sur un potentiel de 73%. Cela repr´esente tout de mˆeme 2220 sur 18259 r´e´ecritures.
  • 17. 16 Figure 5.2 – Statistiques des r´e´ecritures de toutes les d´eclarations pour les types variant Pour les types variant, nous voyons que nous obtenons de bien meilleures performances. Sur l’ensemble des six librairies, on obtient un total de 34% de renommage. De plus, la r´e´ecriture seule de JDK ne prend que deux minutes pour 198 milles lignes de code.
  • 18. Chapitre 6 Conclusion En conclusion, apr`es avoir vu quelques exemples d’utilisations ainsi que son fonctionne- ment, nous pouvons voir que cet outil complexe nous permet d’am´eliorer les perfermances de notre code en g´en´eralisant le plus possible les types param´etriques `a l’aide de wildcards. Cependant, en regardant les statistiques sur le pourcentage de renommage apr`es le pas- sage de l’outil sur les six principales librairies Java, 34% des g´en´eriques ont pu ˆetre plus sp´ecifiques avec des wildcards plus g´en´eralis´ees. Nous pouvons alors penser que cet outil peut encore ˆetre am´elior´e. Des travaux futurs ont ´et´e evoqu´e dans ce sens.