Queopius

Gros contrôleurs dans Laravel

Un contrôleur doit coordonner l'entrée HTTP, et non concentrer la validation, les règles métier, les requêtes, l'autorisation, les transformations, l'envoi d'e-mails et les décisions de flux complètes.

Bilan de santé Laravel5 minutes
Image sélectionnée de l'article Fat Controllers dans Laravel publié dans LinkedIn par Queopius
Bilan de santé LaravelContrôleursArchitectureMaintenabilité

Le contrôleur ne devrait pas être là où tout vit

Dans Laravel, il est très simple de commencer à résoudre la logique directement dans le contrôleur. La requête y arrive, le framework permet de valider facilement, d'interroger des modèles, de renvoyer du JSON et de déclencher des processus. Pour une première version, cette vitesse peut être utile.

Le problème apparaît lorsque ce modèle devient la norme. La méthode store commence par valider, puis décide des autorisations, puis interroge divers modèles, calcule les totaux, crée des enregistrements, envoie des notifications et construit une réponse manuelle. Le contrôleur cesse d'être une passerelle et devient le cas d'utilisation complet.

Un contrôleur sain coordonne. Reçoit la demande, délègue la validation, l'autorisation et l'exécution, et renvoie une réponse. Lorsque vous absorbez tout le comportement, l’application peut continuer à fonctionner, mais chaque point de terminaison devient plus difficile à lire, tester et réutiliser.

Signes d'un contrôleur trop gros

Le signe le plus évident est la méthode de stockage, de mise à jour ou de destruction sur plusieurs lignes. Mais la taille n’est pas le seul indicateur. Il convient également d'observer s'il existe une validation manuelle au sein de la méthode, des requêtes complexes, des conditions commerciales mélangées à HTTP, des autorisations répétées ou des transformations de réponses manuscrites.

Un autre symptôme courant est la détection d'envois d'e-mails, de tâches, de notifications ou d'intégrations exécutés directement à partir du contrôleur. Parfois, des try/catch génériques apparaissent également pour cacher des erreurs réelles, dupliquer du code entre les points de terminaison ou des réponses incohérentes selon la personne qui a implémenté chaque méthode.

Si pour tester un comportement métier, vous devez préparer une requête complète, authentifier l'utilisateur, configurer trop de dépendances et tout parcourir HTTP, le cas d'utilisation est probablement trop lié au contrôleur.

Pourquoi se passe-t-il tant de choses ?

Le contrôleur est le premier point visible lorsqu'une requête arrive. Dans un jeune projet, y parvenir semble naturel : c'est à portée de main, cela se comprend vite et cela ne nécessite pas de décider d'une structure. La pression de fournir des fonctionnalités renforce cette décision car créer une action ou un service semble être un travail supplémentaire.

Le problème est cumulatif. Une période isolée ne fait pas de mal. Dix règles réparties entre plusieurs contrôleurs, oui. Lorsqu’il n’existe pas de couche d’application claire, chaque point final finit par résoudre sa propre version du processus. Cela génère des duplications, des incohérences et une architecture trop dépendante du HTTP.

Laravel ne vous oblige pas à écrire de gros contrôleurs. Cela rend tout simplement très bon marché de commencer comme ça. Par conséquent, lorsque l’application soutient déjà l’activité, il vaut la peine de vérifier si cette commodité initiale freine la maintenabilité.

Quels risques cela génère-t-il ?

Un contrôleur de grande taille rend les points finaux plus difficiles à maintenir. La modification d'une règle peut affecter la validation, la persistance, la réponse, les notifications et les autorisations dans la même méthode. Le coût cognitif augmente car le lecteur doit comprendre plusieurs niveaux à la fois.

Des tests plus fragiles apparaissent également. Si le comportement réside à l'intérieur du contrôleur, le tester sans passer par HTTP est compliqué. Cela vous pousse à écrire des tests de fonctionnalités très larges pour les règles qui pourraient être testées plus directement si elles se trouvaient dans une action ou un service.

Le couplage avec HTTP rend difficile la réutilisation de la logique dans les commandes, les tâches, les processus internes ou les alternatives APIs. Un petit changement peut avoir un impact inattendu car la logique n’est pas isolée. À moyen terme, refactoriser est plus effrayant que continuer à accumuler du code.

Comment perdre du poids avec une manette

La première extraction est généralement la validation. Les requêtes de formulaire vous permettent de supprimer les règles HTTP de la méthode et de laisser le contrôleur plus propre. L'autorisation doit être déplacée vers les politiques ou les portes lorsque la décision est répétée ou représente une règle d'accès claire.

Les cas d'utilisation s'intègrent bien dans les actions ou les services. Le nom et la responsabilité importent peu : une classe qui exprime « créer un ordre », « approuver la demande » ou « synchroniser le client » permet de tester le flux sans dépendre de HTTP. Les réponses peuvent être déléguées aux ressources API pour éviter des transformations manuelles dispersées.

Les processus asynchrones, les e-mails volumineux ou les intégrations doivent être dirigés vers Jobs lorsque cela est logique. Les événements et les auditeurs peuvent aider à découpler les effets secondaires, mais ne doivent pas être utilisés comme cachette pour la logique. Les DTO ou Data Objects peuvent être utiles si le projet doit transmettre plus clairement les données entre les couches.

Exemple conceptuel

Avant : une méthode de magasin valide les champs, vérifie les autorisations, crée plusieurs enregistrements, calcule les montants, applique des remises, envoie un e-mail, déclenche une notification, enregistre l'activité et renvoie une réponse personnalisée. Tout fonctionne, mais le contrôleur ne coordonne plus : il exécute l'intégralité du cas d'utilisation.

Après : StoreOrderRequest valide. OrderPolicy autorise. CreateOrderAction exécute le cas d'utilisation. OrderResource transforme la sortie. Un Job gère des tâches lourdes. Le contrôleur est réduit à quelques lignes qui se lisent comme une séquence claire.

L'avantage est pratique. Si la validation change, vous savez où appuyer. Si le cas d'utilisation change, vous l'essayez sans HTTP. Si la réponse change, vous modifiez la ressource. Si l'expédition change, vous examinez le travail. Chaque pièce a moins de raisons de changer.

Liste de contrôle rapide

Un contrôleur mérite d'être examiné s'il contient des méthodes de plus de 40 ou 50 lignes, des règles métier, des validations répétées, des requêtes complexes, des e-mails ou notifications directs, des transformations de réponses manuelles ou une logique en double entre les points de terminaison.

La question utile n'est pas « puis-je déplacer ceci ? », mais « serait-ce plus clair si cette décision était prise en dehors de HTTP ? » Si vous pouvez tester le cas d'utilisation sans passer par une requête complète, l'application sera probablement plus facile à maintenir.

Clôture

Un contrôleur de grande taille est généralement un signe précoce que l'application perd la séparation des responsabilités. Ce n’est pas toujours urgent, mais il convient de le détecter avant que chaque point final ne devienne une pièce fragile.

Si vos contrôleurs commencent à ressembler à des cas d'utilisation complets, un audit backend Laravel peut vous aider à détecter quelle logique doit être extraite en premier et quelles modifications réduiraient le plus de risques.

Votre Laravel affiche-t-il des signaux similaires ?

Si votre application fonctionne, mais que chaque changement commence à être plus lent, plus fragile ou plus difficile à expliquer, un audit backend Laravel peut vous aider à trier les risques, les gains rapides et les priorités techniques.