📐 Construire une app en JS
05 Commande

Une commande

La réservation d'un hébergement par un locataire est une commande parce qu'elle modifie l'état du système.

Ce qui change

De quelle façon l'état du système est-il modifié ? Qu'est-ce qui a changé ?

On a ajouté une réservation. Enfin peut-être, si la réservation était faisable.

Mais à quoi a-t-on ajouté la réservation ?

Posez la question à votre expert métier. Il vous répond "bah au calendrier des réservations de ce logement".

Evident (pour lui).

L'hébergement n'est pas modifié par une réservation : il ne va pas avoir une chambre ou une piscine supplémentaire.

Le locataire non plus : il n'a pas changé de numéro de téléphone ou de date de naissance en faisant sa réservation. Par contre, on pourrait se poser la question sur les notifications.

Au passage surgit un nouveau concept : le calendrier. Ce qui change dans le système, c'est le calendrier des réservations du logement.

Maintenant, notre test s'affine.

// Avant : le calendrier est vide
const initialCalendar = Calendar.of(accomodation)
expect(initialCalendar.count()).toBe(0)
 
const booking = book(accomodation, tenant, stay);
 
// Après, il comporte une réservation
const alteredCalendar = Calendar.of(accomodation)
expect(alteredCalendar.count()).toBe(1)

Notre test contrôle le changement d'état du système provoqué par la commande.

Observez que l'on se passe même de contrôler la variable booking retournée par la commande. Une commande change le système, donc on se désintéresse de ce qu'elle retourne.

Attribuer la méthode

Notre commande est une fonction. C'est simple.

Et si l'on veut absolument un objet ?

Dit autrement, quel serait l'objet dont la commande book() serait une méthode ?

Puisque c'est le calendrier qui change, c'est naturel de lui attribuer la méthode. Le classe calendrier est reponsable de la logique métier d'une réservation.

// Avant : le calendrier est vide
const calendar = Calendar.of(accomodation)
expect(calendar.count()).toBe(0)
 
calendar.book(tenant, stay);
 
// Après, il comporte une réservation
expect(calendar.count()).toBe(1)

C'est plus simple. Une seule instance calendar est manipulée par notre test. Son contenu (la liste des réservations) va évoluer en raison de la réservation.

L'état de l'objet calendar reflète la modification de l'état du système.

Cette approche est parfaitement valable, mais interroge sur la synchronisation. C'est élégant de modifier l'état de notre objet calendar, mais quelle garantie a-t-on sur le fait que l'état global de l'application est bien modifié ?

const calendar = Calendar.of(accomodation)
expect(calendar.count()).toBe(0)
 
calendar.book(accomodation, tenant, stay);
calendar.save(); // On synchronise notre état local avec l'état du système
 
// Et on reconstruit un nouveau calendrier pour interroger le système
const alteredCalendar = Calendar.of(accomodation)
expect(alteredCalendar.count()).toBe(1)

Notre test semble orchestrer top d'opérations. Pourquoi devrait-il se soucier de cette synchronisation au travers de cette méthode save ? C'est le signe d'un mauvais niveau d'abstraction.

Nous allons corriger cela.

Mais avant, abordons une question sur laquelle la plupart des développeurs font l'impasse.