Mis à jour le 12/10/2018
  • 20 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Ce cours est en vidéo.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

J'ai tout compris !

Découvrez les visibilités

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Dans ce chapitre, démarrons le code de notre application ! Nous allons commencer par implémenter une partie du diagramme UML que nous avons vu ensemble précédemment :

  • la classe  Product ;

  • la classe  Client .

Dans un second temps, je vous expliquerai un concept important : la visibilité.

Implémentez un UML

Votre projet

Commençons par créer notre projet dans IntelliJ. Si vous avez oublié comment faire, voici un petit rappel du premier cours. Cette fois, chez moi, le projet se nomme HomeShop et le package com.cursan.homeshop.

Produit

Voici un petit rappel de notre UML :

UML d'un produit
UML d'un produit

Commençons par coder cette classe :

package com.cursan.homeshop;

public class Product {
    String name;
    String description;
    double price;

    /**
     * Display a full description of the product
     */
    public void look() {

    }

    /**
     * Add the product to a Bill
     * @param bill the concerned bill
     * @param quantity the quantity to add
     */
    public void buy(Bill bill, Integer quantity) {

    }
}

Pour que le code puisse compiler, nous allons créer une classe  Bill  vide.

package com.cursan.homeshop;

public class Bill {
}

Un bon réflexe à avoir est de créer immédiatement une classe de tests dès que vous créez une classe. Si les pratiques de TDD vous échappent, je vous invite à consulter ce chapitre du premier cours.

Commencez par créer un dossier test à la racine de votre projet.

Création dossier test
Création dossier test
Nom dossier test
Nom dossier test

Il faut ensuite préciser à IntelliJ que ce dossier va servir à stocker nos tests. Faites clic droit sur le dossier test > Mark Directory As > Test Sources Root.

Test Sources Root
Test Sources Root

Maintenant, revenez dans la classe  Product , puis dans le menu Navigate >Test.

Menu Navigate > Test
Menu Navigate > Test

IntelliJ ne trouve pas de classe de tests correspondant à  Product , il vous propose de la créer.

Créer un nouveau test
Créer un nouveau test

Sélectionnez JUnit5.

Création de test avec JUnit 5
Création de test avec JUnit 5

Voilà ! IntelliJ vient de vous créer une nouvelle classe.

Nouvelle classe ProductTest
Nouvelle classe ProductTest

Cette classe contient des erreurs, car, par défaut, notre projet ne contient pas JUnit5. Comme dans le premier cours, résolvez le souci automatiquement via IntelliJ.

Ajout JUnit5 dans le classpath
Ajout JUnit5 dans le classpath

Voilà, votre classe de tests est créée. Pour l'instant,  Product  ne fait rien, pas besoin d'écrire des tests. Dès que nous voudrons ajouter un comportement, nous rédigerons les tests d'abord dans  ProductTest .

Qu'est-ce que le classpath exactement ?

Le classpath est un paramètre contenant un ensemble de chemins vers des classes Java. Au lancement d'un programme, un outil inclus dans la JVM va scanner ces chemins pour charger toutes les classes nécessaires. Dans notre cas, on ajoute JUnit5.0 dans le classpath pour que cette librairie soit chargée avec notre programme. 

Client

On passe maintenant à client. Le code est encore plus simple :

package com.cursan.homeshop;

public class Customer {
    String fullname;
    String address;
}

La visibilité

Quand on développe du code, il faut toujours penser : "Peut-être qu'un jour, un autre développeur utilisera mon code." C'est pour cette raison que l'on :

  • nomme correctement nos classes, attributs, méthodes et variables ;

  • rédige de la javadoc ;

  • écrit des tests.

Dans cette même logique, la visibilité est une des notions les plus importantes.

Prenons un exemple de la vie réelle :

Quand vous utilisez un four, vous pouvez le démarrer à 180 degrés pendant 10 minutes. Quand vous faites cela, de nombreux mécanismes internes vont être activés (les résistances vont chauffer, la soufflerie va s'activer, etc.).

Vous, en tant qu'utilisateur de ce four, n'avez pas accès à tous ces composants : ils sont cachés par la carcasse du four.

Pour coder un four, nous pourrions faire :

public class Four {
    Resistance resistance;
    Soufflerie soufflerie;

    public void cuire(int temperature, int duree) {
        ...
    }
}

Si nous codons  Four  de cette façon, un développeur qui l'utilise pourrait avoir accès à  Resistance  et  Soufflerie . 

Il pourrait, par exemple, faire :

Four four = new Four();
four.resistance = null;
four.cuire(180, 10);

En supprimant la valeur de  resistance , il risque de casser la logique interne de  Four .

En tant que développeur, vous devez protéger  Resistance  et  Soufflerie  pour que vous puissiez y avoir accès dans  Four , mais pas à l'extérieur.

Pour cela, il existe un mot clé : private .

public class Four {
    private Resistance resistance;
    private Soufflerie soufflerie;

    public void cuire(int temperature, int duree) {
        ...
    }
}

En faisant cela, il est impossible de faire fonctionner la ligne four.resistance = null;. Le compilateur indiquera une erreur. De cette façon, seul le développeur de  Four  a un contrôle sur ses composants internes.

Il existe 4 types de visibilités :

  • private  : uniquement accessible dans la classe ;

  • public  : accessible partout ;

  • ""   (rien) : accessible dans le package ;

  • protected  : nous verrons ce type plus tard.

Ce concept est aussi applicable aux méthodes. Continuons avec notre exemple du four. Sur certains fours professionnels, il peut y avoir des fonctions de maintenance accessibles au technicien, mais pas à l'utilisateur final du four. Cela se symboliserait par une méthode accessible uniquement à l'intérieur d'une classe.

public class Four {
    ...

    private void maintenir() {
        ...
    }
}

Les méthodes servent principalement à structurer son code à l'intérieur d'une classe.

Getter et Setter

Par défaut, il faut toujours mettre tous les attributs à  private , afin de bien maîtriser ce que l'on peut faire ou non avec notre classe depuis l'extérieur.

Il faut ensuite se poser la question : est-ce que l'on a besoin de lire cette information depuis l'extérieur ?

Si oui, il faut créer un Getter. C'est une méthode très simple qui ressemble à :

public Resistance getResistance() {
    return resistance;
}

Cette fonction retourne une copie de la valeur  de  resistance . Les autres développeurs peuvent donc accéder à sa valeur, mais ne peuvent pas la modifier.

La deuxième question à se poser est : est-ce que l'on a besoin de modifier cette information depuis l'extérieur ?

Si oui, il faut créer un Setter. De nouveau le code est très simple :

public void setSoufflerie(Soufflerie soufflerie) {
    this.soufflerie = soufflerie;
}

Mais du coup, cela revient au même ? Pas du tout ! Un développeur qui utilise votre classe va voir les méthodes Getter et Setter que vous avez créées. Il sait ce que vous l'autorisez à faire. Un Setter veut clairement dire : "J'ai prévu dans mon code que tu puisses modifier cette valeur."

Implémentez un UML proprement !

Un bon UML précise ce qui est accessible et ce qui ne l'est pas. Il existe 2 types de représentations. Dans la première, très verbeuse, on voit tous les Getter et Setter. Ici,  name ,  description  et  price  ont un Getter. Seul  price  possède un Setter.

UML de Product verbeux
UML de Product verbeux

Le second format est plus concis. Des points verts sur les attributs signalent des Getter. Des points rouges signalent des Setter.

UML de Product concis
UML de Product concis

Voici le nouveau code de Product  :

package com.cursan.homeshop;

public class Product {
    private String name;
    private String description;
    private double price;

    /**
     * Display a full description of the product
     */
    public void look() {
        System.out.println(String.format(name + " : " + price + "%n" + description));
    }

    /**
     * Add the product to a Bill
     */
    public void buy(Bill bill, Integer quantity) {

    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

Voici l'UML verbeux pour  Customer  :

UML de Customer verbeux
UML de Customer verbeux

Puis son code :

package com.cursan.homeshop;

public class Customer {
    private String fullname;
    private String address;

    public String getFullname() {
        return fullname;
    }

    public String getAddress() {
        return address;
    }
}

Exemple de certificat de réussite
Exemple de certificat de réussite