GLO-4002 - Site du cours 2023

Temps estimé: 50 minutes

Exercices préparatoires III

Architecture d'un domaine

Préparation

Ajoutez le code suivant dans votre IDE:

public class Planet {

    private final double distance; // million km
    private final double mass; // 10^24 kg

    public Planet(double distance, double mass) {
        this.distance = distance;
        this.mass = mass;
    }

    public double getDistance() {
        return this.distance;
    }

    public double getMass() {
        return this.mass;
    }
}
public class InvalidPlanetException extends RuntimeException {
}
public class SolarSystemService {

    private static final double MERCURY_SPEED = 0.15;
    private static final double VENUS_SPEED = 0.50;
    private static final double EARTH_SPEED = 1.25;
    private static final double SUN_MASS = 1989000;
    private static final String MERCURY = "Freddie Mercury";
    private static final String VENUS = "Oh My Venus!";
    private static final String EARTH = "Terre-Neuve";

    private final Map<String, Planet> planets;

    public SolarSystemService() {
        this.planets = createPlanets();
    }

    private Map<String, Planet> createPlanets() {
        return Map.of(
                MERCURY, new Planet(64.568, 0.3285),
                VENUS, new Planet(107.73, 107.73),
                EARTH, new Planet(147.54, 5.972)
        );
    }

    public double calculateFutureDistanceFromSun(String planet, int year) {
        switch (planet) {
        case MERCURY:
            return calculateFutureDistanceFromSun(year, MERCURY, MERCURY_SPEED);
        case VENUS:
            return calculateFutureDistanceFromSun(year, VENUS, VENUS_SPEED);
        case EARTH:
            return calculateFutureDistanceFromSun(year, EARTH, EARTH_SPEED);
        }

        throw new InvalidPlanetException();
    }

    private double calculateFutureDistanceFromSun(int year, String planetName, double speed) {
        Planet planet = planets.get(planetName);
        double distance = planet.getDistance();
        for (int i = 0; i <= year; ++i) {
            distance = distance + (speed * planet.getMass()) / SUN_MASS;
        }

        return distance;
    }
}

Règles d'affaires

Listez les règles d'affaires en lien avec le code.

Note: Oubliez tout ce que vous connaissez de l'astrophysique, basez-vous seulement sur le code affiché.

Dans un système solaire différent, dont les lois de la physique peuvent être simplifiées aux règles d'affaires suivantes:

  • Il existe 3 planètes: Mercury, Venus, Earth.
  • Chaque planète à un nom, une masse, une vitesse et une distance du Soleil.
  • Chaque planète s'éloigne du Soleil à chaque année, selon le calcul suivant:

S: distance du Soleil prévue après le déplacement.

d: distance du Soleil actuelle; y: nombre d'années; v: vitesse; m: masse de la planète; s: masse du soleil.

S = d + yvm/s

Domaine Anémique

L'auxiliaire du cours vous critique en disant que votre domaine est anémique.

Impressionnez le en réglant ce problème.

public class Planet {

    private static final double SUN_MASS = 1989000;

    private final String name;
    private final double distance;
    private final double mass;
    private final double speed;

    public Planet(String name, double distance, double mass, double speed) {
        this.name = name;
        this.distance = distance;
        this.mass = mass;
        this.speed = speed;
    }

    public String getName() {
        return name;
    }

    public double calculateFutureDistanceFromSun(int year) {
        return distance + year * speed * mass / SUN_MASS;
    }
}
public class SolarSystem {

    private final List<Planet> planets;

    public SolarSystem(List<Planet> planets) {
        this.planets = planets;
    }

    public double calculateFutureDistanceFromSun(String planetName, int year) {
        Planet planet = planets.stream()
                .filter(p -> p.getName().equals(planetName))
                .findAny()
                .orElseThrow(InvalidPlanetException::new);

        return planet.calculateFutureDistanceFromSun(year);
    }
}
public class SolarSystemService {

    private static final double MERCURY_SPEED = 0.15;
    private static final double VENUS_SPEED = 0.50;
    private static final double EARTH_SPEED = 1.25;
    private static final String MERCURY = "Freddie Mercury";
    private static final String VENUS = "Oh My Venus!";
    private static final String EARTH = "Terre-Neuve";

    private final SolarSystem solarSystem;

    public SolarSystemService() {
        solarSystem = new SolarSystem(createPlanets());
    }

    private List<Planet> createPlanets() {
        return Arrays.asList(
                new Planet(MERCURY, 64.568, 0.3285, MERCURY_SPEED),
                new Planet(VENUS, 107.73, 107.73, VENUS_SPEED),
                new Planet(EARTH, 147.54, 5.972, EARTH_SPEED)
        );
    }
}

Notez que la classe "SolarSystemService" fait partie de la couche d'application.

C'est elle qui décide du besoin de l'application par rapport aux planètes, c'est-à-dire qu'elle connait le contexte dans lequel le domaine s'applique.

Ça nous permet de déplacer toute la logique d'affaires dans le domaine (ex. le calcul de distance avec le Soleil).

Il est important de comprendre que le domaine ne connait pas le contexte dans lequel sa logique d'affaires doit être appliquée.

Cette séparation permet à plusieurs applications de reprendre le même domaine dans un contexte différent (ex. un autre système solaire).

Réflexion

Quels changements seraient nécessaires dans le cas où le client demande de pouvoir ajouter/supprimer des planètes à volonté, sans avoir besoin de repartir l'application à chaque fois?

Tout d'abord, on commence par créer des méthodes d'ajout/suppression de planètes dans la classe "SolarSystem".

Ensuite, il faut extraire les valeurs des planètes de la classe "SolarSystemService" vers la solution choisie parmi les choix suivants:

  • Un fichier de resource qui est lu à chaque fois qu'on le modifie.
  • Des calls API rest d'ajout/suppression.
  • Une BD qui contient toutes les planètes et qui est lu à chaque changement (ex. requeue).