Déclarer des contrats pour les dépendances
Objectif : Définir les opérations de persistance dont les cas d’usage du carnet ont besoin, au moyen d’une interface indépendante de leur implémentation.
Un service métier qui connaît directement une classe de persistance devient difficile à faire évoluer : changer la façon de stocker les contacts oblige alors à modifier le code métier. Vous allez formaliser ce dont ce service a besoin sans décider comment les données sont stockées. Ce contrat servira de point de rencontre entre les deux composants.
Les responsabilités des couches et les règles du contact ont déjà été établies dans les deux leçons précédentes. Ici, concentrez-vous sur la frontière entre le service métier et la persistance : le service exprime des opérations utiles au carnet, tandis que le dépôt s’engage à les fournir.
Décrire les besoins dans une interface
Une interface PHP énumère des méthodes publiques et leurs signatures, sans fournir leur traitement. Une classe qui l’implémente doit respecter ces signatures. Le contrat est donc vérifiable par PHP : si une méthode manque ou ne correspond pas à la déclaration, la classe ne satisfait pas l’interface.
Créez le fichier src/Depot/DepotInterface.php. Les opérations ci-dessous couvrent la consultation complète, la recherche, la récupération d’un contact pour modification, l’enregistrement, ainsi que la suppression. Les tableaux de contacts ont ici une forme documentée : chaque résultat contient id, nom, courriel et telephone.
<?php
declare(strict_types=1);
interface DepotInterface
{
/**
* @return list<array{
* id: int,
* nom: string,
* courriel: string,
* telephone: string
* }>
*/
public function lister(): array;
/**
* @param string $terme Texte recherché dans les contacts.
* @return list<array{
* id: int,
* nom: string,
* courriel: string,
* telephone: string
* }>
*/
public function rechercher(string $terme): array;
/**
* @return array{
* id: int,
* nom: string,
* courriel: string,
* telephone: string
* }|null
*/
public function trouverParId(int $id): ?array;
/**
* Enregistre un contact et renvoie son identifiant.
* Un identifiant nul indique une création ; sinon, une modification.
*/
public function enregistrer(
?int $id,
string $nom,
string $courriel,
string $telephone
): int;
/**
* Renvoie true si un contact a été supprimé.
*/
public function supprimer(int $id): bool;
}Les annotations de type précisent les entrées et les sorties attendues ; les annotations PHPDoc décrivent plus finement la structure des tableaux. trouverParId renvoie null si aucun contact ne correspond. supprimer indique si une suppression a réellement eu lieu, tandis que enregistrer fournit l’identifiant du contact obtenu.
Choisir un contrat utile aux cas d’usage
Les méthodes correspondent à des besoins de l’application, pas à des détails techniques comme une requête SQL, une table ou une connexion PDO. Ainsi, le service peut demander « rechercher des contacts » sans savoir si le dépôt consulte une base relationnelle ou une autre source. Les signatures demeurent stables tant que le besoin métier ne change pas.
Le contrat fixe aussi des décisions qui doivent être explicites. Ici, une recherche sans résultat renvoie une liste vide, et une suppression d’un identifiant absent renvoie false. Avant d’ajouter une méthode, vérifiez qu’un cas d’usage en a besoin : une interface trop large multiplie les obligations pour chaque implémentation.
Appliquer l’inversion des dépendances
Sans contrat, le service métier est tenté de dépendre de la classe concrète de stockage. Avec ce contrat, il peut s’appuyer sur les opérations décrites par DepotInterface, et le dépôt concret s’engage à les réaliser. C’est le principe d’inversion des dépendances : la politique métier ne dicte pas ses détails à la persistance, et toutes deux se conforment à une abstraction.
Dans la suite du projet, ContactDepot implémentera cette interface et ContactService pourra utiliser le contrat plutôt que la classe concrète. Cette leçon fixe seulement la frontière et ses opérations ; le raccordement des objets, notamment par constructeur, sera traité dans la leçon sur l’assemblage explicite des dépendances.
À retenir
- Une interface PHP décrit des méthodes attendues sans imposer leur implémentation.
- Le contrat du dépôt expose des opérations de consultation et de gestion formulées selon les besoins du carnet.
- Des types de retour précis rendent les résultats et les cas d’absence explicites.
- Le service métier peut dépendre du contrat plutôt que d’une classe de persistance concrète.
La prochaine leçon reliera concrètement les composants en assemblant leurs dépendances de manière explicite.