Quelques pistes de réflexion

Quelques pistes de réflexion #

Nous avons proposé, pour notre gestionnaire de réservations/ressources, deux classes représentant une réservation:

  • Reservation pour une réservation d’un ensemble de ressources qui a été planifié
  • PendingReservation pour la préparation d’une réservation d’un ensemble de ressources qui n’est pas encore planifié

Si ce n’était pas le cas, une réservation pourrait avoir des états différents (planifié ou non planifié), ce qui nous obligerait à fournir davantage de fonctionnalités pour connaître le contexte. Il deviendrait nécessaire de faire des vérifications à l’exécution avant certaines actions et il deviendrait plus difficile à tester ce type d’objets. Quelques exemples de situations embêtantes:

  • pour savoir si deux réservations sont en conflit, elles doivent être planifiées toutes les deux
  • pour sauvegarder une réservation, elle devrait également être planifiée
  • il ne devrait pas être possible d’ajouter une date/heure à une réservation uniquement si elle n’est pas planifiée
  • il devrait être possible de modifier la date/heure d’une réservation uniquement si elle a déjà été planifiée

Exemples de la sauvegarde d’une réservation ou d’une modification:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public boolean trySave(Reservation r) {
    if( r.isScheduled() && !r.hasResources() ) { // est programmée
        List<Reservation> others = allOtherReservations();
        for(Reservation other: others) {
            if( other.isScheduled() && r.isInConflictWith(other) ) {
                return false; // en conflit
            }
        }
        reservationsRepo.save(r);
        return true;
    } else {
        return false; // ne peut être sauvée si elle n'est pas 
                      // planifiée ou si elle n'a pas de ressources
    }
}

1
2
3
4
5
6
if ( aReservation.isScheduled() ) {
    aReservation.changeWith(beginningDateHour);
} else {
    aReservation.scheduleAt(beginningDateHour);
}
trySave(r);

L’avantage de séparer ses deux états et de permettre de vérifier ce genre de contexte à la compilation et non à l’exécution. Le code se simplifie, sa compréhension aussi, mais également les tests unitaires pour vérifier ses règles deviennent inutiles.

Version Reservation et PendingReservation #

Cette version améliore donc la compréhension, réduit les états possibles ainsi que les cas d’utilisation à vérifier/tester.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public boolean trySave(Reservation r) { // maintenant une réservation est forcément planifiée et a forcément des ressources
    List<Reservation> others = allOtherReservations();
    for(Reservation other: others) {
        if( r.isInConflictWith(other) ) {
            return false; // en conflit
        }
    }
    reservationsRepo.save(r);
    return true;
}

1
2
3
4
PendingReservation aPendingReservation = ...;
Reservation aReservation = aPendingReservation.scheduleAt(beginningDateHour);
// trySave(aPendingReservation) ne compile pas !
trySave(aReservation);











comments powered by Disqus