Comment améliorer son développement avec Laravel ?

Published by Ludovic

Cela fait plusieurs années que nous utilisons le framework PHP Laravel au sein de l'agence et que nous cherchons perpétuellement à optimiser notre façon de développer. Si de base Laravel s'appuie sur le pattern MVC pour Model, View et Controller, sa modularité permet toutefois de sortir des conventions. Dans cet article, nous vous proposons de découvrir notre façon d'utiliser Laravel qui s'appuie sur quelques principes SOLID.

KISS & SOLID

Avant même de parler de patterns, nous avons pour habitude de respecter et d'emprunter quelques concepts de développement existant dans ce domaine. Le premier : KISS ne fait pas référence au célèbre groupe de musique mais plutôt à une approche visant à éviter de complexifier le code : "Keep It Simple, Stupid". Autrement dit, si les commentaires dans le code font souvent débat, nous préférons en limiter sa présence au profit d'une lecture du code que même n'importe qui pourrait comprendre. Cela se traduit donc pas du code moins dense, moins de magie, au profit d'une séparation des responsabilités ce qui nous amène au principe : SOLID.

SOLID regroupe à lui seul cinq principes de conception ! Nous détaillerons ici celui qui nous intéresse le plus, à savoir le S pour : "Single Responsibility Principle". En d'autres termes, il s'agit de diviser pour "mieux organiser". Chaque fichier a une responsabilité unique. Pour illustrer notre propos, imaginez avoir besoin de faire un appel vers une API externe. De façon conventionnelle, si l'on s'appuie sur Laravel et le pattern MVC, on pourrait se dire qu'une action du controller pourrait se charger de faire l'appel HTTP vers l'API, puis traiter la réponse et ensuite travailler la réponse.

Le problème est que cela cloisonne ce besoin à un endroit spécifique de votre application, que ces pales pourraient être utilisés ailleurs et que le mélange de responsabilité pourrait très vite congestionner et rendre complexe la relecture de notre action de controller.

Pensez "Service"

Pour faciliter l'approche et l'adoption des concepts KISS et SOLID, que ce soit dans Laravel, Symfony, ou d'autres frameworks, nous suggérons de penser "Services" et à l'injection de dépendances. Concrètement, cela consiste à la mise en place de classes qui sont injectées dans le constructeur d'une partie de votre application. On peut donc assez facilement imaginer un service TwitchApiManager, dont la responsabilité serait de faire des appels HTTP vers l'API de Twitch et de n'en retourner que la réponse. Le traitement de la réponse et la suite qui en découle seraient gérées dans une classe d'Action.

Le pattern Action

À mesure qu'une application grandit et que son besoin métier évolue, l'usage du pattern MVC peut rapidement présenter des limites. Notamment sur la densité d'informations et lignes de code présentes dans le controller. Pour tenter de simplifier votre code métier, nous vous suggérons d'adopter le pattern d'Action. Autrement dit, au lieu de d'écrire la logique d'une portion de votre métier au sein même des différentes actions de votre controller, déportez ce traitement dans une classe d'Action dont la responsabilité est et sera toujours de réaliser le même objectif. Par exemple, on peut très bien imaginer une classe d'Action qui va se charger de faire un appel HTTP vers un endpoint de l'API de Twitch. Bonus en prime, cette classe d'Action peut faire appel au service que nous avions précédemment discuté.

Nous vous suggérons d'ailleurs d'organiser vos Actions en fonction de domaines métier. Ainsi, d'un point de vue arborescence, au sein de votre application Laravel, on peut imaginer le chemin suivant "app/Actions/Twitch/GetChannelFollowers". Si vous souhaitez en connaitre davantage sur le pattern Action au sein de Laravel, un bon point de démarrage peut être de suivre le package Laravel Actions.

Le pattern Repository/Interface

L'un des travers de Laravel est surement son côté magique et l'usage du model builder de façon statique. Si cela se révèle au départ plutôt sympathique de pouvoir récupérer des collections ou des instances d'objet à différents endroits de l'application, centraliser ce besoin devient vite indispensable pour la pérennité de vos données. Ainsi grâce à l'injection de services, il est possible de mettre en place le pattern de Repository/Interface.

Concrètement, nous avons pour habitude d'utiliser le Repository comme moyen pour centraliser les appels vers la base de données. L'interface servant de contrat pour exposer les méthodes du Repository. Grâce au système de tagging et binding de Laravel, vous aurez donc le loisir d'associer votre interface et votre repository pour ensuite vous en servir en tant qu'injection de dépendances dans le constructeur d'une classe d'Action.

Ainsi, plutôt que de faire appel à votre modèle "Article::where('status', $status)->get();" au sein de votre code, il est préférable de le déporter dans une méthode getArticleByStatus(Status $status); de votre Repository. Ainsi vous pourrez plus facilement moduler un changement sur votre besoin, en ne modifiant uniquement les informations présentes dans cette méthode.

Les DTO et le typage fort

En guise de conclusion de cette courte couverture et présentation de nos pratiques de développement, nous vous encourageons très vivement à utiliser le typage fort et autant que possible avoir recourt à des DTO. Derrière, cet acronyme se cache ce que l'on appelle des Data Transfer Objects. L'objectif d'un DTO est d'avoir une représentation plus détaillée d'une donnée mais qui ne dépend pas de votre métier.

Par exemple, lorsque vous traitez la réponse d'un appel API Twitch, il est préférable de ne pas la considérer comme un simple tableau (souvent le cas en PHP, ce qui limite l'interprétation par votre IDE et la compréhension par les développeurs), mais plutôt de le en un objet qui ne retient que les éléments de la réponse qui vous intéressent.

L'usage du DTO ira de paire avec le typage, puisque vous pourrez ainsi faire en sorte que vos méthodes demandent la présence d'un DTO plutôt que d'un simple array, du moins en PHP. En effet, certains langages offrent un typage plus avancé, cela vous permet d'utiliser des génériques dans certains cas. Une bonne introduction des DTO au sein de Laravel peut se faire avec le package Spatie Laravel Data.

Conclusion

Cet article n'est qu'une ébauche des nombreuses pratiques qui existent dans le développement. Il ne s'agit pas d'une méthode à suivre et à respecter, mais plutôt d'un partage de ce qui nous semble aujourd'hui une méthodologie de développement adaptée aux besoins de nos clients !