Jeune développeur web levant les mains avec enthousiasme devant son écran d’ordinateur.

Bonnes pratiques de développement web : le guide du succès du développeur

Le métier de développeur est devenu à la fois très spécifique et si vaste qu’il est facile de s’y perdre. À titre d'exemple récent, une forte onde médiatique au sujet de l'intelligence artificielle a suscité des prédictions alarmantes de la part de certains éminents chercheurs qui annonçaient l’extinction totale de notre profession. Cependant, nous ne sommes pas des machines à écrire du code, et la complexité de notre savoir ne peut s’y résumer.

Il est essentiel de garder un œil sur les pratiques émergentes ; cette démarche est ce que l'on appelle communément la veille technologique. Dans cet article, je vous invite à faire un tour d’horizon des différents grands principes et courants de pensée qui existent aujourd’hui. Ce qu’ils prônent, pourquoi, et leur philosophie. 

Ces principes, que je nomme intentionnellement « dogmes », sont des idées fortes qui sont apparues au fil du temps. Elles réunissent à la fois des bonnes pratiques de développement web et des techniques visant à faciliter le travail du développeur. C’est parti ! 

#1

Appliquez le Clean Code, pour un code lisible ! 

Parue en août 2008, la première édition de Clean Code ou Coder Proprement en français est tout d’abord un ouvrage de référence que nous devons à Robert C. Martin, le bien nommé Uncle Bob. 

Ce livre offre des axes de programmation visant à améliorer la lisibilité du code que nous créons, et par conséquent, à en faciliter la maintenance. 

Pour en savoir plus sur cette bonne pratique de développement web essentielle, je vous invite à consulter mon article « Programmer, oui ; mais programmer propre ! ».

#2

Utilisez l’Architecture Hexagonale ou Clean Architecture 

L’architecture logicielle représente une part importante de notre métier. En effet, pour que les solutions soient viables, commençons par le commencement : les fondations. 

Si vous deviez construire une maison, peu d’entre vous commenceraient par le toit et les murs : nous poserions d’abord les fondations de l’ouvrage. La même procédure s’applique pour un logiciel. Il est nécessaire d'établir les principaux axes à suivre afin de maintenir un projet lisible, facilement maintenable, et in fine, résilient. 

C’est ici que les architectures hexagonales et la clean architecture prennent tout leur intérêt. 

Commençons par distinguer ces deux solutions : l’architecture hexagonale propose un pattern de port et d’adapter (qui représentent les liaisons entre l’application et l’extérieur), tandis que la clean architecture reprend diverses bonnes pratiques de développement web visant à améliorer la robustesse de la solution. Ces deux méthodes ont en commun le principe de l’inversion de dépendance, qui nous oblige à ne plus dépendre d’implémentations, mais d’abstraction. De ce fait, les modules de haut niveau ne doivent plus dépendre des modules plus bas niveau.

Architecture Hexagonale 

L’architecture hexagonale isole la partie métier depuis l’extérieur de l’application. Cela signifie que toute logique applicative ne doit jamais dépendre directement d’un système externe, telle qu’une base de données par exemple. Cette isolation permet de créer une haute résistance au changement, car les modifications extérieures n’impacteront jamais la logique de l’application. 
Cette isolation est rendue possible grâce aux ports dans l’application, et aux adapters à l’extérieur. 

Schéma d'une architecture hexagonale

 

Bien que techniquement, les ports représentent des interfaces, il est possible dans le cadre de l’architecture hexagonale de rencontrer des ports primaires sous forme de classe concrète. Les ports représenteront ainsi les contrats à respecter pour communiquer avec l’intérieur de l’application. L’application est contrôlée par des actions externes qui utiliseront des adapters pour communiquer. Ces adapters sont en fin de compte des classes qui implémentent les interfaces, c’est-à-dire qui assurent le contrat avec le port de l’application.

Distinguons les adapters qui conduisent l’applications, appelés adapters primaires (souvent représentés à gauche des schémas) et les adapters pilotés, appelés adapters secondaires (souvent représentés à droite sur les schémas). 

Clean Architecture 

La clean architecture a été concrétisée dans le livre « Clean Architecture : A Craftsman Guide to Software Structure and Design » paru en 2017 et signé une fois encore par Robert C. Martin, avec les participations de James Grenning et Simon Brown. 

Cette architecture s’applique globalement sur les sujets complexes, qui nécessitent une séparation claire des concepts utilisés par l’application. Elle est donc très utilisée dans le cas de projets complexes et conséquents. Vous trouverez sûrement des exemples concernant la modélisation des clients dans les ressources que vous lirez (un client au sens comptable n’est pas le même qu’au sens commercial). 

Elle est généralement représentée sous forme de cercles concentriques.

Schéma explicatif clean architecture

 
Elle souligne l’importance du Domain Driven Design (DDD), un sujet que nous explorerons en détail plus loin dans l'article. 

  • Au centre se trouvent les entités : il s’agit des objets métier qui représentent notre domaine. 

  • Autour, nous retrouvons les use cases, qui s’apparentent à la partie Application de l’architecture Hexa. 

  • Plus haut se situent les controllers (attention, il ne s’agit pas ici du même terme technique que les controllers de votre framework favori : il s’agit de l’élément qui contrôle l’application). 

  • La partie bleue représente l’inconnu, soit l’extérieur de l’application. 

L’hexagone, représenté par les parties rouge et jaune, contient toujours les ports. La partie verte représente ce qu’on peut appeler l’infrastructure, contenant notamment les adapters. Dans la clean architecture, on parlera de controllers pour les adapters primaires/pilotes et de gateway pour les adapters secondaires / pilotés. 

La Clean Architecture introduit également la notion de Presenter, des classes dont le rôle consiste à transformer le retour de l’application en une réponse plus simple à soumettre à la vue. Cela peut transformer le retour en JSON par exemple, ou à créer un objet simple avec des propriétés simples. On évitera les types complexes ici : par exemple, les dates sont transformées en chaînes de caractères. 

#3

Découpez vos projets en microservices 

Commençons par comparer cette architecture à son extrême opposé : le monolithe

Un monolithe est une application composée d’un seul gros bloc. C’est-à-dire qu’elle n’est composée que d’un seul projet regroupant toutes les fonctionnalités inhérentes au programme. 

Son exact opposé, l’architecture en microservices se décompose, elle, en plusieurs projets. L’intérêt premier de cette décomposition est de ne laisser qu’une seule responsabilité à chacun des microservices. Dans l’exemple d’une boutique en ligne, il s’agirait d’avoir un microservice pour le paiement, un pour le panier, un autre pour les produits, etc. 

Schéma composition microservices

 

L’API Gateway n’est en réalité qu’un point d’entrée dans l’ensemble des microservices. Il permet, entre autres, de gérer les appels et de réaliser leur orchestration. 

Les avantages de l’architecture en microservices sont nombreux. Ils sont plus faciles à créer et déployer, mais également à maintenir. En effet, puisque chaque microservice n’a comme responsabilité qu’une partie bien définie de l’application, cela simplifie le code et les dépendances internes. De même, si un bug est repéré sur une partie de l’application, il est plus aisé de le corriger sans impacter l’intégralité de l’application. Encore mieux : si un microservice tombe en panne, cela n’affectera pas le fonctionnement de toute l'application. 

Les microservices simplifient de plus la collaboration en équipe, avec un grand nombre de développeurs. Chaque microservice est développé par une équipe qui détermine son propre rythme. Cette méthode offre enfin l’opportunité de développer des produits polytechnologiques avec des équipes spécialisées. 

#4

Suivez le manifeste Agile Software Craftmanship  

Vous avez très certainement au moins entendu ces mots. Mais qu’est-ce que c’est ? 

Les valeurs de ce mouvement sont fortement inspirées du livre « The pragmatic programmer: from journey man to master » (Andy Hunt et Davis Thomas ; 1999). Dans ce sillage de l’Agilité, Robert C. Martin proposera en 2008 une cinquième valeur au manifeste Agile : « Craftsmanship over execution » traduit par « L’artisanat plutôt que l’exécution ». Cela donnera naissance au manifeste Software Craftsmanship. 

Image des quatres fondements du manifeste agile "manifesto for software craftmanship"

 

Quatre fondements 

« Not only working software, but also well-crafted software » 

Vous rappelez vous de la première fois où vous avez fait du vélo sans roulettes ? De la première longueur à la piscine sans vos brassards ? Vous aviez certainement ressenti de la fierté. C’est ce qu’encourage ce premier pilier du craft : soyez fiers de ce que vous produisez. Ce sentiment témoigne d'une conception soignée du code qui facilitera toute révision ultérieure. 

« Not only responding to change, but also steadily adding value » 

Apporter un changement, réparer un dysfonctionnement, c’est bien. Mais y ajouter de la valeur, c’est mieux. L’idée consiste à participer au changement, d’être actif dans l’amélioration continue du produit. Comme refactoriser une série de « if » dans un switch (ceci n’est qu’à titre d’exemple, et bien évidemment, je ne conseille pas de systématiquement réaliser des switch). Faites preuve d’autant d’excellence que vous savez le faire. 

« Not only individuals and interactions, but also a community of professionals » 

Ne travaillez pas en silo, ne vous contentez pas de faire ce que vous savez faire. Au-delà du métier, être développeur revient également à faire partie d’une immense communauté. À travers des conférences, des blogs, ou bien des vidéos, vous aurez l’opportunité d’échanger ou d’enrichir vos connaissances. Si vous lisez ces lignes, j’ai une bonne nouvelle : vous êtes sur la bonne voie ! Continuez ! 

« Not only customer collaboration, but also productive partnerships » 

Les clients sont de véritables partenaires tout au long du projet. Ils savent ce qu’ils attendent, et pourquoi. Dans le meilleur des cas, ils savent même comment l’outil fonctionne. Établir une collaboration étroite se révèle mutuellement bénéfique. Cependant, soyez professionnels ! Apprenez à dire non lorsque la situation dégénère, selon vous : blocage technique, contraintes fonctionnelles... Ne pas dire oui à tout amène souvent à une relation plus saine. Le client gagnera en confiance en constatant que vous l'accompagnez activement, plutôt que de simplement exécuter ses demandes. 

#5

Appliquez le Domain Driven Design 
 

L’un des enjeux majeurs dans notre profession est la compréhension du besoin du client, et par conséquent la compréhension de son métier. Pour comprendre ce qui est attendu, il faut donc que notre modélisation colle au plus près à ce qui est utilisé, manié, par les utilisateurs finaux de l’application. 

C’est à cet enjeu que répond le Domain Driven Design (abrégé DDD). Il nous contraint à utiliser le vocabulaire* exact du métier concerné (*nous reverrons plus tard ce terme de vocabulaire). Plus le code s’ajustera au métier, plus il sera aisé de comprendre les éventuels bugs et d’expliquer au client les difficultés rencontrées au cours du développement web. 

Le grand principe autour du DDD consiste à partitionner correctement les différentes facettes du logiciel que nous concevons. Par exemple, vous ne modéliserez pas de la même façon un client si vous êtes dans un contexte de livraison, ou dans un contexte de facturation, vous n’aurez pas besoin des mêmes informations : dans le premier cas, vous utiliserez son nom et son adresse, alors que dans le second, vous aurez potentiellement son nom et son RIB. 

Ce sujet étant extrêmement vaste, je ne pourrai l’aborder de façon exhaustive. Nous nous concentrerons sur quelques concepts qui me paraissent être clés dans cette démarche. 

Ubiquitous Language 

L’ubiquité, késako ? C’est la capacité à être partout à la fois. Vous voyez venir le truc ? 
L’ubiquitous language est donc un langage qui se trouvera partout, autrement dit, parlé par tous. Vous vous souvenez lorsque je vous parlais de vocabulaire ? Eh bien, nous y sommes. 
Le but de l’ubiquitous language est de rassembler, au sein d’un langage partagé, les termes métier liés au domaine de l’application. Chaque partie prenante doit accepter et utiliser ce nouveau langage spécifique. 

Schéma explicatif de l'ubiquitous language

 

Lors de la phase de conception, invitez les acteurs du projet à définir un glossaire des termes liés au domaine métier. Chaque partie prenante peut proposer ses idées. Mais gardez toutefois à l’esprit que ce langage doit refléter parfaitement les spécificités métier. Il est donc essentiel que les experts du domaine aient systématiquement le dernier mot quant au choix des termes utilisés. 

Event Storming 

Comme son nom l’indique, nous évoquerons ici les évènements. L’objectif d’un event storming consiste à se focaliser sur les évènements qui se produiront sur l’application (ex : l’utilisateur ajoute un article à son panier).  Tous les acteurs du projet doivent être conviés, du développeur à l'expert métier, en passant par les utilisateurs finaux, sans oublier le propriétaire du produit. De manière conventionnelle, l’event storming est réalisé sur un mur en y accrochant des post-it, et l’histoire y est déroulée horizontalement. C’est-à-dire, à partir d’une action réalisée sur le produit, en passant par les conséquences intermédiaires jusqu’à la conséquence finale. 

  • Les évènements sont décrits au participe passé (ex : Paiement Reçu) 

  • On y ajoute également les commandes (à gauche des évènements), qui représentent in fine les déclencheurs. 

  • Elles sont décrites à l’infinitif (ex : Payer) 

D’autres variables peuvent être ajoutées : 

  • Les acteurs (qui vont utiliser la commande) 

  • Les données (on reste synthétique pour mettre en exergue l’intention) 

  • Les services externes (service de paiement tiers, par exemple) 

Schéma explicatif event storming montrant plusieurs post-it avec différentes étapes du projet

Nous nous concentrons dans un premier temps sur le parcours le plus représentatif et simple du scénario, afin d’obtenir une première vision large et concrète de la direction à prendre. Il sera tout à fait possible de programmer un nouvel event storming ultérieurement afin de détailler de nouveaux  aspects. Il est donc possible de réaliser un event storming en cas de constat d’un nombre de bugs trop important ou une mauvaise compréhension de l’attente du client. 

Modélisation 

Afin de créer un domaine qui représente au mieux le métier que l’on souhaite synthétiser, il faudra donc commencer par une partie de modélisation. Cet exercice permettra de créer les classes que nous manipulerons plus tard dans le code. 

Aggregat 

Martin Fowler le définit ainsi : « Un agrégat est un groupe d'objets du domaine qui peuvent être traités comme une seule unité ». Un agrégat possède une entité qui représente la racine (root). Il s’agit de l’unique composant capable de communiquer avec le reste de l’application, les autres seront formellement internes à l’agrégat. 

Attention toutefois à ne pas confondre un agrégat avec une simple collection. Une collection est en ensemble de données du même type. Un agrégat est une composition de plusieurs données cohérentes entre elles. Ce concept appartient au domaine, par exemple, une playlist dans une application de streaming. 

Entity 

Nous nous appuyons ici sur la définition d’Eric Evans (dont je vous recommande les excellents ouvrages « Domain-Driven Design: Tackling Complexity in the Heart of Software » et « Implementing Domain-Driven Design ») : « Objets qui ont une identité distincte qui traverse le temps et les différentes représentations. On les appelle aussi "objets de référence". ». 

Les entités sont des objets du domaine, soit la représentation précise d’un concept précis. Elles possèdent une vie et une évolution. En effet, leurs valeurs pourront évoluer au cours de leur vie dans l'application. Elles possèdent forcément un identificateur, car elles doivent être uniques. C’est également le premier endroit dans le code où mettre de l’intelligence : du code métier, représentant… le métier. 

Value Object 

Toujours selon Eric Evans, les « value object » représentent des « objets qui n'ont d'importance qu'en tant que combinaison de leurs attributs. Deux value objects ayant les mêmes valeurs pour tous leurs attributs sont considérés comme égaux.. Comme le nom l’indique, ils représentent l’aspect valeur d’un concept. Les value object n’ont donc pas d’identité propre et sont immuables. Un exemple courant concerne un billet : un billet de 20€ sera toujours un billet de 20€. Il ne changera pas de valeur. Tout comme une adresse. 

#6

Employez le Test Driven Development 

Qui n’a jamais entendu la fameuse phrase « tester c’est douter » ? Et combien de malheureux se trompent  en affirmant cela… Le principe du Test Driven Development (abrégé TDD), consiste à placer ses tests au centre de la préoccupation. 

Schéma du cycle test driven development


La pratique du TDD réunit trois phases : 

  1. En premier lieu, nous rédigeons un test décrivant l'objectif à atteindre. Ce test se trouve alors dans un état erroné, étant donné qu'aucun code n'a encore été écrit. 

  1. On écrit le code strictement nécessaire pour faire passer le test. 

  1. On peut refactoriser le code pour le rendre plus maintenable, tout en gardant son test vert. 

Et on recommence pour coder la fonctionnalité que l’on souhaite implémenter. 

  • Pour illustrer cette idée, je vous présente une bonne pratique de développement web pilotée par les tests (TDD) appliquée au cas très basique du FizzBuzz. L'objectif est de rédiger : « Fizz » pour les multiples de 3, 

  • « Buzz » pour les multiples de 5, 

  • « FizzBuzz » pour les multiples des deux. 

 

1) Le test doit échouer.

Exemple test driven qui échoue Message d'échec du test driven development

2) Le code suivant doit être minimal afin que le test soit un succès. 

Code du test driven development valide Message de réussite du test driven development

3) On peut refactoriser en gardant le test vert. 

Code du test driven development valide Message de réussite du test driven development

 

#7

Utilisez la méthode Behavior Driven Development 

Nous évoquions plus haut la nécessité de s'aligner sur le vocabulaire spécifique au domaine, en utilisant les termes métier appropriés. Cependant, comprendre pourquoi et comment ces divers modules interagissent les uns avec les autres et quels sont les comportements attendus est tout aussi important. Cette approche contribue à minimiser les erreurs comportementales et à renforcer la compréhension des attentes. C'est précisément l'objectif du Behaviour Driven Development (abrégé BDD). 

Selon Uncle Bob lui-même, le BDD représente tout simplement une évolution du TDD.  

Post twitter de Uncle Bob Martin parlant du BDD


En réalité, l'objectif est de concevoir des tests qui compris de tous, en utilisant un langage naturel.  

Les tests résultant du BDD adoptent généralement la forme de ce modèle, appelé « synthaxe Gherkin ». : 

Given [mise en place du contexte] 
When [une action] 
Then [résultat] 

Given Le client consulte son panier avec 1 article 

When Le client supprime l’article du panier 

Then Le panier est vide 

Les 3 amigos 

Une technique de BDD consiste à réunir simultanément un minimum de  trois profils lors des ateliers de spécifications : un expert métier, un développeur ainsi qu’un challenger. L’expert métier a pour mission de décrire le besoin et l’attente ; le développeur représentera la force de mise en œuvre ; et le challenger apportera un point de vue externe qui incitera à aborder les problématiques sous un angle différent. 

Application technique 

En fonction du framework et du langage sur lesquels vous travaillez, vous pourrez opter pour le plugin Gherkin qui convient le mieux. Le plus répandu est probablement cucumber.io. Pour illustrer ce propos, je prendrai l'exemple de SpecFlow avec .Net en utilisant leur guide de démarrage.

exemple code pensé behavior drive development exemple code pensé behavior drive development exemple code pensé behavior drive development

Comme vous pouvez le constater, en partant de la syntaxe Gherkin, nous décrivons un scénario que nous décomposons ensuite en étapes à suivre pour vérifier le bon fonctionnement de la fonctionnalité. 

#8

Travaillez en mode Pair/Mob Programming 

Avez-vous déjà vécu la frustration de vous retrouver bloqué sur un bug ? A-t-il déjà été nécessaire de consacrer plus de temps que prévu à une fonctionnalité ? Et pour finir, n'avez-vous jamais été libéré de cette impasse en discutant avec un collègue qui avait expérimenté ce problème et qui vous a offert une solution appropriée ?  

Ce sont précisément les types de situations auxquelles les méthodes de programmation en binôme (pair programming) et en groupe (mob programming) visent à répondre.  

On distingue deux rôles : 

  • Le pilote : écrit le code 

  • Le co-pilote  : guide le pilote en fournissant des indications sur la manière de résoudre le problème. 

En alternant régulièrement sur de courtes périodes, les rôles sont échangés. Le pilote devient co-pilote et vice versa. 

Pourquoi utiliser la méthode du pair/mob programming ? Il existe de nombreux avantages : 
 

Avec deux esprits concentrés sur une même tâche, les solutions envisagées divergent, offrant ainsi une réponse plus complète au problème. Cela se traduit généralement par un code plus soigné et plus sophistiqué. En outre, cette approche facilite le transfert de savoir. Étant donné que deux individus apportent leurs perspectives distinctes, il y a des opportunités d'apprentissage mutuel. 

Cette méthode peut donc être appliquée dans de nombreuses situations, telles que des impasses, l'intégration de nouveaux membres, le partage de connaissances, et bien d'autres. 

Nous avons exploré un large éventail de bonnes pratiques de développement web. Il est évident que notre métier est en constante évolution, offrant sans cesse de nouveaux sujets à explorer pour résoudre les problèmes que nous rencontrons. 

Vous souhaitez échanger avec un expert ?

Contactez-nous