Table of Contents

Des modèles aux codes et vis-versa

Objectifs :

  1. Faire un lien direct entre la modélisation des classes et les codes correspondants.
Nous faisons le lien entre modèles et codes. Vous pouvez travailler les codes uniquement au niveau du papier (mais c'est peut-être dommage). Vous devez essentiellement comprendre les grands principes.
ObjectAid sous Install new software > add > http://www.objectaid.com/update/current

Puis après avoir relancé Eclipse, sous New > Other > Object Aid..> Classes …. ensuite vous posez simplement les classes à visualiser sur votre diagramme.

Pour générer les codes :
  • Donnez un nom au projet qui peut devenir le nom du package ⇒ pas d'espace dans le nom

Je comprends

1) Je sais passer du modèle d'une classe au code

Le concept d'“Engin” modélisé ici sous la forme d'une classe sera représenté par le code suivant :

En Java

public class Engine {
}

En C#

public class Engine {
};

En PHP

<?php
public class Engine {
}
?>
Une “instance” du concept d'engin sera par exemple “defiance”, un vaisseau spacial. On crée une instance d'engin en java par le code suivant :
Engine defiance = new Engine();

On crée un autre engin par :

Engine xwing = new Engine();

Je visualise les codes à partir du modèle

Pour générer les codes sous Outils > generer

Elements pour GenMyModel

2) Je sais passer du modèle d'une classe avec un attribut au code

Les codes correspondants

Le concept d'“Engin” modélisé ici sous la forme d'une classe contient à présent un attribut qui permet d'exprimer la puissance. Il sera représenté par le code suivant :

Code généré en Java

public class Engine {
	private int power;
}

Code généré en C#

public class Engine {
	private int power;
}

Code généré en php

<?php
class Engine {
	/**
	 * @AttributeType int
	 */
	private $_power;
}
?>

Complétons ce code

Pour pouvoir accéder à cet attribut nous allons à présent dans le code définir des accesseurs.

Ajout des accesseurs

Le code de la classe Engin en java devient :

public class Engine {
 
	private int power;
 
        //Accesseur en lecture : on lit la valeur de l'attribut power
	public int getPower() {
		return power;
	}
 
       //Accesseur en écriture : on modifie la valeur de l'attribut power (noté this.power) avec la valeur en parametre power
	public void setPower(int power) {
		this.power = power;
	}
 
}

A partir de ce code, nous pouvons à présent créer une “instance” de la classe “Engine” et lui affecter une puissance de 2000.

public class TestInMain {
	public static void main(String[] args) {
		Engine defiance = new Engine();
		//Set Power to 2000
		defiance.setPower(2000);
		//Get power of  defiance
		int defiancePower = defiance.getPower();
		//Print Defiance's power
		System.out.println("Power : " + defiancePower);
	}
 
}

Représentation d'une instance de la classe Engine (sous GenMyModel vous pouvez faire cela en créant un diagramme d'objets.)

3) Je sais passer du modèle d'une classe avec un attribut et une méthode au code

Les codes correspondants

Code généré en java (La version générée par est un peu différente. Au lieu d'une levée d'exception, le commentaire suivant est ajouté : TODO implement me)

public class Engine {
	private int power;
 
	public void stop() {
		throw new UnsupportedOperationException();
	}
}

Code généré en php

<?php
/**
 * @access public
 * @author blay
 */
class Engine {
	/**
	 * @AttributeType int
	 */
	private $_power;
 
	/**
	 * @access public
	 */
	public function stop() {
		// Not yet implemented
	}
}
?>

Une proposition d'implémentation en java pour stop :

public class Engine {
	private int power;
 
	public void stop() {
		power = 0;
	}
}

Tests des méthodes

import static org.junit.jupiter.api.Assertions.*;
 
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
 
class EngineTest {
 
	@BeforeEach
	void setUp() throws Exception {
		//Because you are beginners, we don't use it.
		// Nevertheless, it would be better.
	}
 
	@Test
	void testInit() {
		Engine defiance = new Engine();
		assertEquals(0, defiance.getPower());
	}
 
	@Test
	void testSetPower() {
		Engine defiance = new Engine();
		defiance.setPower(2000);
		int defiancePower = defiance.getPower();
		assertEquals(2000,defiancePower, "expected power : 2000" );
	}
 
	@Test
	void testStop() {
		Engine defiance = new Engine();
		defiance.setPower(2000);
		assertEquals(2000,defiance.getPower(), "expected power : 2000" );
	   //Stop the engine defiance
	    defiance.stop();
	    assertEquals(0,defiance.getPower(), "expected power should be 0" );
		   //Stop the engine defiance
	}
 
}

Utilisation de la méthode Stop

public class TestInMain {
 
	public static void main(String[] args) {
		Engine defiance = new Engine();
		//Set Power to 2000
		defiance.setPower(2000);
		//Get power of  defiance
		int defiancePower = defiance.getPower();
		//Print Defiance's power : expected 2000
		System.out.println("Power : " + defiancePower);
 
	    //Stop the engine defiance
		defiance.stop();
		//Get power of  defiance
		defiancePower = defiance.getPower();
		//Print Defiance's power : expected 0
		System.out.println("Power : " + defiancePower);
	}
 
}

4) Je sais passer du modèle d'une association au code

Les codes correspondants

Code java correspondant Dans genMyModel, c'est un set<> qui est généré.

public class Engine {
 
	private int power;
 
        //Association becomes an attribute ; multiplicity * => array or any collections 
	private Pilot[] pilots; // = new Pilot[0]; //array de dimension 1
 
 
	public int getPower() {
		return power;
	}
 
	public void setPower(int power) {
		this.power = power;
	}
 
	public void stop() {
		power = 0;
	}
 
}

et une nouvelle classe :

public class Pilot {
 
}

Complétons la classe Engine pour manipuler les pilotes.

Les codes correspondants

public class Engine {
 
	private int power;
	private Pilot[] pilots = new Pilot[1];
 
 
	public Pilot[] getPilots() {
		return pilots;
	}
 
	public void setPilots(Pilot[] pilots) {
		this.pilots = pilots;
	}
 
	public void addPilotAtRank(Pilot onePilot, int rank) {
		if (rank < pilots.length & rank >=0 )
			this.pilots[rank] = onePilot;
		//else
			//too many pilots, do nothing
 
	}
 
	public int getPower() {
		return power;
	}
 
	public void setPower(int power) {
		this.power = power;
	}
 
	public void stop() {
		power = 0;
	}
 
}

On ajoute des tests

        @Test
	void testInitPilot() {
		Engine defiance = new Engine();
		assertTrue(defiance.getPilots()!=null);
	}
 
	@Test
	void testAddPilot() {
		Engine defiance = new Engine();
	   //Admiral Nammo
		Pilot nammo =  new Pilot();
		defiance.addPilotAtRank(nammo, 0);
        //Get the pilots of defiance
		Pilot[] pilots = defiance.getPilots();
		assertEquals(nammo, pilots[0]);
	}

Utilisons notre nouveau code en complétant le main

		//Admiral Nammo
		Pilot nammo =  new Pilot();
		defiance.addPilotAtRank(nammo, 0);
 
		//Get the pilots of defiance
		Pilot[] ourPilots = defiance.getPilots();
 
		//Print the first pilot (only object reference)
		System.out.println("Pilot : " + ourPilots[0]);
	}

5) Relation Bidirectionnelle

On peut naviguer à présent du pilote à l'engin et inversement. La classe Pilot générée est donc modifiée. Remarquez que la multiplicité de 1 cette fois-ci crée un attribut simple de type Engine

Les codes correspondants

public class Pilot {
	private Engine drivenEngine;
}

Nous complétons le code pour pouvoir accéder et modifier le moteur associé au pilot.

public class Pilot {
 
	private Engine drivenEngine;
 
	public Engine getDrivenEngine() {
		return drivenEngine;
	}
 
	public void setDrivenEngine(Engine newEngine) {
		this.drivenEngine = newEngine;
	}
}

Pour tester nous ajoutons à présent l'engin defiance comme celui conduit par l'amiral nammo

		nammo.setDrivenEngine(defiance);

Nous décidons à présent que l'on ne veut pas que n'importe qui affecte un engin à un pilote (on passe la méthode setDrivenEngine en Protected) et que lorsque l'on affecte un pilote à un engin alors il en devient pilote. Nous modifions nos codes.

Les codes correspondants

package tdS2;
 
public class Engine {
 
	private int power;
	private Pilot[] pilots = new Pilot[1];
 
 
	public Pilot[] getPilots() {
		return pilots;
	}
 
	public void setPilots(Pilot[] pilots) {
		this.pilots = pilots;
	}
 
	public void addPilotAtRank(Pilot onePilot, int rank) {
		if (rank < pilots.length & rank >=0 )
			this.pilots[rank] = onePilot;
			onePilot.setDrivenEngine(this);
		//else
			//too many pilots, do nothing
 
	}
 
	public int getPower() {
		return power;
	}
 
	public void setPower(int power) {
		this.power = power;
	}
 
	public void stop() {
		power = 0;
	}
 
}
public class Pilot {
 
	private Engine drivenEngine;
 
	public Engine getDrivenEngine() {
		return drivenEngine;
	}
 
	protected void setDrivenEngine(Engine newEngine) {
		this.drivenEngine = newEngine;
	}
}

Nous testons ce code.

	@Test
	void testSetDriver() {
		Engine defiance = new Engine();
		Pilot nammo =  new Pilot();
		defiance.addPilotAtRank(nammo, 0);
		assertEquals(defiance, nammo.getDrivenEngine(),"The pilot of an engine drives it");
	}

Nous utilisons ce code.

                Engine X100rocketBoosters = new Engine();
		Pilot r2D2 =  new Pilot();
 
		X100rocketBoosters.addPilotAtRank(r2D2, 0);
		//expected one pilot
		pilots = X100rocketBoosters.getPilots();
		System.out.println("expected one pilot" + pilots);
		Engine engine4R2D2 = r2D2.getDrivenEngine();
		System.out.println("expected one engine" + engine4R2D2);

6) A vous : appliquez tout seul ce qui précède

C'est la suite de l'exercice, lisez Engine au lieu de Engin

  1. Quel code correspond au diagramme de classe UML ci-dessus ? 1)
  2. La méthode move correspond à modifier la position.2)
  3. Compléter le diagramme pour ajouter un nom au pilote.

ET aussi :

  1. Quel code correspond au diagramme de classe UML ci-dessus (A faire en complétant les diagrammes précédents)?

7) Je sais passer du modèle d'une relation d'héritage au code

Les codes correspondants au diagramme

Classe Weapon

public class Weapon {
   private Jedi belongsTo ;
 
public Jedi getBelongsTo() {
	return belongsTo;
}
 
public void setBelongsTo(Jedi owner) {
	this.belongsTo = owner;
}
 
 
}

Classe MeleeWeapon “hérite de”/“Spécialise” Weapon

public class MeleeWeapon extends Weapon{
}

Classe Lightsaber “hérite de”/“Spécialise” MeleeWeapon

public class Lightsaber extends MeleeWeapon{
 
}

Je peux accéder au propriétaire d'une arme quelconque.

		Lightsaber excaLight = new Lightsaber();
		Jedi Revan = new Jedi();
		excaLight.setBelongsTo(Revan);

8) A vous

  1. Quel code correspond au diagramme de classe UML ci-dessus ?
  2. Imaginez que l'on veuille pouvoir demander à une Armada d'attaquer, quelle méthode devez-vous ajouter?
  3. Voici le code de cette nouvelle méthode, si besoin

    1. Voici le code de cette nouvelle méthode :
    	public void attack() {
    		//All engines must attack
    		for (Engine e : engines)
    			//e is one Engine in engines
    			e.attack();
    	}
    1. Voici un code qui peut permettre de créer une Armada, de lui associer 10 Engine et de déclencher une attaque
                    Armada sithArmada = new Armada();
    		//Array of 10 Engines
    		Engine[] machines = new Engine[10];
    		//Initialise with 10 Engine
    		for(int i=0; i<10; i++){
    			machines[i] = new Engine(); 
    		}
    		sithArmada.setEngines(machines);
    		sithArmada.attack();

9) Je sais passer du code au modèle

public class Avatar {
    private String name;
    private Position pos;
    private Weapon[] weapons;
    
    public Position moveDelta(int x, int y) {
    		pos.addX(x);
    		pos.addY(y);
    		return pos;
    }
    
}


public class Submarine extends Engine{
	private int capacity;
	
	private DecompressionChamber decompressionChamber;
}
  1. Quel modèle correspond au code ci-dessus ?

Diagrammes de séquence, diagramme de classe et Codes

Du diagramme de séquence au diagramme de classes

Voici un diagramme de séquence, complétez le diagramme de classe pour tenir compte des nouveaux éléments.

Pour vous aider :

Complétez le diagramme de séquence

Compléter les diagrammes de classes et séquence pour introduire :

  1. les armadas attaquent. Chaque armada demande à ses engins d'attaquer.

Du diagramme de séquence aux codes

  1. Construire vos classes au niveau du code
  2. Complétez vos codes pour prendre en compte le diagramme de séquence
1)
 private Position position = new Position();
2)
 public void move (int x, int y) {
		position.setX(x);
		position.setY(y);
	}