Exercice
L'objectif de cet exercice est de montrer comment on peut concevoir un logiciel avec UML et le programmer en Java en utilisant simultanément deux outils (ici, Modelio et Eclipse).
Cette démarche devra être appliquée pour le projet intégré.
Vu sa faible complexité, le sujet de cet exercice (représentation de polynômes) ne nécessite pas nécessairement une démarche préalable de modélisation. Pour autant, celle-ci sera effectuée sur cet exemple simple afin de maitriser la démarche et ainsi être en mesure de l'appliquer pour des cas plus complexes.
1. Modèle UML initial
On souhaite représenter les nombres rationnels, c'est-à-dire les nombres qui s'écrivent sous la forme
{$$ numérateur \over denominateur $$}
où le numérateur et le dénominateur sont entiers. Un nombre rationnel sera représenté par la donnée de son numérateur et de son dénominateur.
- Lancer Modelio et créer un projet
PolynomeUML
.
Modelio a créé un automatiquement un paquetage polynomeuml
dans le projet PolynomeUML
, mais celui-ci sera ignoré lors de la génération du code Java.
- Créer un paquetage
gloo
dans le paquetagepolynomeuml
, puis un paquetagepolynome
dans ce paquetagegloo
.

Figure 1. Création des paquetages
- Créer un diagramme de classes dans le dernier paquetage créé.
- Créer une classe
Rational
sur ce diagramme, lui ajouter deux attributs privés,numerator
etdenominator
de typeinteger
. - Créer une classe
RationalTest
sur ce diagramme, lui ajouter une méthode statique (propriétéClass
)main
ayant un paramètreargs
de typestring
et de multiplicité0..*
(double-clic sur la méthode pour pouvoir ajouter des paramètres).

Figure 2. Les deux classes UML
2. Traduction du modèle UML en Java
- Dans le menu
Configuration
, choisirModules…
, cliquer surAdd…
, sélectionnerJavaDesigner 5.4.02
:

- Cliquer sur
Deploy in the project
, puis surClose
. - Sélectionner successivement les 2 paquetage
gloo
etpolynome
et les deux classesRational
etRationalTest
dans la vue modèle, et activer pour chacun la propriété Java element dans l'onglet Java :

L'icone Java est alors ajouté aux éléments visibles :

- Utiliser le menu contextuel sur le paquetage
gloo
et demander la génération de code dans le sous-menu Java Designer :

3. Création du projet Eclipse correspondant
- Lancer Eclipse, demander la création d'un projet Java
gloo.polynome
, décocher la case Use default location, cliquer sur Browse… et sélectionner le dossier correspondant à votre projetPolynomeUML
(dans/config/modelio/workspace
) :

- Décocher la case Create module-info.java

- Cliquer sur Next, sélectionner l'onglet Librairies, sélectionner Classpath dans la vue centrale puis Add External JARs…

- Choisir Other Locations → Computer →
usr
→lib
→modelio-open-source5.4
→bundle
→java
→javadesigner.jar
, cliquer sur Open

- Cliquer sur Finish.
Le code généré contient des annotations @objid
, vous ne devez pas les modifier, elles sont utilisées par Modelio quand il relit le code. Il y a une telle annotation devant chaque élément Java généré (classe, attribut, méthode…) : vous pouvez déplacer cet élément pour réorganiser votre code, mais vous devez déplacer l'annotation en même temps.

Vous pouvez adapter la génération du code Java à vos besoins et contraintes ; par exemple, le type de l'argument de main
est List<String>
au lieu de String[]
, il faut corriger.
- Dans Modelio, sélectionner l'argument de
main
dans la vue modèle, et choisirArray
commeCollection to use
. Régénérer le code Java et vérifier la bonne prise en compte de cette modification (il faut éventuellement demander à Eclipse de rafraichir ses données File → Refresh).

4. Synchronisation du modèle UML avec le code Java
La modélisation UML est utile pour trouver les bonnes classes et les opérations nécessaires au fonctionnement de l'application. Elle n'est pas pertinente pour d'autres tâches, par exemple l'écriture des constructeurs, pour lesquelles un IDE comme Eclipse sera beaucoup plus efficace. Pour autant, il faut veiller à conserver la cohérence entre le monde UML et le monde Java.
- Dans Eclipse, ouvrez le fichier
Rational.java
et positionner le curseur à l'intérieur de la classe. - Dans le menu
Source
, choisirGenerate Constructor using Fields…
:

- Les 2 attributs sont sélectionnés par défaut, cliquer sur
Generate
, le constructeur est automatiquement écrit (l'appelsuper()
sera expliqué lors du cours sur l'héritage).

- N'oublier pas de sauvegarder les changements apportés au fichier
Rational.java
.
Pour ne pas perdre le code généré par Eclipse, il faut que Modelio soit capable de relire ce code afin de le restituer lors de la prochaine génération. La version de Java utilisée doit être prise en compte lors de cette opération, sachant que Modelio n'est capable de relire que du code Java 8.
- Pour configurer Modelio afin qu'il puisse relire correctement du code Java, choisir dans le menu contextuel sur le paquetage
polynomeuml
Java Designer → Configuration → Edit accessible classes :

- Sélectionner la ligne
rt.jar
existante et supprimer là avec le croix rouge ❌

- Cliquer sur l'icône à gauche de la croix rouge ❌ puis naviguer vers Other Locations → Computer →
usr
→lib
→jvm
→java-8-openjdk-amd64
→jre
→lib
, sélectionnerrt.jar
et cliquer sur Open, puis sur OK :

- Choisir dans le menu contextuel sur le paquetage
polynomeuml
Java Designer → Update model from source if necessary :

Le constructeur n'apparait pas sur le diagramme de classes, mais on peut vérifier sa présence dans l'onglet modèle :

Il est possible de le glisser-déposer sur la classe Rational
du diagramme de classes pour le rendre visible.
En sens inverse, Modelio peut aussi générer du code utilitaire :
- Sélectionner l'attribut
numerator
et, dans l'onglet Java, cocher la caseGetter
:

- Faire la même chose pour l'attribut
denominator
, les deux opérations apparaissent sur le diagramme de classes, et sont présentes dans le code Java après une nouvelle génération :

Il est important, pour conserver la synchronisation entre le modèle UML de votre projet et son code Java, de respecter ces procédures :
- Après une modification dans Eclipse (ne pas oublier de sauvegarder le ou les fichiers modifiés), utiliser Update model from source if necessary dans Modelio.
- Après une mise à jour du modèle dans Modelio, générer de nouveau le code Java et utiliser si besoin Refresh sous Eclipse.
5. Affichage d'un rationnel
- Sous Eclipse, compléter la méthode
main
avec le code suivant :
public static void main(String[] args) { Rational q = new Rational(3, 4); System.out.println("q = " + q); Rational r = new Rational(1, 6); System.out.println("r = " + r); }
- Exécuter votre classe de test. L'affichage obtenu est-il satisfaisant ? Pourquoi ?
- Ajouter à la classe
Rational
une méthodetoString
(vous pouvez demander à Eclipse de générer une version via le menuSource
→Generate toString…
). Les chaînes renvoyées partoString
devront être de la forme7/5, 0/4, 2/6, 3/1,
etc.
- Tester à nouveau le programme.
Pour la méthode main
donnée précédemment, on doit obtenir l'affichage suivant :
q = 3/4
r = 1/6
- Mettre à jour votre modèle UML.
6. Monôme
Nous souhaitons maintenant manipuler des polynômes à coefficients rationnels. On considère qu'un polynôme est défini par un ensemble de monômes. Nous commençons par définir une classe Monomial
, puis une classe Polynomial
.
Un monôme est défini par un coefficient (qui est de type rationnel) et un degré (de type entier, et obligatoirement positif ou nul).
- Dans Modelio, créer une classe
Monomial
ayant un attributdegree
privé et de type entier et une composition navigable versRational
; l'extrémité correspondante sera privée, aura une multiplicité de1
et pour nomcoefficient
. Créer une classeMonomialTest
avec une méthodemain
. - Générer le code Java, définir dans Eclipse le constructeur de
Monomial
et la méthodetoString
donnant une représentation textuelle du monôme (par exemple :3/4*X^5
; on ne cherchera pas à traiter les cas particuliers, ainsi on écrira :1/1*X^0
). - Compléter la méthode
main
deMonomialTest
avec le code suivant :
public static void main(String[] args) { Monomial m = new Monomial( new Rational( 3, 4 ), 5 ); System.out.println( "3/4*X^5 = " + m ); }
- Vérifier que vous obtenez l'affichage suivant :
3/4*X^5 = 3/4*X^5
- Mettre à jour votre modèle UML.
- Ajouter dans Modelio des accesseurs au coefficient et au degré du monôme.
7. Polynôme
- Dans Modelio, créer une classe
Polynomial
ayant une composition navigable versMonomial
; l'extrémité correspondante sera privée, aura une multiplicité*
et pour nommonomials
. Créer une classePolynomialTest
avec une méthodemain
.
On appelle forme canonique d'un polynôme une écriture dans laquelle les monômes sont triés par degrés décroissants, et où il n'y a qu'un seul monôme par degré (et aucun de coefficient nul).
Nous allons faire en sorte que la représentation du polynôme soit directement sous forme canonique. On peut pour cela stocker les monômes sous la forme d'un dictionnaire utilisant comme clef le degré et comme valeur associée le monôme correspondant (le coefficient aurait suffi, mais l'affichage sera plus facile en mémorisant le monôme). Pour accéder de plus aux monômes dans l'ordre donné par les degrés, nous n'utiliserons pas une HashMap
présentée en cours, mais une TreeMap
(n'hésitez pas à aller consulter la documentation de cette classe).
Exemple de code utilisant TreeMap
:
// Un TreeMap est un dictionnaire dont l'implémentation est basée sur un arbre // des clefs permettant un parcours de l'arbre selon l'ordre croissant des clefs. TreeMap<Integer, String> m = new TreeMap<>(); m.put(3, "trois"); m.put(1, "un"); m.put(2, "deux"); // Une entrée d'un dictionnaire contient la clef et la valeur associée for (var entry : m.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } /* Affichage obtenu : 1 = un 2 = deux 3 = trois */
- Sous Modelio, demander que la génération Java de l'extrémité
monomials
se fasse avec comme collection un TreeMap as SortedMap dont la clef sera unInteger
, générer le code Java, vérifier avec Eclipse que vous obtenez dans la classePolynomial
:
private SortedMap<Integer, Monomial> monomials = new TreeMap<Integer, Monomial> ();
- Mettre à jour le modèle UML (la clef va apparaître sur le diagramme).
- Nous aurons besoin de faire des sommes de rationnels. Dans Modelio, ajouter à la classe
Rational
une méthodeadd
qui rend un nouveau rationnel (et donc ne modifie pas le rationnel courant) égal à la somme (non simplifiée) du rationnel courant et d'un autre rationnel passé en paramètre. - La création d'un polynôme se fera en ajoutant des monômes à un polynôme initialement vide. Ajouter à la classe
Polynomial
une méthodeadd
qui reçoit un monôme en paramètre et l'ajoute au polynôme courant. - Générer le code Java, le compléter sous Eclipse, ajouter une méthode
toString
àPolynomial
et des tests de création et d'affichage de polynômes. N'oubliez pas de mettre à jour votre modèle UML après les modifications faites sous Eclipse.

8. Calculs
Nous voulons maintenant évaluer un polynôme pour une valeur donnée de la variable (un rationnel).
- Ajouter les comportements nécessaires dans les différentes classes. Vous aurez en particulier besoin de faire des multiplications de rationnels.

© 2024-25 CentraleSupélec