UC-01 · Un use case sert une seule opération
Signal
- Une méthode
save,updateouupsertqui sert plusieurs situations métier, selon les champs fournis. - Des paramètres optionnels ou un
Partial<Dto>, suivis d’une cascade deif (x !== undefined) entity.setX(x). - Un
Object.assign(entity, dto)sur un objet du domaine. - La création et la modification dans la même méthode.
- Un endpoint
PATCHgénérique qui alimente une telle méthode.
Pourquoi
La signature ne montre aucune intention. Personne ne sait quelles combinaisons sont valides, ni pourquoi la méthode existe.
Elle a bien plus de façons de mal tourner que de cas corrects, et aucun test ne peut prouver qu’elle ne fait rien de travers. Le code a perdu la trace de sa raison d’être : c’est l’effet d’un anemic model (ENT-10).
Exceptions
Un bounded context déclaré transaction-script (CTX-14) : chaque méthode de son service est un use case (TXS-01).
Correction
Une méthode par use case (suspendHolder, blockWallet), qui appelle une méthode métier du modèle. L’interface envoie alors des intentions plus précises.
Côté API, des endpoints nommés d’après les intentions, plutôt qu’un PATCH générique.
Adaptation
Notre choix : un handler par use case, séparés en commands et en queries (UC-08). Une command (debit-wallet.command.ts : DebitWalletCommand et DebitWalletHandler) travaille sur des aggregates à travers des repositories. Une query (get-wallet.query.ts : GetWalletQuery et GetWalletHandler) lit des views à travers un view port. Chaque handler a une seule méthode handle() ; les refus reviennent dans un Result. Les étapes communes à plusieurs commands vont à une place déjà prévue : une méthode de repository, un domain service, une factory. Jamais dans un helper, ni dans un service à multiples méthodes.