5 applications web impressionnantes développées avec Laravel

Découvrez comment Laravel transforme le développement web avec 5 exemples d'applications, de la mode à l'éducation.

Bienvenue dans le monde fascinant de Laravel, le framework PHP qui a révolutionné le développement web avec sa simplicité, son élégance et sa puissance. Que vous soyez un développeur chevronné ou simplement curieux de découvrir comment les applications web modernes sont construites, Laravel est un outil incontournable qui facilite la réalisation de projets complexes grâce à ses fonctionnalités avancées et son code élégant.

Dans cet article, nous allons plonger dans cinq exemples d'applications web exceptionnelles développées avec Laravel, qui illustrent parfaitement la polyvalence et l'efficacité de ce framework. De la préparation aux tests linguistiques avec GlobalExam à l’apprentissage de la conduite avec Ornikar, en passant par la formation logicielle via Lemon Learning ou encore le recrutement en ligne avec HelloWork, préparez-vous à être inspiré par la créativité et l'innovation que Laravel rend possible. Suivez-nous dans ce voyage à la découverte des meilleures applications Laravel et voyez par vous-même pourquoi ce framework est tant plébiscité dans le monde du développement web.

 

1. GlobalExam : Optimiser la préparation aux tests de langues

 

GlobalExam est une plateforme innovante qui permet aux utilisateurs de se préparer efficacement à divers tests de langues officiels tels que le TOEFL, le TOEIC, et le DELF. Utilisant Laravel, GlobalExam offre une interface flexible et robuste pour l'apprentissage en ligne, la gestion de contenu dynamique, et un suivi personnalisé des progrès des utilisateurs.

GlobalExam tire parti de Laravel pour développer une interface utilisateur qui facilite l'interaction et l'engagement des apprenants. Laravel aide à structurer des parcours d'apprentissage personnalisés en fonction des besoins spécifiques de chaque utilisateur, intégrant des exercices pratiques, des simulations d'examens, et des analyses de performances.

 

Exemple de code pour afficher des exercices personnalisés aux utilisateurs :

public function showExercises(Request $request)
{
	$userLevel = $request->user()->level;
	$exercises = Exercise::where('difficulty', $userLevel)->get();
	return view('exercises.list', compact('exercises'));
}

 

Ce code PHP illustre comment Laravel peut être utilisé pour récupérer et afficher des exercices adaptés au niveau de difficulté de l'utilisateur, en utilisant l'ORM Eloquent pour une extraction efficace des données correspondantes.

 

 

La capacité de Laravel à gérer de grandes quantités de contenu éducatif est essentielle pour une plateforme comme GlobalExam, qui offre des ressources pour une variété de tests dans plusieurs langues. Laravel facilite la mise à jour et l'organisation du contenu, assurant que les informations restent à jour et pertinentes.

 

public function updateContent(Request $request, $contentId)
{
	$content = Content::find($contentId);
	$content->update($request->all());
	return redirect()->back()->with('status', 'Content updated successfully!');
}

Cet exemple montre comment Laravel gère la mise à jour du contenu éducatif, permettant aux administrateurs de la plateforme de maintenir facilement le matériel à jour avec des informations précises et actuelles.

 

Un aspect crucial de la préparation aux tests est le suivi des performances. Laravel aide GlobalExam à collecter et analyser les données des utilisateurs pour fournir des feedbacks détaillés et des recommandations personnalisées. Laravel offre des outils robustes pour le reporting et les analytics, qui sont essentiels pour optimiser les parcours d'apprentissage.

 

public function getUserProgress($userId)
{
	$progress = Progress::where('user_id', $userId)->latest()->first();
	return view('users.progress', compact('progress'));
}

 

Ce code démontre l'utilisation de Laravel pour suivre et afficher les progrès des utilisateurs, en permettant un accès facile aux informations historiques et actuelles sur les performances.

 

GlobalExam est un exemple parfait de la façon dont Laravel peut être utilisé pour développer des applications web complexes, centrées sur l'utilisateur, dans le domaine de l'éducation.

2. Ornikar : Révolutionner l'apprentissage de la conduite

 

Ornikar est non seulement une auto-école en ligne qui offre des leçons de conduite et des cours de code de la route, mais elle transforme également la façon dont les gens apprennent à conduire en France. Utilisant Laravel, Ornikar offre une plateforme flexible et sécurisée pour que les utilisateurs planifient leurs leçons, étudient le code de la route et passent leurs examens, le tout en ligne.

 

Laravel permet à Ornikar de proposer une interface utilisateur (UI) fluide qui s'adapte à tous les appareils, essentielle pour les étudiants en déplacement. La facilité d'utilisation est améliorée par Laravel, qui soutient une expérience utilisateur homogène sur le site web, en permettant de réserver des leçons et d'accéder à des matériaux d'étude interactifs.

 

Exemple de code pour une réservation de leçon dans Laravel :

public function bookLesson(Request $request)
{
	$request->validate([
    	'lesson_date' => 'required|date',
    	'instructor_id' => 'required|exists:instructors,id',
	]);
 
	$lesson = new Lesson([
    	'student_id' => auth()->id(),
    	'instructor_id' => $request->instructor_id,
    	'scheduled_date' => $request->lesson_date,
	]);
 
	$lesson->save();
 
	return redirect()->back()->with('success', 'Lesson booked successfully!');
}

 

Ce code Laravel illustre comment une leçon peut être réservée via la plateforme, en s'assurant que toutes les données sont validées avant de procéder à l'enregistrement dans la base de données.

 

 

Avec un grand nombre d'utilisateurs accédant à des cours variés, la gestion efficace du contenu est cruciale. Laravel aide Ornikar à organiser et à mettre à jour ses contenus éducatifs de manière dynamique, garantissant que les informations sont toujours actuelles et pertinentes.

public function updateCourseMaterial(Request $request, $courseId)
{
	$course = Course::findOrFail($courseId);
	$course->update($request->all());
 
	return redirect()->back()->with('status', 'Course material updated successfully!');
}

 

Ce morceau de code permet aux administrateurs de mettre à jour facilement le matériel de cours, en utilisant l'ORM Eloquent de Laravel pour une interaction fluide avec la base de données.

 

Ornikar utilise Laravel pour suivre les progrès des étudiants et analyser les données d'utilisation pour améliorer continuellement leurs services. Cette fonctionnalité est essentielle pour fournir un feedback personnalisé aux étudiants et pour ajuster les méthodes d'enseignement en fonction des besoins des utilisateurs.

public function getStudentProgress($studentId)
{
	$progress = Progress::where('student_id', $studentId)->latest()->get();
	return view('students.progress', ['progress' => $progress]);
}

 

Ce code utilise Laravel pour récupérer et afficher les progrès d'un étudiant, aidant les instructeurs et les étudiants à visualiser les améliorations au fil du temps et à identifier les domaines nécessitant une attention supplémentaire.

 

Ornikar est un exemple éloquent de la manière dont Laravel peut être utilisé pour transformer des industries traditionnelles comme l'éducation à la conduite.

 

3. Lemon Learning : Transformer la formation logicielle en entreprise

 

Lemon Learning est une plateforme innovante qui révolutionne la formation logicielle en entreprise en intégrant des guides interactifs directement dans les outils SaaS utilisés par les entreprises. Grâce à Laravel, Lemon Learning offre une solution fluide et intégrée qui aide les employés à maîtriser rapidement et efficacement divers logiciels, en réduisant le temps nécessaire à la formation et en maximisant la productivité.

 

L'un des défis majeurs pour Lemon Learning était d'assurer une intégration transparente de ses guides interactifs avec une multitude d'applications d'entreprise sans perturber l'expérience utilisateur. Laravel a permis de développer une API robuste et sécurisée qui s'interface facilement avec n'importe quel logiciel d'entreprise utilisé par les clients.

 

Exemple de code pour une API Laravel gérant les requêtes d'intégration :

Route::post('/integration/setup', 'IntegrationController@store');
 
public function store(Request $request)
{
	$this->validate($request, [
    	'software_id' => 'required|exists:softwares,id',
    	'client_id' => 'required|exists:clients,id',
    	// Autres validations nécessaires
	]);
 
	$integration = new Integration([
    	'software_id' => $request->software_id,
    	'client_id' => $request->client_id,
    	// Autres paramètres
	]);
 
	$integration->save();
 
	return response()->json(['message' => 'Integration setup successfully!'], 201);
}

 

Ce code illustre comment Laravel peut être utilisé pour créer des endpoints API qui facilitent l'intégration de la plateforme Lemon Learning avec divers logiciels d'entreprise, permettant des configurations personnalisées pour chaque client.

 

 

Laravel aide également Lemon Learning à gérer de manière dynamique et efficace les contenus de formation. La plateforme doit constamment mettre à jour et personnaliser les tutoriels pour s'adapter aux logiciels qui évoluent rapidement. Laravel offre des outils puissants pour la gestion de contenu qui facilitent ces mises à jour régulières.

 

public function updateTutorial(Request $request, $tutorialId)
{
	$tutorial = Tutorial::findOrFail($tutorialId);
	$tutorial->update($request->all());
 
	return redirect()->back()->with('success', 'Tutorial updated successfully!');
}

 

Ce morceau de code permet aux administrateurs de Lemon Learning de mettre à jour les tutoriels directement via le tableau de bord, en utilisant l'ORM Eloquent pour une interaction efficace avec la base de données.

 

Un autre aspect crucial de Lemon Learning est le suivi des progrès des utilisateurs et l'analyse des performances des tutoriels. Laravel fournit des capacités sophistiquées de reporting et d'analyse qui permettent à Lemon Learning d'offrir des insights précieux aux entreprises sur l'efficacité des formations.

public function getUserProgress($userId)
{
	$progress = Progress::with('tutorials.completed')->where('user_id', $userId)->get();
	return view('progress.show', compact('progress'));
}

 

Ce code utilise Laravel pour recueillir et présenter des données détaillées sur la progression de chaque utilisateur, aidant les entreprises à mesurer l'impact réel de la formation sur la productivité et l'efficacité des employés.

 

Lemon Learning illustre parfaitement la capacité de Laravel à soutenir des solutions technologiques innovantes dans le domaine de la formation en entreprise.

 

4. HelloWork : Dynamiser le recrutement en ligne

 

HelloWork est une plateforme française leader dans le domaine du recrutement en ligne, qui connecte les employeurs aux candidats à travers une interface intuitive et efficace. Utilisant Laravel, HelloWork optimise les processus de recherche d'emploi et de recrutement, facilitant les interactions entre les entreprises et les chercheurs d'emploi grâce à des fonctionnalités avancées et une gestion fluide des données.

 

La plateforme HelloWork repose sur Laravel pour fournir une expérience utilisateur (UX) riche et interactive, facilitant la navigation, la recherche d'emploi et la gestion des candidatures. Laravel aide à structurer une interface utilisateur qui répond rapidement aux actions des utilisateurs, améliorant ainsi leur engagement et leur satisfaction.

 

Exemple de code pour afficher les offres d'emploi selon les filtres de l'utilisateur :

 

public function listJobs(Request $request)
{
	$jobs = Job::query();
 
	if ($request->has('location')) {
    	$jobs->where('location', $request->location);
	}
	if ($request->has('keyword')) {
    	$jobs->where('title', 'like', '%' . $request->keyword . '%');
	}
 
	return view('jobs.index', ['jobs' => $jobs->paginate(10)]);
}

 

Ce code illustre comment Laravel peut être utilisé pour créer des filtres dynamiques qui ajustent les résultats de recherche en fonction des préférences des utilisateurs, rendant la recherche d'emploi plus ciblée et efficace.

 

Laravel fournit à HelloWork les outils nécessaires pour gérer dynamiquement des milliers d'annonces d'emploi et de profils de candidats. L'ORM Eloquent intégré permet une manipulation aisée des données, assurant une mise à jour et une récupération efficace des informations pertinentes.

public function updateJob(Request $request, $jobId)
{
	$job = Job::findOrFail($jobId);
	$job->update($request->all());
 
	return redirect()->back()->with('success', 'Job updated successfully!');
}

Ce morceau de code montre comment les annonces d'emploi peuvent être mises à jour facilement par les employeurs, garantissant que les informations restent actuelles et précises.

 

La capacité de suivre les candidatures et d'analyser le comportement des utilisateurs est cruciale pour optimiser les stratégies de recrutement. Laravel aide HelloWork à collecter et analyser les données des utilisateurs, fournissant des insights précieux pour les employeurs sur l'efficacité de leurs annonces.

public function trackApplications($jobId)
{
	$applications = Application::where('job_id', $jobId)->get();
	return view('employers.analytics', ['applications' => $applications]);
}

 

Ce code utilise Laravel pour récupérer et afficher les données sur les candidatures reçues pour un poste spécifique, permettant aux employeurs de mesurer l'intérêt et l'efficacité de leurs annonces.

 

HelloWork démontre l'efficacité de Laravel dans le développement de solutions de recrutement en ligne.

 

5. Ecodrop : Faciliter le recyclage pour les professionnels du BTP

 

Ecodrop est une plateforme innovante qui révolutionne la gestion des déchets de construction en facilitant le recyclage pour les professionnels du BTP en France. Utilisant Laravel, Ecodrop offre une solution efficace pour localiser les points de collecte les plus proches, gérer les déchets de manière responsable, et optimiser la logistique des déchets de chantier.

 

Laravel aide Ecodrop à fournir une interface utilisateur claire et facile à naviguer, permettant aux professionnels de trouver rapidement des solutions de recyclage à proximité. La plateforme permet également une interaction fluide pour la réservation de collectes de déchets, la consultation des prix et le suivi des transactions.

 

Exemple de code pour la recherche de centres de recyclage par localisation :

public function searchRecyclingCenters(Request $request)
{
	$centers = RecyclingCenter::query();
	if ($request->has('zipcode')) {
    	$centers->where('zipcode', $request->zipcode);
	}
	return view('recycling.centers', ['centers' => $centers->get()]);
}

 

Ce code montre comment Laravel peut être utilisé pour filtrer les centres de recyclage en fonction du code postal fourni par l'utilisateur, simplifiant ainsi la recherche et aidant les professionnels à trouver les options les plus pratiques.

 

 

Laravel fournit les outils nécessaires pour gérer efficacement les profils des utilisateurs et les commandes de collecte de déchets. Les professionnels peuvent s'enregistrer, gérer leurs informations, et planifier des collectes en quelques clics.

public function updateProfile(Request $request)
{
	$user = Auth::user();
	$user->update($request->all());
 
	return redirect()->route('profile')->with('success', 'Profile updated successfully!');
}

 

Ce morceau de code illustre la mise à jour du profil utilisateur avec Laravel, utilisant l'authentification intégrée et l'ORM Eloquent pour une interaction sécurisée et efficace avec la base de données.

 

Laravel aide Ecodrop à suivre les transactions et à analyser l'efficacité des services offerts. La plateforme collecte des données sur les types et volumes de déchets collectés, permettant des analyses approfondies pour améliorer continuellement le service.

public function getTransactionDetails($transactionId)
{
	$transaction = Transaction::with('user', 'recyclingCenter')->findOrFail($transactionId);
	return view('transactions.detail', ['transaction' => $transaction]);
}

 

Ce code utilise Laravel pour récupérer les détails d'une transaction spécifique, y compris les informations sur l'utilisateur et le centre de recyclage, facilitant le suivi et l'analyse des services de collecte.

 

Ecodrop illustre parfaitement comment Laravel peut être exploité pour développer des solutions durables et efficaces dans le secteur du BTP.

 

En explorant ces cinq applications fascinantes développées avec Laravel - de GlobalExam à Ecodrop, en passant par Ornikar, Lemon Learning, et HelloWork -, il est clair que Laravel ne se contente pas d'être un simple outil de développement web. Il représente une solution complète qui offre flexibilité, efficacité et puissance pour relever les défis du développement web moderne. Chaque exemple met en lumière la capacité de Laravel à transformer des idées ambitieuses en réalités numériques robustes et performantes, offrant des expériences utilisateur riches et intuitives.

Que vous soyez un développeur cherchant à affiner vos compétences ou une entreprise en quête d'innovation, Laravel se présente comme le framework de choix pour créer des applications web qui se distinguent. En définitive, ces cinq exemples ne sont qu'un aperçu de ce qui est possible avec Laravel, ouvrant la porte à un monde de potentiel illimité pour les développeurs et les entreprises du monde entier.

Sommaire
Nos autres catégories
Partager sur :
Nos autres catégories
Partager sur :

Ne manquez rien
Abonnez-vous à notre newsletter

Notre newsletter tous les mois :
Je m'abonne
Merci ! C'est dans la boîte :)
Oops! Something went wrong while submitting the form.

Nos experts vous parlent
Le décodeur

Vue.js vs React.js : quel Framework pour son projet ?
4/12/2023

À l'ère du développement web, choisir le bon Framework frontend peut définir le succès de votre projet. Aujourd'hui, plongeons dans le débat Vue.js vs React.js. Quel géant du JavaScript convient le mieux à votre vision ? C'est la question à laquelle nous répondrons dans cette comparaison détaillée. Explorez les fondamentaux, découvrez les différences clés, et faites un choix éclairé pour votre prochaine aventure digitale.

Les fondamentaux de Vue.js et React.js

Entamons notre exploration en mettant en lumière les caractéristiques distinctives de Vue.js et React.js, deux incontournables du développement JavaScript.

Vue.js : une approche progressive

Vue.js se démarque par son approche incrémentielle. Son système de composants facilite l'intégration avec des projets existants, offrant une simplicité appréciée. L'outil Vue CLI permet un démarrage rapide, un atout pour les projets de toutes envergures.

La partie écrite en HTML propose une balise div avec l'id app, qui est la zone d'application que Vue.js cible.

À l'intérieur de cette balise, nous avons un bouton avec un événement @click qui déclenche la méthode showMessage() lorsque le bouton est cliqué. Le paragraphe avec la directive v-if  s'affiche uniquement lorsque la propriété messageVisible est true.

Enfin, la partie script JavaScript est écrite en Vue.js. Elle créée une nouvelle instance de Vue avec les données et les méthodes nécessaires. Lorsque le bouton est cliqué, la méthode showMessage() est appelée pour rendre le message visible.

En résumé, ce code Vue.js crée une application basique avec un bouton qui, une fois cliqué, fait apparaître un message dans un paragraphe. La logique de rendu conditionnel est gérée par les propriétés réactives de Vue.js (messageVisible, dans ce cas).

React.js : la puissance du Virtual DOM

React.js brille avec le concept de Virtual DOM, améliorant significativement les performances. Sa flexibilité s'étend au-delà des applications web, permettant le développement d'applications mobiles avec React Native. Create React App offre, quant à lui, une entrée en matière rapide pour les nouveaux projets.

Une image contenant texte, capture d’écran, logiciel, ordinateurDescription générée automatiquement

Dans cet exemple, nous utilisons la fonction useState() de React pour déclarer et initialiser l'état du composant fonction App. Sa syntaxe est simplifiée grâce à l'utilisation d’une fonction fléchée.

Pour des projets réels, il serait préférable d'utiliser des outils comme Create React App ou Nextjs pour une configuration plus complète et une structure de dossier organisée.

Comparaison directe

Plongeons maintenant dans une analyse détaillée des différences clés entre Vue.js et React.js, mettant en lumière les points qui pourraient orienter votre choix.

Performance et DOM virtuel

En matière de performances, Vue.js excelle avec son système de rendu réactif. React.js, quant à lui, mise sur la puissance du Virtual DOM pour des applications fluides et réactives. Un point crucial à considérer selon les exigences de votre projet.

Facilité d'apprentissage et courbe d'apprentissage

Vue.js se distingue par sa courbe d'apprentissage douce, idéale pour les débutants. À l'inverse, React.js offre une courbe d'apprentissage plus prononcée, mais son écosystème robuste attire les développeurs expérimentés. Un choix à faire en fonction de votre équipe et de vos délais.

Composants et modularité

Vue.js brille avec son système de composants intuitif, favorisant la réutilisabilité. React.js propose également une approche modulaire, mais dans un écosystème plus vaste. Choisissez en fonction de la complexité de votre application et de vos besoins en modularité.

Choisir en fonction de vos besoins

Maintenant que nous avons disséqué les différences, concentrons-nous sur la prise de décision. Comment choisir entre Vue.js et React.js en fonction de vos besoins spécifiques ? C'est ce que nous allons explorer dans cette section.

Vue.js excelle dans le développement d'applications web, offrant simplicité et efficacité. À l'inverse, React.js élargit son spectre en permettant également le développement d'applications mobiles grâce à React Native. La nature de votre projet guidera ce choix crucial.

Vue.js se distingue par sa simplicité d'intégration avec HTML et CSS, facilitant la transition pour les développeurs. React.js adopte une approche JSX, plus proche du JavaScript pur. La préférence pour l'une ou l'autre dépendra de votre équipe et de vos préférences de codage.

Communautés actives et support

Entrons maintenant dans le monde des communautés, un aspect essentiel pour le succès continu d'un Framework. Voyons comment Vue.js et React.js se positionnent en termes de soutien et de ressources.

La communauté Vue.js connaît une croissance significative. Des forums actifs, des tutoriels, et un soutien en ligne abondant font de Vue.js une option attrayante pour ceux qui apprécient une communauté en pleine expansion.

Vue.js dispose d'un forum officiel où les développeurs de tous niveaux peuvent poser des questions, partager leurs expériences et discuter des meilleures pratiques. La communauté est connue pour être accueillante et réactive.

Les meetups et les conférences dédiés à Vue.js sont organisés régulièrement dans le monde entier. Ils offrent une excellente occasion de rencontrer d'autres développeurs, de partager des idées et d'en apprendre davantage sur les nouvelles fonctionnalités et les meilleures pratiques.

La documentation officielle de Vue.js est très complète et bien organisée. Elle propose des guides, des exemples concrets et une référence exhaustive pour aider les développeurs à comprendre et à utiliser Vue.js de manière efficace.

Vue Mastery propose des cours en ligne avancés pour les développeurs Vue.js de tous niveaux. Ces cours couvrent une variété de sujets, de l'apprentissage des bases à des sujets avancés tels que la gestion d'état avancée.

React.js, avec l'une des plus grandes communautés, offre une richesse de ressources et de forums de discussion. La stabilité et la maturité de la communauté React.js en font un choix rassurant pour ceux qui recherchent une base solide de soutien.

Le répertoire GitHub de React est un centre actif de collaboration. Les développeurs peuvent signaler des problèmes, proposer des fonctionnalités, et contribuer directement au développement du Framework.

Reactiflux est une communauté React sur Discord où les développeurs peuvent discuter en temps réel, poser des questions et partager leurs expériences.

La documentation officielle de React est exhaustive et mise à jour régulièrement. Elle couvre tout, de l'installation à des sujets avancés tels que les Hooks, les Context API, et la gestion d'état.

La communauté React est très active sur Stack Overflow. Les développeurs peuvent poser des questions et obtenir des réponses rapides de la part de la communauté.

Nos conseils pour optimiser votre choix

Nous arrivons à la phase cruciale de la prise de décision. Comment optimiser votre choix entre Vue.js et React.js ? Découvrons des conseils pratiques pour guider cette étape.

Vue.js se démarque par son accent sur une expérience utilisateur fluide. Ses fonctionnalités réactives et sa simplicité d'utilisation en font un choix idéal pour des applications offrant une expérience utilisateur exceptionnelle.

Quel que soit le choix, misez sur la qualité. Évitez des refontes coûteuses en privilégiant la qualité dès le début. Des applications bien conçues offrent une base solide pour le succès à long terme, que vous optiez pour Vue.js ou React.js.

En fin de compte, le choix entre Vue.js et React.js est personnel, dépendant de vos besoins spécifiques, de la nature de votre projet, et de vos préférences. Dans la prochaine section, rappelons l'essentiel de cette comparaison et offrons une vision claire pour vous aider à faire le choix éclairé qui propulsera votre projet vers le succès.

En conclusion, le choix entre Vue.js et React.js est une décision cruciale, dépendante de la nature unique de votre projet. Que vous soyez séduit par l'approche progressive de Vue.js ou par la puissance du Virtual DOM de React.js, l'essentiel est de faire un choix éclairé.

À travers cette comparaison, nous avons exploré les fondamentaux, examiné les différences clés, et offert des conseils pratiques pour guider votre décision.

N'oubliez pas : la clé du succès réside souvent dans la simplicité. Optez pour le Framework qui s'aligne le mieux avec vos besoins, tout en privilégiant la qualité dès le départ. Que vous choisissiez Vue.js ou React.js, transformons ensemble votre vision en une réalité digitale.

Si des questions persistent ou si vous avez besoin d'un accompagnement plus approfondi, n'hésitez pas à nous contacter. Chez Yield Studio, nous sommes là pour concrétiser vos projets avec expertise et engagement.

Test Driven Development (TDD) : Guide pour un Développement Efficace
21/9/2023

L'origine


Le Test-Driven Development plus communément appelé TDD n'a pas été inventé par une seule personne mais par plusieurs développeurs. Kent Beck est souvent la personne la plus affiliée au TDD parce qu'il est celui qui l'a popularisé lors de ses travaux sur la méthodologie Extreme Programming à la fin des années 90. Néanmoins il est important de rappeler qu'il n'est pas le créateur de l'outil qu'est le TDD, il a été mis en place pour tout un tas de personne, dont notamment Martin Fowler (co-auteur du Manifeste Agile) ou encore Ward Cunningham et Ron Jeffries qui ont fondé l'Extreme Programming avec Kent Beck.


Un outil de travail


L'outil


Le TDD est un outil de travail qui permet au développeur de coder en étant guidé par les tests. Il permet d'avancer étape par étape, petit pas par petit pas, pour avancer vers une solution toujours plus fiable.


Cette solution plus fiable est notamment due à sa forte proximité avec les principes SOLID. En effet, le TDD facilite la mise en place des principes SOLID. En écrivant d'abord des tests, il est plus naturel de concevoir un code simple et cohérent qui respecte les principes tels que l'encapsulation, le découplage, la gestion des dépendances et la séparation des responsabilités. On se retrouve plus naturellement avec des modules indépendants et l'injection de dépendances, ce qui conduit à du code plus propre.


Le TDD et les principes SOLID vont donc de pair pour une conception logicielle de qualité.



  1. Nous avons une première phase (rouge sur le schéma) où nous devons écrire un test qui échoue, basé sur une spécification. NB : on n'écrit pas de code de production (code final) tant que le test n'est pas en échec.
  2. La deuxième phase (verte sur le schéma) consiste à faire passer le test en succès en écrivant du code de production et tout en restant le plus simple possible. NB : on écrit uniquement le code nécessaire pour faire passer le test et sans retourner dans le code du test.
  3. La dernière phase (bleue sur le schéma) concerne le refactoring. On met à jour le code en appliquant les bonnes pratiques, le clean code, etc. Une fois que le refactoring est fait, si les tests passent toujours, on conserve le refactor et on passe aux prochaines spécifications, sinon, on annule le refactor et on essaye autre chose. NB : ne doit jamais effectuer de refactoring dans les autres phases, seulement ici.


L'approche TDD est un développement itératif et incremental qui met l'accent sur la qualité du code.


Le manifeste


Le TDD respecte certains principes qui sont :


  • Baby steps instead of large-scale changes

On avance petit pas par petit pas pour avoir une boucle de feedback rapide et régulière.


  • Continuous refactoring instead of late quality improvements

On améliore le code en continue, on s'en occupe tout de suite parce qu'un refactor annoncé pour plus tard n'arrive finalement en général jamais.


  • Evolutionary design instead of big design up front

On développe ce qui est nécessaire et suffisant et on évolue progressivement.


  • Executable documentation instead of static documents

Les tests mis en place pendant le TDD sont en réalité une documentation executable. L'idée est de lier la documentation avec le code pour s'assurer qu'elle est bien à jour et maintenue.


  • Minimalist code instead of gold-plated solution

Un code simple et qui fonctionne plutôt qu'une solution surdimensionnées avec un niveau de complexité bien trop élevé et pas nécessaire.




Le test propre

Given When Then


L'approche Given When Then est basée sur une convention développée dans le cadre du Behaviour-Driven Development autrement appelé BDD. Il s'agit d'une approche de développement axée sur la collaboration et la spécification du comportement à travers ds scénarios clairs et compréhensibles.


En utilisant cette convention on divise le test en trois parties :

  1. Given, la condition préalable au test
  2. When, l'exécution du système testé
  3. Then, le comportement attendu


Exemple : Given user is not logged in When user logs in Then user is logged in successfully


Should When


L'approche Should When est une convention de nommage facile à lire et plus largement utilisée.


En utilisant cette convention on divise le test en deux parties :

  1. When, la condition préalable au test
  2. Should, le comportement attendu


Exemple : Should have user logged in When user logs in


Arrange Act Assert


Le modèle Arrange Act Assert autrement appelé AAA est un pattern descriptif et révélateur des intentions pour structurer le test.


Le test est alors organisé de la manière suivante :

  1. La partie Arrange contient la logique de configuration du test. C'est ici qu'on initialise le test.
  2. La partie Act execute le système que l'on souhaite tester. C'est ici qu'on fait l'appel d'une fonction, d'un composant, d'un call API, etc.
  3. La partie Assert, vérifie que le système testé se comporte comme prévu. C'est ici qu'on vérifie que le résultat obtenu correspond au résultat attendu.


Exemple :




F.I.R.S.T.


Le principe F.I.R.S.T. est un ensemble de principes qui définissent les caractéristiques d'un test propre et de qualité.


Ces caractéristiques sont les suivantes :

  • Fast, un test doit être rapide et efficace de manière à pouvoir être exécuté fréquemment pour avoir un feedback régulier
  • Independent, les tests doivent être indépendants les uns des autres afin d'être exécutable individuellement et efficacement
  • Repeatable, un test doit être répétable dans n'importe quel environnement et à tout moment
  • Self-Validating, les tests doivent retourner un succès ou un échec afin de vérifier lui même si l'exécution du test a réussi ou échoué sans évaluation manuelle
  • Timely, les tests doivent être écrit avant ou en même temps que le code de production. ils doivent être maintenus et exécutés régulièrement


Quand l'utiliser ?


Quand ne pas l'utiliser plutôt !


Il n'est pas nécessaire et pas utile de faire du TDD quand on a pas de spécifications, quand les tests n'apportent rien, quand les tests sont trop lents, quand il n'y a pas de logique.


La démo


L'incontournable Fizz Buzz


Le Fizz Buzz est un exercice populaire qui permet d'appréhender la méthode TDD. Ce n'est qu'un échantillon et qu'un début de la méthode, mais ça reste intéressant.


Les spécifications sont les suivantes :

  • On commence à compter à partir de 1 jusqu'à 100
  • Lorsqu'on rencontre un nombre divisible par 3, on retourne "Fizz"
  • Lorsqu'on rencontre un nombre divisible par 5, on retourne "Buzz"
  • Lorsqu'on rencontre un nombre divisible par 3 et par 5, on retourne "Fizz-Buzz"


Nous allons utiliser le TypeScript pour mettre en place cet algorithme et le tester.


Première spécification


On créé un fichier test fizz-buzz.test.ts et on créé notre premier test qui va gérer la spécification où on teste le nombre 1.





Ici, le test ne passe pas parce qu'on a pas encore créé la fonction fizzBuzz() et encore moins l'algorithme associé. Nous sommes donc à la première phase du TDD, la phase rouge, celle où on écrit un test qui échoue.


On va maintenant passer à la deuxième phase du TDD, celle où on va faire passer le test au vert. Pour cela, on va créer le fichier fizz-buzz.ts et écrire le code permettant de gérer notre cas de spécification.




Ici, on pourrait avoir tendance à faire un return String(n) directement, mais TDD nous dit de commence par écrire le code le plus simple possible pour faire passer le test au vert, et en réalité le plus simple et rapide et de tout simplement retourner 1 directement.


On va passer au prochain test qui est de tester l'input 2.



Le test échoue parce qu'on a pas encore géré ce cas dans notre fonction. On retourne donc dans notre fonction et on essaye de résoudre ce cas de la manière la plus simple et rapide.




Ici, encore une fois, le plus rapide est de retourner 2 si on a 2 en input.


Maintenant on arrive à la troisième et dernière phase du TDD, celle du refactor. En effet, actuellement nos tests passent avec succès, le code est simple, mais il pourrait l'être encore plus en appliquant de bonnes pratiques.


On va donc revenir sur notre fonction fizzBuzz() sans modifier les tests.




Notre fonction est maintenant simple, propre et concise et les tests sont toujours verts. Notre refactor est donc réussit, on peut passer à la prochaine spécification.


Deuxième spécification


Nous devons maintenant faire en sorte de retourner Fizz si l'input est divisible par 3.



Le test échoue, on va maintenant gérer le cas du Fizz dans la fonction.




Le code le plus simple pour retourner  Fizz quand on a 3 et de tester si n === 3.


On va maintenant gérer un deuxième cas où on a un nombre divisible par 3.




Le test échoue, on met à jour le code.




Le code le plus simple pour retourner Fizzquand on a 3 ou 6 et de faire un ||, mais on se rend bien compte qu'on peut améliorer le code en utilisant le modulo de 3. Les tests sont tous verts, donc on peut se permettre de passer à la phase de refactor en modifiant uniquement le code de la production.



Refactor terminé, tous les tests sont verts, on peut passer à la prochaine spécification.


Troisième spécification


Nous devons maintenant faire en sorte de retourner Buzz si l'input est divisible par 5.


On va aller un peu plus vite, mais le procédé est le même, on va d'abord faire un test avec un input 5 puis 10, puis refactor.




Dernière spécification


Nous devons maintenant faire en sorte de retourner Fizz-Buzz si l'input est divisible par 3 et par 5.


Comme pour les spécifications précédentes, on va faire un test avec un input 15 puis 30 et enfin refactor.


Et voilà !


Le mot de la fin


Stop aux amalgames ! Le TDD n'est pas un outil pour avoir une bonne couverture de code avec les tests, ce n'est pas simplement "faire des tests". Le TDD est un outil dont le but est de guider le développeur vers un objectif. Il permet de donner un feedback régulier afin de s'assurer qu'on est toujours sur la bonne voie. Il faut le voir comme un GPS, qui nous donne des directions à suivre (tourner à droite, aller tout droit pendant 2km, etc.) jusqu'à atteindre un objectif.


Les dédicaces


L’Architecture Hexagonale sur un projet Web + Mobile (Partie 2 sur 5)
28/2/2024

Dans l'article précédent nous avons initialisé notre monorepo, la CI, le framework de test et préparé la structure de notre projet et plus précisément de notre Architecture Hexagonale pour la lib core.

Dans ce nouvel article de la série notre objectif va être de mettre en place l'Architecture Hexagonale et de montrer comment grâce à elle nous allons pouvoir développer et créer de la logique métier sans UI (donc sans ouvrir le navigateur ou l'app mobile). Pour cela nous allons travailler en TDD (Test-Driven Development, vous pouvez voir mon article à ce sujet) et utiliser le feedback des tests.

L'Architecture Hexagonale

La structure cible

Pour rappel, voici la structure que l'on va mettre en place à l'issue de cet article :

- src
    - wallet
       - __ tests __
         - wallet.service.test.ts
       - domain
         - wallet.ts
         - wallet.repository.ts
         - wallet.service.ts
       - infrastructure
         - in-memory-wallet.repository.ts
         - local-storage-wallet.repository.ts
         - mmkv-wallet.repository.ts
       - user-interface
         - wallet.store.ts

Chose promise, chose due ! Nous allons maintenant rentrer dans le détail de chaque fichier, à quoi ils servent et ce qu'ils contient.

Développer en TDD

Lorsqu'on travaille en TDD on commence par le test et ce test va nous guider vers un objectif. Il va nous assurer qu'on suit le bon chemin à l'aide de la boucle de feedback régulière qu'on obtient à l'aide des tests. Pour en savoir plus sur la méthodologie à suivre pour faire du TDD je vous invite à nouveau à lire mon article à ce sujet.

Nous allons commencer par travailler sur l'entité Wallet qui correspond à un portefeuille qui a un solde négatif ou positif (par exemple on peut avoir le portefeuille "Compte Principal Julien" qui a un solde positif de 1000€).

Voici les tests mis en place pour cette entité :

describe('Wallet Service', () => {
	let service: WalletService

	beforeEach(() => {
		const repository = new InMemoryWalletRepository()
		service = new WalletService(repository)
	})

	test('getAll > should retrieve all wallets', async () => {
		const newWallet = { id: '1', name: 'Wallet 1', balance: 0 }

		await service.create(newWallet)
		const retrievedWallets = await service.getAll()

		expect(retrievedWallets).toEqual([newWallet])
	})

	test('get > should retrieve a wallet according to an id', async () => {
		const newWallet = { id: '1', name: 'Wallet 1', balance: 0 }

		await service.create(newWallet)
		const retrievedWallet = await service.get(newWallet.id)

		expect(retrievedWallet).toEqual(newWallet)
	})

	test('create > shoudl create a wallet', async () => {
		const newWallet = { id: '1', name: 'Wallet 1', balance: 0 }

		const createdWallet = await service.create(newWallet)
		const retrievedWallets = await service.getAll()
		const retrievedWallet = await service.get(createdWallet.id)

		expect(createdWallet).toEqual(newWallet)
		expect(retrievedWallets).toEqual([newWallet])
		expect(retrievedWallet).toEqual(newWallet)
	})

	test('update > should update the specified wallet', async () => {
		const newWallet = { id: '1', name: 'Wallet 1', balance: 0 }
		const updatedWallet = { id: '1', name: 'Wallet 1', balance: 100 }

		await service.create(newWallet)
		const retrievedWallet = await service.get(newWallet.id)
		const modifiedWallet = await service.update(updatedWallet)
		const retrievedModifiedWallet = await service.get(modifiedWallet.id)

		expect(retrievedWallet).toEqual(newWallet)
		expect(modifiedWallet).toEqual(updatedWallet)
		expect(retrievedModifiedWallet).toEqual(updatedWallet)
	})

	test('delete > should delete a wallet according to an id', async () => {
		const newWallet = { id: '1', name: 'Wallet 1', balance: 0 }

		await service.create(newWallet)
		const retrievedWallet = await service.get(newWallet.id)
		await service.delete(newWallet.id)
		const retrievedWallets = await service.getAll()

		expect(retrievedWallet).toEqual(newWallet)
		expect(retrievedWallets).toEqual([])
	})
})

On peut comprendre via ces tests que les cas d'utilisations de notre entité sont :

  • getAll, récupération de tous les portefeuilles
  • get, récupération d'un portefeuille en particulier
  • create, création d'un portefeuille
  • update, mise à jour d'un portefeuille
  • delete, suppression d'un portefeuille

Nous allons voir maintenant comme réussir à mettre en place ces tests.

Domain

Nous allons commencé par créer le contenu de la partie Domain. Dans cette partie nous allons retrouver tout ce qui représente le problème à résoudre (problème métier). C'est une partie qui doit être totalement indépendante.

L'entité

Commençons par créer notre entité Wallet correspondant à un portefeuille.

type Wallet = {
	// un identifiant unique (ex: 4d0c2e72-be1a-4e2c-a189-2f321fcdc3a4)
	id: string

	// un nom (ex: Compte Principal Julien)
	name: string

	// un nombre positif ou négatif pour le solde (ex: +1000€)
	balance: number
}


Le repository

Maintenant que notre entité est définie, nous allons définir une interface que l'on appelle également port qui va préciser comment interagir avec cette entité. Nous utilisons ici un modèle de conception d'inversion de dépendances qui nous permet de rester totalement libre sur les outils à utiliser pour respecter cette interface. Nous pourrons très bien implémenté cette interface en utilisant une base de données, une API ou un localStorage par exemple, le domaine s'en fiche.

interface WalletRepository {
	getAll(): Promise
	get(walletId: string): Promise
	create(wallet: Wallet): Promise
	update(wallet: Wallet): Promise
	delete(walletId: string): Promise
}

Le service

Nous avons notre entité et nous savons commencer interagir avec, maintenant nous allons créer un service qui va consumer une implémentation du de notre interface repository (partie suivante dans l'infrastructure).

class WalletService implements WalletRepository {
	constructor(private repository: WalletRepository) {}

	getAll() {
		return this.repository.getAll()
	}

	get(walletId: string) {
		return this.repository.get(walletId)
	}

	create(wallet: Wallet) {
		return this.repository.create(wallet)
	}

	update(wallet: Wallet) {
		return this.repository.update(wallet)
	}

	delete(walletId: string) {
		return this.repository.delete(walletId)
	}
}

Infrastructure

L'infrastructure est composée des différentes implémentations des ports du domaine, on les appelle également Adapters. Ici, nous aurons du code spécifique pour consommer une technologie concrète (une base de données, une API, etc.). C'est une partie qui ne doit dépendre uniquement du domaine.

L'implémentation du repository

Nous allons maintenant voir l'une des implémentation possible de notre WalletRepository. Pour commencer nous allons faire du in-memory, pratique notamment pour la mise en place des premiers tests de nos cas d'utilisations.

class InMemoryWalletRepository implements WalletRepository {
	private wallets: Wallet[] = []

	getAll() {
		return Promise.resolve(this.wallets)
	}

	get(walletId: string) {
		return Promise.resolve(this.wallets.find((wallet) => wallet.id === walletId))
	}

	create(wallet: Wallet) {
		this.wallets.push(wallet)
		return Promise.resolve(wallet)
	}

	update(wallet: Wallet) {
		const index = this.wallets.findIndex((w) => w.id === wallet.id)
		this.wallets[index] = wallet
		return Promise.resolve(wallet)
	}

	delete(walletId: string) {
		const index = this.wallets.findIndex((w) => w.id === walletId)
		this.wallets.splice(index, 1)
		return Promise.resolve()
	}
}

Comment dis précédemment, il s'agit d'une des multiples implémentation possible de notre WalletRepository. Nous pouvons très bien imaginer plus tard mettre en place un LocalStorageWalletRepository ou bien un SupabaseWalletRepostory.

Vous pouvez consulter mon répertoire public de broney sur GitHub pour voir mon implémentation de ces 2 repository et notamment de comment j'ai adapté ma série de test pour garantir leur bon fonctionnement.

User Interface

La partie user interface est composée de tous les adaptateurs qui constituent les points d'entrée de l'application. Les utilisateurs utilisent ces adaptateurs pour pouvoir interagir avec le coeur de l'application. Dans notre cas nous allons régulièrement utiliser des stores en utilisant la libraire Zustand. Il s'agit d'une libraire JS minimaliste pour la gestion d'états (une solution plus complexe serait par exemple Redux).

Voyons voir comment articuler notre store Zustand pour permettre à l'utilisateur d'interagir avec le coeur de l'application.

import { createStore } from 'zustand/vanilla'
import { InMemoryWalletRepository } from '../infrastructure/in-memory-wallet.repository'
import { WalletService } from '../domain/wallet.service'
import { Wallet } from '../domain/wallet'

const repository = new InMemoryWalletRepository()
const service = new WalletService(repository)

type States = {
	wallets: Wallet[]
	currentWallet: Wallet | undefined
}

type Actions = {
	load: () => void
	setCurrentWallet: (wallet: Wallet) => void
	getWallet: (walletId: string) => void
	createWallet: (wallet: Wallet) => void
	updateWallet: (wallet: Wallet) => void
	deleteWallet: (walletId: string) => void
}

export const walletStore = createStore()((set) => ({
	wallets: [],
	currentWallet: undefined,

	load: async () => {
		const allWallets = await service.getAll()
		set({ wallets: allWallets })
	},

	setCurrentWallet: (wallet) => set({ currentWallet: wallet }),

	getWallet: async (walletId: string) => {
		const wallet = await service.get(walletId)
		set({ currentWallet: wallet })
	},

	createWallet: async (wallet: Wallet) => {
		const newWallet = await service.create(wallet)
		set((state) => ({ wallets: [...state.wallets, newWallet] }))
	},

	updateWallet: async (wallet: Wallet) => {
		const updatedWallet = await service.update(wallet)
		set((state) => ({
			wallets: state.wallets.map((w) => (w.id === updatedWallet.id ? updatedWallet : w)),
			currentWallet: state.currentWallet?.id === updatedWallet.id ? updatedWallet : state.currentWallet,
		}))
	},

	deleteWallet: async (walletId: string) => {
		await service.delete(walletId)
		set((state) => ({
			wallets: state.wallets.filter((w) => w.id !== walletId),
			currentWallet: state.currentWallet?.id === walletId ? undefined : state.currentWallet,
		}))
	},
}))


Avec ce store on remarque qu'on va pouvoir facilement, dans n'importe quel environnement JavaScript, charger, définir, récupérer, créer, mettre à jour et supprimer des portefeuilles, tout en maintenant un état global pour l'ensemble des portefeuilles et du portefeuille courant.

Conclusion

Nous avons maintenant terminé ce deuxième article de cette série sur le développement d'une application web et mobile avec l'Architecture Hexagonale et le partage de la logique métier et des composants UI.

Dans cette deuxième partie nous avons vu comment travailler en TDD et surtout comment écrire de la logique métier sans avoir à ouvrir une quelque interface à l'exception du terminal pour les retours de tests.

Nous avons également eu un aperçu de comment nous allons interagir avec nos applications avec le coeur de l'application, via notre store Zustand. Nous irons plus loin à ce sujet dans le prochain article, la troisième partie : Partager de la logique métier et des composants entre le Web et le Mobile.

Échangeons sur votre projet !

Développement web
Application mobile
Data & IA
Nous contacter

Simulateur

Bienvenue dans le
simulateur d’estimation

Sélectionnez
vos besoins

Sélectionnez un ou plusieurs choix

Définissez les
fonctionnalités

Sélectionnez un ou plusieurs choix

Dernière
étape !

Renseignez votre adresse mail pour recevoir l’estimation !
Obtenez l’estimation
Précédent
Suivant

Bravo ! Vous avez terminé
l’estimation de votre future app !

Vous recevrez dans votre boite mail l’estimation personnalisé. Une estimation vous offre la possibilité de vous projeter dans un budget, vous permettant ainsi de planifier en toute confiance. Néanmoins, chez Yield, nous adoptons une approche agile, prêts à remettre en question et ajuster nos évaluations en fonction de l'évolution de vos besoins et des spécificités de votre projet.
Retour au site
Oops! Something went wrong while submitting the form.