GLO-4002 - Site du cours 2023

Temps estimé: 30 minutes

Exercices sur le modèle hexagonal

Code de base

Pour l'exercice suivant, considérez cette classe où tout est dans le main().

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

class FrequentFlyerCalculator {
    private static final LocalDate CALCULATION_PERIOD_START = LocalDate.of(2020, 9, 10);
    private static final LocalDate CALCULATION_PERIOD_END = LocalDate.of(2020, 11, 10);

    public static void main(String[] args) {
        String passengerName = args[0];

        List<Flight> flights = findAllPassengerFlights(passengerName);

        FrequentFlyerPoints points = new FrequentFlyerPoints();
        points.addAllFlightsWithinDates(flights, CALCULATION_PERIOD_START, CALCULATION_PERIOD_END);

        updatePoints(passengerName, points);
    }

    private static List<Flight> findAllPassengerFlights(String passengerName) {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("example");

        EntityManager entityManager = factory.createEntityManager();
        Query<Flight> query = entityManager.createNativeQuery("SELECT flight_date, flight_duration FROM flights WHERE passenger_name = ?;", Flight.class);
        query.setParamenter(1, passengerName);
        List<Flight> flights = query.getQueryList();
        entityManager.close();
        return flights;
    }

    private static void updatePoints(String passengerName, FrequentFlyerPoints points) {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://external-frequent-flyers-api.com/flyers/" + passengerName + "/points"))
            .timeout(Duration.ofMinutes(1))
            .header("Content-Type", "application/x-www-url-form encoded")
            .POST("points=" + points.getTotalPoints())
            .build();

        HttpClient.newHttpClient()
            .send(request, BodyHandlers.ofString());
    }
}

Il existe également ces 2 classes :

class FrequentFlyerPoints {
    private static final int POINTS_PER_HOUR_OF_FLIGHT = 54;

    private double points;

    public void addAllFlightsWithinDates(List<Flight> flights, LocalDate start, LocalDate end) {
        for (Flight flight: flights) {
            if (flight.getFlightDate().isAfter(start) && flight.getFlightDate().isBefore(end)) {
                double pointsEarned = flight.getFlightDuration().doubleValue() * POINTS_PER_HOUR_OF_FLIGHT;
                points += pointsEarned;
            }
        }
    }

    public double getTotalPoints() {
        return points;
    }
}
class Flight {
    private LocalDate flightDate;
    private BigDecimal flightDuration;

    public LocalDate getFlightDate() {
        return flightDate;
    }

    public BigDecimal getFlightDuration() {
        return flightDuration;
    }
}

Les classes suivantes sont utilisées, mais considérez les comme déjà fournies (provenant de librairies). Ignorez-les pour cet exercice.

  • EntityManagerFactory
  • EntityManager
  • Persistence
  • Query

Note: N'essayez pas nécessairement d'améliorer le code. Ce ne sont pas tous les principes OO qui sont forcément bien respectés, mais au fin de cet exercice, c'est correct. Il manque également les annotations hibernate (pour ceux qui s'y connaissent), mais ce n'est pas important pour cet exercice.

Partie 1

Pour cette partie, nous vous demandons de diviser cette application en plusieurs classes! Tout est codé dans le main(), ce n'est évidement pas bon.

Vous n'avez pas à le coder, faites simplement un UML.

Pour vous aiguiller un peu, demandez-vous

  • Y a-t-il une interface utilisateur?
  • Comment pourriez-vous séparer la "recette" (business case, le quoi) de l'implémentation (le comment)?
  • Y a-t-il moyen de s'assurer que tout ce qui touche au EntityManager soit isolé?

Voici les classes (dans aucun ordre précis) que l'on pourrait identifier. Les flèches ne sont pas dessinées dans solution, vous devriez pouvoir faire cela! Il manque aussi sûrement des interfaces...

Diagramme de classes

Partie 2

Placez toutes ces classes dans le modèle hexagonal vu dans le cours, avec 2 hexagones imbriqués (et non 3 dans ce cas-ci).

La solution exacte n'est pas donnée pour cet exercice.

Cependant, vous devriez avoir 2 classes d'infrastructure , une classe d'interface utilisateur, et le reste dans le domaine (au centre).

Au final, vous devriez seulement avoir des flèches qui pointent vers le centre du modèle hexagonal. Aucune flèche ne devrait pointer vers l'extérieur.