Nos experts vous parlent
Le décodeur
.webp)
Les métriques DORA sont devenues incontournables pour évaluer et améliorer la performance des équipes DevOps. Ces indicateurs clés permettent de mesurer la rapidité, la stabilité et l'efficacité du processus de développement et de déploiement logiciel.
Dans cet article, nous analyserons en profondeur ces métriques, leurs implications pour les équipes techniques, et comment les implémenter efficacement. Que vous soyez CTO, membre de la DSI ou développeur, comprendre et utiliser les métriques DORA est essentiel pour optimiser vos opérations et garantir la livraison continue de valeur à vos utilisateurs finaux.
Voici un exemple de projet pour lequel nous suivons les DORA Metrics chez Yield Studio :

Pour qui ?
Avant d’attaquer le sujet concrètement, commençons par définir la cible de ces métriques.
Contre toute attente, elles sont transverses. Moyennant une bonne application, les métriques peuvent être consultées par la DSI , le CTO ou le management top level mais elles sont belles et bien pilotées par les équipes techniques. Ces métriques sont également essentielles pour les équipes DevOps qui cherchent à améliorer leur collaboration et leur performance globale.
Pourquoi ?
Assez simplement ce sont des métriques, des KPI, des nombres qui portent plus ou moins de contexte et permettent de quantifier la performance des équipes techniques (software team). Bien souvent, la littérature retient 4 métriques au total bien qu’il en existe une 5ème qu’on évoquera rapidement mais qu’on exclura par la suite.
Elles fournissent des informations précieuses sur la rapidité avec laquelle les équipes DevOps peuvent répondre aux changements, le temps moyen pour déployer du code, la fréquence des itérations et les échecs.
Ces indicateurs sont cruciaux pour :
- Fournir des estimations de réponse réalistes
- Améliorer la planification du travail
- Identifier les domaines à améliorer
- Consolider les investissements techniques et en ressources
Les 4 Principales Métriques DORA
- DF (Deployment Frequency)
Il s’agit de la fréquence à laquelle du code est déployé en production sur une période de temps. Précisions tout de même que le code doit être déployé avec succès. S’il faut rollback chaque déploiement ça compte pas.
C’est également un indicateur de fréquence à laquelle les ingénieurs délivrent de la valeur aux utilisateurs finaux.
Plus elle est élevée et plus les utilisateurs profitent vite des incréments de code.
A titre indicatif, une valeur moyenne est de 1 déploiement par semaine.
- MLTC (Mean Lead Time for Changes)
Il s’agit du temps moyen entre le premier commit et le déploiement en production.
Souvent les développeurs doivent repasser plusieurs fois sur le code produit initialement suite notamment à la re-lecture par d’autre développeurs ou pour apporter des corrections demandées par le product owner.
Dans un autre domaine, cette métrique correspond au temps d’immobilisation (stock).
A titre indicatif, une valeur moyenne est de 1 semaine.
- CFR (Change Failure Rate)
Il s’agit du pourcentage de déploiements en production qui causent un problème.
On le calcule en divisant le nombre d’incident par le nombre de déploiements.
A titre indicatif, une valeur moyenne se situe entre 16 et 30%.
- MTTR (Mean Time To Recovery)
Il s’agit du temps moyen nécessaire pour réparer un problème et remettre le système dans un état stable.
A titre indicatif, une valeur moyenne se situe à moins d’un jour.
Une Cinquième Métrique : La Fiabilité
aSouvent oubliée, cette métrique est plus orientée DevOps/SRE et se base sur des objectifs opérationnels/contractuels (SLA). Elle mesure la capacité à atteindre ou dépasser ces objectifs, fournissant une perspective supplémentaire sur la performance opérationnelle.
Comment mettre en place ces métriques ?
Il existe plusieurs approches pour mettre en places ces métriques. La plus simple reste de s’appuyer sur un outil qui les intègre déjà, comme LinearB.
.png)
Qu’importe le flacon l’outil, pourvu que vous commenciez à mesurer.
Et si cela ne marche pas dans mon cas ?
“Oui mais moi ma feature est complexe, il me faut plusieurs semaines pour terminer, je vais biaiser la moyenne gneu gneu gneu …”
- Découpe ta feature et utilise des feature flags pour délivrer de façon incrémentale.
"Oui mais c’est long de tout tester à chaque fois gneu gneu gneu …"
- Sois flemmard et écris des tests pour automatiser ton job.
TL;DR
Les métriques DORA sont des indicateurs de la production de valeur produit/business.
Elles sont applicables aux DevOps comme aux développeurs et intéressent toute la software team. Pour être pertinentes, les développeurs doivent être acteurs du pilotage de ces métriques car aucun manager ne pourra les forcer à cela.
Une observation macro est que les DORA poussent naturellement à réduire les incréments de code. En effet, en envoyant moins de code à chaque déploiement, on mitige le risque et les déploiements sont naturellement plus rapide.
Notons aussi que les DORA ne se suffisent pas à elle même, elles appellent à d’autre bonnes pratiques que sont le respect du manifeste agile https://agilemanifesto.org/, l’ajout de tests ou encore les principes LEAN de Toyota.
Enfin, avis aux néophytes avides de tableau Excel, si les DORA permettent de quantifier un problème, une lame de fond, elles ne le qualifie pas pour autant. Le sujet central reste un sujet humain, on parle d’équipes d’homme et de femme qui ont leur code, leur cohésion, leur problématique propre. Piloter uniquement les DORA pour présenter un Excel “tout au vert” serait naïf et pourrait compromettre l’équipe ciblée.
Et Yield Studio là dedans ?
Selon la classification mentionnée en annexe Yield Studio se situe en “high performer” et s’améliore en continu pour atteindre prochainement le grade “elite”. Et vous, vous vous situez où dans ce tableau ? Aujourd'hui les DORA Metrics nous permettent de garantir une réelle qualité auprès de nos clients dans les projets qu'ils nous confient.
Source
Valeurs indicatives pour chaque DORA metric
.png)
Source: Google Cloud https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance?hl=en

Si vous développez une application SaaS, un réseau social, une marketplace ou encore une application métier, il est fort probable que vous aillez besoin d’envoyer des e-mails ou des SMS transactionnels à vos utilisateurs.
Si vous vous demandez ce qu’est un message transactionnel, c’est un message automatisé qui fournit aux utilisateurs des informations utiles qui visent à l’aider et améliorer son expérience. Parmi les exemples les plus courants, on retrouve les confirmations de commande, les rappels de rendez-vous et l'authentification à deux facteurs.

L’envoi d’e-mails et de SMS transactionnels avec Laravel est un jeu d’enfant, cette simplicité nous la devons au composant Notifications.
Laravel embarque le support de certains canaux : SMTP, Vonage et Slack. Les développeurs peuvent ensuite intégrer leurs propres canaux et les partager à la communauté sous forme de librairies.
C’est ce que nous avons fait chez Yield Studio en développant des packages pour Brevo, Mailjet et Expo !
Dans ce tutoriel, nous allons vous expliquer étape par étape comment envoyer des e-mails et des SMS transactionnels avec yieldstudio/laravel-brevo-notifier !
Étape 1 : Créer un compte Brevo
Pour commencer, vous devez vous créer un compte sur Brevo et vérifier votre adresse e-mail. Après ça vous pourrez vous rendre sur le tableau de bord.
Le plan Gratuit de Brevo vous permet d’envoyer jusqu’à 300 e-mails par jour, quant au SMS vous devrez charger votre compte avec des crédits SMS, à titre d’exemple le pack de 100 crédits SMS à destination de la France est facturé 4,5€.
Étape 2 : Installer Laravel Brevo Notifier
Après avoir créé votre compte Brevo, nous pouvons continuer l’installation.
Une fois l'installation terminée, nous pouvons éditer le fichier .env
et ajouter les variables suivantes avec vos propres valeurs.
La valeur de BREVO_KEY
peut être obtenue sur votre tableau de bord dans SMTP et API.

Quant à la valeur de BREVO_SMS_SENDER
, elle est limitée à 11 caractères alphanumériques ou 15 caractères numériques. Il s’agit de l’expéditeur que verra votre utilisateur lors de l’envoi SMS (Yield, Amazon, IKEA)
Étape 3 : Authentifier vos expéditeurs
Avec Brevo comme avec de nombreux fournisseurs, les adresses e-mail qui servent à envoyer des e-mails doivent être une adresse authentifiée. Vous pouvez authentifier une adresse e-mail en particulier ou bien directement un nom de domaine.
Vous devez vous rendre dans Expéditeurs, domaines et IP dédiées et ajouter les adresses e-mails ou les domaines qui vous serviront à envoyer des e-mails.

Étape 4 : Générer la Notification
Vous devez ensuite créer une classe pour votre notification, vous pouvez utiliser la commande Artisan ci-dessous, par exemple nous créons une notification OrderShipped
Cette commande génère la classe dans le dossier App\Notifications
. Si ce dossier n’existe pas encore, Laravel le créera pour nous.
Étape 5 : Envoyer un e-mail et un SMS
Assurez ensuite vous de changer le retour de la méthode via
pour y ajouter notre BrevoSmsChannel
et/ou BrevoEmailChannel
Vous pouvez ensuite préparer votre notification en ajoutant la méthode toBrevoSms
et/ou toBrevoEmail
:
Pour envoyer un e-mail transactionnel avec Brevo, vous devez créer des Templates.
Vous pouvez maintenant envoyer votre notification depuis votre controller, un listener ou l’endroit le plus approprié dans votre cas :
Et voilà vous avez envoyé votre première notification avec Brevo ⚡

Conclusion
Et voila, envoyer un e-mail ou un SMS transactionnel avec Brevo à partir d'une application Laravel c’est relativement simple. Créez d'abord un compte Brevo, installez la librairie yieldstudio/laravel-brevo-notifier
, configurez et envoyez votre superbe notification.
Vous pouvez aller encore plus loin en ajoutant des destinataires en copie, des pièces jointes (une facture par exemple) et bien plus.
Sentez-vous libre de tester ce package et d’y contribuer sur Github.

Introduction
En tant que développeurs, nous savons que les projets évoluent constamment : les besoins changent, les designs se métamorphosent et les spécifications initiales peuvent rapidement devenir obsolètes.
Face à cet environnement mouvant, nos composants traditionnels montrent parfois leurs limites. Ils ne sont pas tous adaptés pour faire face de manière flexible et robuste à cette évolution constante.
Qui n'a jamais été frustré par un composant trop rigide pour s'accommoder d'un changement de maquette ou d'une mise à jour des exigences du projet ?
Examinons ensemble, deux exemples, pour illustrer le Design Pattern : Compound Components.

Exemple d’un composant d’UI simple ✏️
Supposons que nous devons créer un composant Card tout ce qu’il y a de plus classique. On a besoin d’affiche un title, une description et un thumbnail.
Voilà une implementation simple de ce que pourrait être ce composant :
Ainsi que son usage :
Jusque là, tout va bien, notre composant est simple à développer, simple à utiliser et facile à relire.
Maintenant, comme dans tous les projets, le besoin évolue et le design de nos composants avec. Admettons, que notre besoin a évolué de façon à ce qu’on ai besoin d’ajouter un bouton sur notre composant Card. Mais, ce bouton ne doit pas apparaître à tous les endroits de mon application.
Ce que l’on va retrouver dans la plupart des projets professionnels aujourd’hui, c’est une surcharge de propriétés sur le composant. Le plus souvent, notre composant serait comme suit :
NB : c’est volontairement exagéré pour mettre en avant le problème. Même sans Compound Components que l’on verra après, on pourra avoir un composant bien plus propre !
Et l’usage du composant serait comme suit :
Observations
Que peux-tu observer sur cet exemple de composant “traditionnel” qui ne représente que de l’UI ?
- Structure rigide
Le composant Card a une structure définie, il contient toujours une image, un titre, une description et un bouton. Il n’y a flexibilité pour changer la structure d’un composant en fonction des besoins.
- Passage de props
Toutes les données dont le composant Card a besoin sont passées via les props. Cela peut devenir encombrant et difficile à maintenir à mesure que nous ajoutons plus de props au composant.
- Moins de réutilisabilité
Les sous-composants ne peuvent pas être réutilisés indépendamment. Par exemple, si nous voulons utiliser seulement le bouton ou l'image de la carte dans un autre composant, cela ne serait pas possible.
- Peu extensible
Ajouter de nouvelles fonctionnalités à la carte nécessite une modification de l'implémentation de la carte elle-même, augmentant potentiellement le risque de créer des bugs non liés.
- Simplicité
Cependant, dans certains cas, cette approche peut être préférable pour sa simplicité. Si votre composant est très simple et n'a pas besoin des avantages offerts par le pattern de Compound Components, le surcoût en complexité peut ne pas en valoir la peine.
Exemple d’un composant plus complexe ✏️
Supposons maintenant que nous devons créer un composant plus complexe, des composants mêmes, qui ont besoin de travailler ensuite pour mettre en oeuvre une fonctionnalité de Todo-list.
Pour cela, nous allons avoir les composants TodoList (pour afficher une liste d’item de todo), TodoItem (qui représente un item de todo), TodoForm (qui représente le formulaire d’un item de todo) et TodoStats (qui affiche des statistiques pour une liste de todo donnée).
Voilà une implementation de ce que pourrait être ces composants :
Ainsi que l’usage de ces composants :
Observations
Que peux-tu observer sur cet exemple de composant “traditionnel” qui ne représente cette fois une fonctionnalité plus complexe ?
- Rigidité
Dans l'état actuel, la structure est assez rigide. Par exemple, si vous voulez une autre variante de TodoItem qui a un bouton pour marquer une tâche comme terminée, ou peut-être une variante de TodoForm qui a des champs supplémentaires, l'adaptation de ces composants à ces scénarios serait plus complexe.
- Passage de props
Les fonctions de suppression et d'ajout sont transmises en tant que props aux composants enfants TodoItem et TodoForm depuis le composant parent HomeScreen. Cela peut devenir compliqué à gérer à mesure que l'application s'agrandit, car chaque fois que vous voulez utiliser ces fonctions, vous devez les transmettre à travers tous les composants intermédiaires.
- Manque d’encapsulation
Les composants TodoItem et TodoForm exposent trop de détails d'implémentation. Par exemple, TodoItem a besoin de connaître non seulement le contenu de la tâche, mais aussi son id et comment traiter une action de suppression. De même, TodoForm doit gérer son propre état et savoir comment gérer une action de soumission. Cela pourrait être évité avec une version composée qui masquerait ces détails.
- Peu extensible et peu lisible
Ce point est suffisamment explicite je pense !
Le Design Pattern : Compound Components 👀
Le Design Pattern : Compound Components s’applique à n’importe quel langage fonctionnant avec des composants et de la gestion d’états. Il s’agit d’une approche qui offre :
- Structure
Le terme "Compound Components" décrit une relation "a un" entre les composants. Un composant comporte plusieurs sous-composants qui travaillent ensemble pour former une unité cohérente. Le composant parent sert de composant de mise en page tandis que les sous-composants déterminent le contenu.
- Flexibilité
Les Compound Components offrent une grande flexibilité dans l'arrangement des sous-composants. Les utilisateurs de cette API de composant peuvent contrôler l'organisation, la structure et la présentation d'un composant.
- Abstraction
Ils permettent une bonne séparation des préoccupations car chaque sous-composant traite une fonctionnalité particulière. Cela permet une meilleure réutilisation des composants et simplifie le test et la maintenance.
- Pas de passage de props
Un avantage majeur du modèle de Compound Components est l'évitement du prop-drilling, qui est un problème où des props doivent être passés à travers de nombreux niveaux de composants. Les Compound Components résolvent ce problème en utilisant le contexte React pour partager la valeur entre les composants.
- Encapsulation
Avec les Compound Components, nous pouvons exposer ce qui est nécessaire et masquer les détails d'implémentation spécifiques. Cela aide à produire un code plus clair et plus facile à maintenir.
Mise en pratique
Maintenant, voyons ensemble un refactor de nos composants précédents en version Compound Components.
Le composant d’UI simple en Compound Components
Reprenons notre composant d’UI simple et convertissons les props title, description, etc. en sous-composants pour en faire une composition comme suit :
Et maintenant l’usage :
Observations
Quelles observations peux-tu faire cette fois ci ?
- Flexibilité
Le Compound Components donne un plus grand contrôle sur l'organisation des éléments dans le rendu. Dans le deuxième exemple d'utilisation, nous avons de l'information supplémentaire et une absence de bouton, ce qui ne serait pas possible avec une version non composée du composant qui limiterait strictement la structure.
- Réutilisabilité
Les sous-composants, comme CardTitle, CardImage, et CardContent peuvent être réutilisés et réarrangés librement. Cette approche réduit la duplication du code et accroît la maintenabilité.
- Lisibilité
Le code est plus facile à comprendre. Alors qu'un composant non composé pourrait avoir un grand nombre de props, ce qui pourrait rendre le code plus difficile à suivre, chaque sous-composant sait clairement quel est son rôle dans le composant de carte.
- Isolation
Les sous-composants (comme CardButton ou CardImage) peuvent être mis à jour indépendamment des autres sous-composants, évitant ainsi les effets de bord inattendus.
- Scalabilité
Les nouveaux sous-composants peuvent être ajoutés facilement en suivant cette approche, permettant au composant de s'adapter et de se développer avec le temps. Par exemple, un sous-composant CardFooter pourrait être ajouté si besoin.
Le composant complexe en Compound Components
Enfin, passons au plus intéressant, le groupe de composant qui représente la fonctionnalité de Todo-list, voilà la version Compound Components :
Ainsi que son usage, drastiquement simplifiée :
Observations
Que peux t-on observer sur cette dernière partie ?
- Flexibilité d’affichage
Avec l'approche de Compound Components, la disposition des composants est beaucoup plus flexible. Vous pouvez choisir de rendre Todos.List, Todos.Form, et Todos.Stats dans n'importe quel ordre ou même de ne pas les afficher en fonction des spécificités des spécifications ou des besoins de votre application.
- Utilisation du Contexte
Grâce à l'utilisation de React Context (TodosContext), vous pouvez facilement partager des données (todos) et des fonctions (add, remove) entre tous les composants enfants. Cela permet d'éviter le problème de prop-drilling propre à l'approche non compound components.
- Hook personnalisé
Ils utilisent un hook personnalisé useTodosContext pour obtenir les valeurs du contexte. Ce hook rend le code plus lisible et plus facile à utiliser.
- Réutilisabilité accrue
Les composants sont désormais plus indépendants et peuvent être facilement réutilisés ailleurs dans l'application. Par exemple, Todos.List pourra être utilisé dans un autre écran ou dans une sidebar sans avoir besoin de passer d'informations supplémentaires via les props.
- Extensibilité
Avec cette approche, vous pouvez également étendre facilement le composant Todos en ajoutant des sous-composants supplémentaires sans bouleverser l'architecture existante. Par exemple, si vous voulez ajouter une fonctionnalité pour marquer les tâches comme faites, vous pourriez créer un nouveau sous-composant Todos.Checkbox.
Le mot de la fin 👋
De manière générale, le composant “traditionnel” est plus simple, mais il offre moins de flexibilité et de potentiel de réutilisation que le Compound Components. Le choix entre les deux approches dépend des besoins spécifiques du projet. Mais de mon experience, partir direct sur du Compound Components est rarement une mauvaise idée !
Les inconvénients potentiels de cette approche sont qu'elle est plus complexe et qu'elle nécessite une compréhension plus approfondie des concepts de React (pour le cas de React), tels que le Contexte et les Compound Components eux-mêmes. De plus, il est important de noter que bien que le Context puisse sembler être une solution à tous les problèmes, il doit être utilisé avec parcimonie pour éviter un couplage excessif entre les composants de votre application.
L'adoption du pattern Compound Components dans la conception d'interfaces utilisateur peut sembler déroutante au début, mais les avantages qu'elle offre en termes de modularité, de flexibilité et de réutilisabilité sont indéniables. Ainsi, en décomposant intelligemment les composants en des sous-éléments logiques, nous pouvons produire des systèmes d'UI flexibles, réutilisables et gérables.
Vous pouvez retrouvez cet article au format vidéo sur YouTube en suivant ce lien.

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é :
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.
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.
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).
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.
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.
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.

Hola, je vais vous présenter le début d'une nouvelle série d'articles dédiées à la construction d'un projet Web et Mobile en mettant à profit l'Architecture Hexagonale. Durant toute cette série, nous allons explorer comment la logique métier peut être partagée et gérée efficacement à travers différentes plateformes.
Nos objectifs
Nous allons avoir plusieurs objectifs à atteindre au fil de ce projet :
- Apprendre comment développer une application Web et Mobile à la fois en mettant à profit les technologies modernes (Nx, Expo, Remix, Vitest, etc.)
- Comprendre les principes de l'Architecture Hexagonale et comment l'appliquer pour optimiser le partage de la logique métier
- Gagner en compétence et en confiance pour lancer votre propre projet multi-plateforme, tout en développant une base de code propre et maintenable
La structure de la série
Comme je l'ai dis au début de ce premier article, ce projet donnera lieu à une série d'articles qui sera structurée de cette manière :
- Partie 1 (cet article) : présentation du projet et mise en place d'un monorepo avec Nx
- Partie 2 : développer sans UI avec l'Architecture Hexagonale
- Partie 3 : partager de la logique métier et des composants entre le Web et le Mobile
- Partie 4 : refactor serein avec les tests et l'Architecture Hexagonale
- Partie 5 : déploiement Web et Mobile avec Netlify et EAS
Le projet
Le projet qui va nous aider à mettre en avant l'Architecture Hexagonale est un outil de gestion de budget que l'on appellera broney (le bro qui t'aides à gérer ta money 😎). Cet outil sera composé de deux applications, une première, web, développée avec Remix et une deuxième, mobile, développée avec Expo. Nous aurons donc 2 applications React et React Native avec un package TypeScript qui contiendra la logique métier partagée entre ces 2 applications.
Stack
La Stack que j'ai choisi est très subjective, on y trouve quelques frameworks qui mérite selon moi plus de lumière (Remix notamment et Nx face à NextJS et Turborepo). Néanmoins il est important de comprendre que peu importe les frameworks et libraires utilisées, le coeur de l'application sera complètement agnostique et réutilisable dans n'importe quel contexte.
- Monorepo avec Nx
- Application mobile avec Expo
- Application web avec Remix
- Testing avec Vitest
- Style avec Tailwind pour le web et twrnc pour le mobile
- Animation avec Framer Motion pour le web et React Native Reanimated pour le mobile
- Déploiement de l'application web avec Netlify
- Base de données, authentification, etc. avec Supabase
- Formatage du code avec Prettier
- Validation du code avec ESLint
- CI/CD avec les GitHub Actions
- Gestion d'état avec Zustand
- Gestion des formulaires avec React Hook Form
- Validation des types avec Zod
- Logging avec Sentry
- Traductions avec FormatJS
- Utilitaire de date avec date-fns
Fonctionnalités
Pour mettre en avant l'Architecture Hexagonale nous allons avoir besoin de développer quelques fonctionnalités pour avoir de la logique métier. Nous allons nous focus sur les fonctionnalités suivantes :
- Mettre en place le storage : react native mmkv pour le mobile et localStorage pour le web
- Gérer les catégories : lister, ajouter, modifier et supprimer
- Gérer les portefeuilles : lister, ajouter, modifier et supprimer
- Gérer les transactions d'un compte : lister, ajouter, modifier et supprimer
- Authentification avec Supabase
- Dynamiser toute l'app avec Supabase
Modèle de données
Pour mettre en place les fonctionnalités nous allons avoir besoin des entités suivantes :
- Wallet, 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€)
- Category, des catégories servant à préciser le contexte des transactions faites (par exemple on a les catégories "Maison", "Restaurants" et "Divertissements")
- Transaction, les transactions sont liées à un portefeuille et à une catégorie pour savoir où l'argent est transférée (par exemple on a une transaction du portefeuille "Compte Principal Julien" de 50€ sur la catégorie "Restaurants")
Mise en place du monorepo avec NX
Initialisation du projet
Nous allons utiliser les commandes de Nx pour initialiser notre projet.
Avec cette commande nous avons le projet Nx configuré de base et sans libs pour le moment. Nous allons travailler avec le style Package-Based Repos qui nous offre plus de liberté en limitant le couplage avec Nx si jamais on souhaite changer facilement d'outil de monorepo. Cela permet également d'avoir des node_modules différents pour chaque app ou lib du projet. En savoir plus sur les différents style d'implémentation de Nx.
Création de la lib core
Nous allons maintenant ajouter notre première lib, la plus importante : core. En effet, c'est dans cette lib que nous allons mettre notre Architecture Hexagonale et la logique métier qui sera utilisée par nos applications Web et Mobile.
Cette commande nous a généré une lib avec le framework de test Vitest, une config eslint et prettier que l'on peut adapter à nos preferences que je ne détaillerai pas ici.
Il est possible de compiler notre lib avec la commande nx core build
et d'executer les tests avec nx core test
.
Mise en place de la CI
Maintenant que nous avons les tests setup ainsi que prettier et eslint, il est pertinent de mettre en place une CI pour avoir du feedback régulier sur la bonne tenue du code. Pour la CI nous allons simplement suivre la documentation de Nx et utiliser les GitHub Actions.
Nous allons donc simplement ajouter un fichier .github/workflows/ci.yml assez simple qui peut être étoffé.
Cette simple CI permet vérifier le bon formatage prettier, d'effectuer les validations eslint et de build et de s'assurer que les tests sont sans erreurs.
Structure du projet
Rentrons plus en détails dans ce que l'on vise comme structure de projet une fois les apps mise en place et notre lib core développée avec l'architecture hexagonale.
- apps
- mobile : notre application React Native développée avec Expo
- web : notre application React développée avec React
- libs
- ui : nos composants React et React Native utilisés par les apps web et mobile
- tailwind : notre configuration tailwind utilisée par les apps web et mobile ainsi que la lib ui
- core : notre architecture hexagonale qui contient le coeur de notre application et toute la logique métier réutilisable par les apps web et mobile
Pour aller plus loin, on peut très bien envisager d'avoir une app en plus pour un Storybook.
La lib qui va nous intéresser et la lib core évidemment. Elle sera structurée de cette manière :
- libs
- core
- src
- wallet
- tests
- wallet.service.test.ts : la logique métier testées
- wallet.test.ts : les règles métiers testées
- domain
- wallet.ts : l'entité qui représente les portefeuilles et qui contient des règles métiers
- wallet.repository.ts: le contrat qui détermine comment manipuler l'entité pour lister, ajouter, etc.
- wallet.service.ts : le service qui consume une implémentation de contrat
- infrastructure
- in-memory-wallet.repository.ts : une implémentation du contrat
- local-storage-wallet.repository.ts : idem
- supabase-wallet.repository.ts : idem
- user-interface
- wallet.store.ts : un store zustand vanilla, utilisable dans n'importe quel environnement javascript et qui sera utilisé dans nos apps
- category
- ...
- ...
Nous verrons le contenu de chaque fichiers ainsi que les détails du fonctionnement de ces derniers dans le prochain article !
Conclusion
Nous avons terminé le premier 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 première partie nous avons vu comment mettre un place un monorepo et nous avons pourquoi et comment ce monorepo va nous aider à partager la logique métier entre nos différentes applications. Nous avons également bien délimité le périmètre et les fonctionnalités attendues pour notre première version, le MVP, de broney.
Enfin, à la fin de cet article nous avons commencé à entrevoir la structure du projet en mettant en évidence l'Architecture Hexagonale, ce sera le thème de la deuxième partie : Développer sans UI avec l'Architecture Hexagonale.

Dans le domaine de la gestion des données, le choix entre Hard Delete et Soft Delete peut avoir un impact significatif sur la sécurité et la récupération des informations. Ces deux méthodes de suppression de données sont essentielles pour les développeurs et les administrateurs de bases de données.
Dans cet article, nous explorerons en détail ce qu'est le Hard Delete et le Soft Delete, leurs avantages respectifs, et comment choisir la meilleure approche en fonction des besoins spécifiques de votre projet. Nous fournirons également des exemples de code source pour illustrer leur mise en œuvre, afin que même les novices puissent comprendre ces concepts fondamentaux.
Comprendre la différence entre Hard Delete et Soft Delete
La gestion des données supprimées est une composante cruciale de toute application ou système de gestion de bases de données. Comprendre les distinctions entre le Hard Delete et le Soft Delete est le point de départ pour prendre des décisions éclairées.
Hard Delete : La Suppression Définitive (h3)
- Le Hard Delete, également connu sous le nom de suppression définitive, signifie que les données supprimées sont éliminées de manière permanente de la base de données.
- Cela signifie qu'une fois que vous avez effectué un Hard Delete, les données sont irrécupérables.
- Exemples de scénarios où le Hard Delete est approprié : suppression de données sensibles ou obsolètes, respect de la conformité légale.
Soft Delete : La suppression réversible
- Le Soft Delete, contrairement au Hard Delete, implique une suppression réversible.
- Les données supprimées sont marquées comme "supprimées" mais restent dans la base de données.
- Cela permet la récupération des données supprimées si nécessaire, offrant une couche de sécurité supplémentaire.
- Utilisation courante du Soft Delete : préservation de l'historique des données, récupération en cas d'erreur de suppression.
En comprenant la différence fondamentale entre le Hard Delete et le Soft Delete, vous pouvez commencer à évaluer quelle méthode convient le mieux à votre projet. La prochaine section examinera les avantages de chacune de ces méthodes pour vous aider à prendre une décision éclairée.
Les avantages du Hard Delete
Le Hard Delete est une méthode de suppression de données qui peut s'avérer essentielle dans certaines situations. Examinons de plus près les avantages qu'il offre :
L'un des principaux avantages du Hard Delete réside dans la sécurité qu'il offre. Lorsque vous effectuez un Hard Delete, les données sont supprimées de manière permanente de la base de données.
Cela garantit qu'aucune trace des données supprimées ne subsiste, réduisant ainsi le risque de divulgation d'informations sensibles.
Dans certains secteurs, comme la santé ou les finances, la conformité légale est cruciale. Le Hard Delete permet de répondre à ces exigences en supprimant irrévocablement les données.
En supprimant définitivement les données, le Hard Delete peut contribuer à améliorer les performances de la base de données en libérant de l'espace et en réduisant la charge de travail du système.
Le Hard Delete simplifie la gestion des données, car il n'est pas nécessaire de gérer un ensemble de données supprimées de manière réversible. Cela peut simplifier les processus de sauvegarde et de restauration.
Pour mieux comprendre la mise en œuvre du Hard Delete, voici un exemple de code SQL montrant comment effectuer une suppression permanente dans une base de données :

Les avantages du Soft Delete
Le Soft Delete, bien que différent du Hard Delete, présente des avantages significatifs dans certaines situations. Examinons en détail les avantages qu'il offre !
L'un des principaux avantages du Soft Delete est la capacité à récupérer des données supprimées par erreur. Les données marquées comme "supprimées" restent dans la base de données et peuvent être restaurées si nécessaire.
Le Soft Delete permet de conserver un historique complet des données, y compris celles qui ont été supprimées. Cela peut être utile pour l'audit, la conformité ou l'analyse des tendances historiques.
En évitant la suppression permanente des données, le Soft Delete offre une couche de protection contre les erreurs humaines, telles que la suppression accidentelle de données critiques.
Lors de la mise en œuvre de nouvelles fonctionnalités ou de modifications de la structure de la base de données, le Soft Delete permet une transition en douceur en conservant les données existantes.
Pour mieux comprendre la mise en œuvre du Soft Delete, voici un exemple de code SQL montrant comment marquer une ligne de données comme "supprimée" sans la supprimer définitivement :

Quand utiliser chacune des méthodes
La décision entre Hard Delete et Soft Delete dépend largement des exigences particulières de votre projet. Voici des conseils pour vous aider à faire le choix approprié :
Choisissez le Hard Delete lorsque la sécurité des données est une priorité absolue. Par exemple, dans les applications de santé ou financières, il est préférable d'opter pour une suppression définitive.
Si la récupération des données supprimées est essentielle, le Soft Delete est la meilleure option. Cela s'applique notamment aux systèmes où les erreurs de suppression peuvent se produire.
Pour respecter les réglementations strictes qui exigent la suppression permanente de données, le choix du Hard Delete est nécessaire.
Si vous avez besoin de conserver un historique complet des données, optez pour le Soft Delete. Cela est particulièrement utile pour l'audit et la conformité.
Si vous souhaitez optimiser la performance de la base de données en réduisant la charge, le Hard Delete peut être plus approprié, car il libère de l'espace.
Envisagez le Soft Delete lorsque vous prévoyez d'introduire de nouvelles fonctionnalités ou des changements structurels dans la base de données, car il permet une transition en douceur.
En évaluant soigneusement les besoins de votre projet en fonction de ces critères, vous pourrez prendre une décision éclairée quant à l'utilisation du Hard Delete ou du Soft Delete. Gardez à l'esprit que dans certains cas, une combinaison des deux méthodes peut également être envisagée pour répondre aux besoins spécifiques de votre application.
Le choix entre Hard Delete et Soft Delete est une décision cruciale dans la gestion des données. Chacune de ces méthodes présente des avantages distincts, et le choix dépend des besoins spécifiques de votre projet.
Le Hard Delete offre une sécurité maximale en supprimant définitivement les données, ce qui le rend idéal pour les applications où la confidentialité et la conformité légale sont essentielles. Cependant, il faut être prudent, car les données sont irrécupérables.
Le Soft Delete, quant à lui, permet la récupération des données supprimées, préservant ainsi un historique complet et offrant une protection contre les erreurs humaines. Il est particulièrement adapté aux systèmes où la récupération des données est une priorité.
Le choix entre ces deux méthodes peut également dépendre des contraintes de performance de votre base de données et de la flexibilité nécessaire pour les futures modifications.
En fin de compte, il n'y a pas de réponse universelle. Il est essentiel d'évaluer les besoins de votre projet et de choisir la méthode qui répond le mieux à ces exigences spécifiques. Dans certains cas, une combinaison des deux méthodes peut également être envisagée pour une gestion des données supprimées plus complète.
Quelle que soit la méthode choisie, la gestion des données supprimées est une composante essentielle de tout système de base de données bien conçu. En comprenant les avantages du Hard Delete et du Soft Delete, vous êtes mieux préparé à prendre des décisions éclairées pour garantir la sécurité et la flexibilité de votre application.
N'hésitez pas à partager vos propres expériences et réflexions sur ce sujet dans les commentaires ci-dessous. La gestion des données supprimées est une discipline en constante évolution, et l'échange d'idées peut bénéficier à l'ensemble de la communauté de développement.

Dans l'univers du développement d'applications mobiles, la gestion des versions de Node.js est cruciale. Découvrez ici comment utiliser Node Version Manager (NVM) pour changer, installer des versions LTS, et éviter les conflits. Que vous soyez débutant ou expert, ce guide vous aidera à maîtriser cet outil essentiel.
Comprendre l'importance de Node Version Manager (NVM)
L'utilisation de différentes versions de Node.js peut être délicate. NVM simplifie ce processus en vous permettant de basculer facilement entre les versions. Vous évitez ainsi les conflits et assurez la compatibilité de vos projets.
NVM offre une flexibilité totale pour installer et gérer des versions spécifiques de Node.js en fonction de vos besoins. Son utilisation est simple, même pour les débutants, avec des commandes intuitives. NVM vous protège contre les conflits de versions en isolant les environnements.
NVM garantit que vos projets restent compatibles avec la version de Node.js sur laquelle ils ont été développés. Vous pouvez également mettre à jour vos projets en douceur sans crainte de problèmes de compatibilité.
En automatisant la gestion des versions de Node.js, NVM vous permet de vous concentrer sur le développement plutôt que sur la résolution de problèmes de version. C'est un gain de temps précieux.
En comprenant ces points, vous serez mieux préparé à tirer parti de Node Version Manager (NVM) dans votre travail de développement Node.js.
Installation de Node Version Manager
L'installation de Node Version Manager (NVM) est la première étape essentielle pour gérer vos versions Node.js. Cette section vous guidera à travers le processus d'installation sur différentes plateformes :
- Linux : Utilisez la commande wget pour récupérer NVM depuis GitHub. Suivez notre guide étape par étape pour une installation sans faille.
- macOS : Apprenez comment installer NVM sur macOS en utilisant la commande curl. Suivez nos instructions pour garantir une installation réussie.
- Windows : Si vous êtes sur Windows, découvrez comment installer NVM en utilisant des outils tels que Git Bash ou Windows Subsystem for Linux (WSL).
Après l'installation, nous vous montrerons comment configurer NVM pour une utilisation optimale. Vous serez prêt à commencer à gérer vos versions Node.js avec aisance.
Familiarisez-vous avec les commandes de base de NVM, telles que nvm --version pour vérifier la version installée, nvm ls pour afficher les versions disponibles et nvm install pour installer une version spécifique.
Suivez les instructions détaillées dans cette section pour installer NVM sur votre plateforme de choix. Vous serez rapidement opérationnel pour gérer vos versions Node.js de manière fluide.
Utilisation de NVM pour installer la dernière version LTS de Node.js
Maintenant que vous avez installé Node Version Manager (NVM), apprenons comment utiliser cet outil pour installer la dernière version LTS (Long Term Support) de Node.js.
Avant de procéder à l'installation, il est essentiel de savoir quelles versions LTS de Node.js sont disponibles. Vous pouvez le faire en utilisant la commande nvm ls-remote --lts.
Suivez ces étapes simples pour installer la dernière version LTS :
- Exécutez nvm install --lts pour installer la dernière version LTS disponible.
- Pour vérifier que l'installation a réussi, utilisez node --version pour afficher la version de Node.js installée.
Si vous souhaitez que la dernière version LTS soit la version par défaut utilisée par NVM, exécutez nvm alias default <version>.
Grâce à ces étapes simples, vous pouvez désormais installer et utiliser la dernière version LTS de Node.js avec facilité en utilisant Node Version Manager (NVM). Cela vous permettra de bénéficier des avantages de stabilité et de support à long terme pour vos projets Node.js.
Gestion de multiples versions de Node.js avec NVM
La gestion de plusieurs versions de Node.js est une nécessité pour de nombreux développeurs. Voici comment utiliser Node Version Manager (NVM) pour gérer efficacement ces versions.
Pour voir toutes les versions de Node.js installées sur votre système, utilisez simplement la commande nvm ls. Vous obtiendrez une liste claire de toutes les versions disponibles.
Pour basculer entre les versions, utilisez la commande nvm use <version>. Cela changera votre environnement de développement pour utiliser la version spécifiée.
Vous pouvez également créer des alias pour des versions spécifiques avec nvm alias <alias> <version>. Cela simplifie encore la gestion des versions.
Avec ces commandes simples, vous pouvez gérer facilement plusieurs versions de Node.js sur votre système, en utilisant Node Version Manager (NVM). Cela vous permet de maintenir la compatibilité de vos projets et de travailler sur des versions spécifiques selon vos besoins.
Mettre à jour Node.js avec NVM
Maintenir votre installation Node.js à jour est crucial pour bénéficier des dernières fonctionnalités et correctifs de sécurité. Voici comment effectuer des mises à jour en utilisant Node Version Manager (NVM).
Pour vérifier si des mises à jour sont disponibles, exécutez nvm ls-remote <version>. Cela affichera les versions de Node.js disponibles à la mise à jour.
Pour mettre à jour Node.js vers la dernière version LTS disponible, utilisez nvm install --lts. Cela installera la dernière version LTS sans affecter vos versions précédentes.
Si vous avez une version spécifique que vous souhaitez mettre à jour, utilisez nvm install <version> pour obtenir la dernière version de cette branche.
En utilisant ces commandes simples, vous pouvez maintenir votre installation Node.js à jour avec facilité, en garantissant que vos projets sont toujours optimisés en termes de performances et de sécurité.
Exemples pratiques et code source
Dans cette section, nous explorerons quelques exemples pratiques d'utilisation de Node Version Manager (NVM) avec des extraits de code source pour une meilleure compréhension.
Exemple 1 : Installation de Node.js LTS

Cette commande installe la dernière version LTS de Node.js.
Exemple 2 : Basculer vers une version spécifique

Utilisez cette commande pour basculer vers une version spécifique de Node.js (dans cet exemple, la version 14.17.6).
Exemple 3 : Créer un alias pour une version

Créez un alias pour définir une version spécifique de Node.js comme version par défaut.
Exemple 4 : Vérifier les versions installées

Cette commande affiche la liste des versions de Node.js installées sur votre système.
Exemple 5 : Mise à jour de Node.js

Mettez à jour Node.js vers la dernière version (ici, la version actuelle) tout en conservant les packages de la version précédente.
Utilisez ces exemples pratiques et extraits de code source pour mieux comprendre comment utiliser NVM dans vos projets Node.js. Cela vous aidera à gérer efficacement les versions et à optimiser votre environnement de développement web.
Les meilleures pratiques de gestion des versions Node.js
Pour tirer le meilleur parti de Node Version Manager (NVM) et maintenir un environnement de développement Node.js efficace, suivez ces meilleures pratiques :
- Gardez NVM à jour : Pensez à mettre à jour régulièrement NVM pour bénéficier des dernières améliorations et corrections de bogues.
- Utilisez les versions LTS : Privilégiez les versions LTS (Long Term Support) pour une stabilité à long terme. Cela garantit que vos projets restent stables et sécurisés.
- Créez des alias significatifs : Lors de la création d'alias pour des versions spécifiques, choisissez des noms significatifs pour vous faciliter la gestion.
- Documentez vos projets : Tenez un journal des versions utilisées pour chaque projet afin de garantir une compatibilité continue.
- Gérez les dépendances avec npm : N'utilisez pas NVM pour gérer les dépendances de vos projets. Utilisez npm pour gérer les packages Node.js spécifiques à chaque projet.
- Restez informé : Suivez les annonces de nouvelles versions Node.js et les mises à jour de sécurité pour rester au courant des dernières avancées.
En suivant ces meilleures pratiques, vous optimiserez votre gestion des versions Node.js avec NVM et garantirez la stabilité, la sécurité et la facilité de gestion de vos projets.
Dans cet article, nous avons exploré en détail l'utilisation de Node Version Manager (NVM) pour la gestion des versions Node.js. Que vous soyez un développeur expérimenté ou que vous découvriez Node.js, NVM est un outil essentiel pour maintenir un environnement de développement propre et efficace.
Nous avons abordé les étapes clés, de l'installation de NVM sur différentes plateformes à la gestion de multiples versions de Node.js, en passant par les mises à jour et les meilleures pratiques. En utilisant NVM, vous pouvez facilement basculer entre les versions, maintenir la compatibilité de vos projets et garantir la sécurité de votre environnement de développement.
Les exemples pratiques et les extraits de code source ont été fournis pour vous aider à mieux comprendre comment utiliser NVM dans vos projets. En suivant les meilleures pratiques recommandées, vous pouvez maintenir un environnement de développement Node.js optimal.
En fin de compte, Node Version Manager (NVM) est un outil puissant qui facilite grandement la gestion des versions Node.js. Il vous permet de rester à jour avec les dernières versions, d'adapter vos projets aux besoins spécifiques et de maintenir un flux de travail de développement efficace. Intégrez NVM dans votre boîte à outils de développement Node.js dès aujourd'hui pour une expérience de développement plus fluide et plus productive.
Maintenant que vous savez correctement utiliser NVM, nous vous invitons à consulter notre guide complet sur l’outil de gestion de versions Git.

À 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.

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.
Introduction
Aujourd'hui, comment parler de développement logiciel sans parler de Git ? Un bon système de gestion des versions est essentiel pour assurer un flux de travail efficace. Git est l'outil de gestion de versions par excellence et est le plus populaire. Néanmoins, avec Git, il s'est développé différentes stratégies pour structurer et gérer le flux de modifications de la codebase. Parmi toutes ces stratégies, aujourd'hui, deux vont nous intéresser : le Trunk-Based Development (TBD) et Git Flow.
D'un côté on a le TBD, une approche minimaliste qui préconise de travailler directement sur un tronc commun, autrement dit la branche principale. Tandis que Git Flow, lui, propose une structure plus complexe, avec des branches dédiées à des fonctionnalités, des corrections, des versions, etc.
Les deux approches ont des avantages et des inconvénients, leurs propres complexités et simplicités et c'est ce que nous allons voir maintenant.
L'objectif de cet article n'est pas simplement de fournir une explication de ces deux stratégies de gestion des versions, mais plutôt de démontrer pourquoi, dans de nombreux contextes, le TBD peut s'avérer une approche plus optimale que Git Flow.

Git Flow vs Trunk-Based Development
La stratégie Git Flow
Git Flow est une stratégie de gestion de versions populaire qui a été conçue pour aider les équipes à gérer les développements complexes, en tirant parti de la puissance et de la flexibilité des branches Git. Elle propose une structure organisée qui facilite le développement parallèle de différentes fonctionnalités et la gestion des versions.
Organisation
Avec Git Flow on organise nos branches de la manière suivante :
- main, la branche principale qui représente l'état actuel de la production
- develop, la branche où se trouve toutes les fonctionnalités, corrections et autres de la prochaine version prévue
- feature/xxx, les branches créées à partir de develop où se trouve le code d'une fonctionnalité qui sera fusionné avec develop une fois le développement terminé
- release/xxx, les branches créées à partir de develop où se trouve le code d'une nouvelle version du logiciel, potentiellement affiné avant le déploiement
- hotfix/xxx, les branches créées à partir de main pour des corrections critiques découvertes en production. Ces branches sont fusionnées dans main dès que le correctif est prêt et sont également fusionnées avec develop pour s'assurer que la correction perdurera dans la codebase

Les problèmes de Git Flow
La force de Git Flow réside dans sa structure qui permet de gérer facilement des tâches parallèles et suivre d'évolution du code à travers le temps.
Cette stratégie entraîne néanmoins un lot d'inconvénients :
- Complexité - Cette stratégie nécessite beaucoup de manipulation manuelle des branches qui demande une maîtrise totale de Git et de ce processus
- Intégration continue compliquée - L'intégration continue est plus complexe à mettre en place en raison du développement parallèle sur plusieurs branches
- Déploiement fréquent coûteux - Le déploiement continus/fréquents n'est pas impossible mais demande beaucoup plus de temps et d'énergie
- Problèmes de fusion - Le nombre parallèle de branches important entraîne de nombreux problèmes potentiels de merge
- Revues de code difficiles - La taille des pull requests a tendance à être plus importante avec Git Flow parce qu'elles contiennent des fonctionnalités complètes. La branche de feature a tendance à vivre trop longtemps, nécessitant des fusions fréquentes avec develop ce qui entraîne des retards dans le processus de livraison

La stratégie Trunk-Based Development
La stratégie Trunk-Based Development est une approche bien plus minimaliste dont le but est de simplifier le flux de travail en minimisant la fragmentation du code et en facilitant l'intégration continue. Pour cela on ne va travailler que sur une seule branche principale (main ou trunk) autrement appelé : le tronc commun.
Une seule source de vérité
Avec le TBD, cela signifie donc que toutes les modifications du code sont introduites et fusionnées directement dans la branche principale. Chaque développeur doit donc fusionner régulièrement ses modifications, plusieurs fois par jour. En conséquence, les versions sont gérées directement à partir de la branche principale, chaque développeur est constamment à jour et les problèmes de fusions sont considérablement réduits. Le cycle de développement est plus rapide et alimente l'intégration et le déploiements continus.
Quid des branches ?
Travailler avec l'approche TBD ne signifie pas qu'on a plus du tout de branche en plus de la branche principale. En effet, les branches peuvent encore être utilisées mais elles se doivent d'être de très courte durée et fusionnées dès que le travail est terminé.

Quid des revues de code ?
Quel que soit la stratégie adoptée, le processus de revue de code persiste et demeure une composante essentielle pour assurer la qualité du code qui est fusionné dans le tronc commun. La subtilité entre les deux stratégie est que avec le TBD, les modifications étant fréquemment fusionnées, elles sont généralement plus petites. Et si les modifications s'avèrent importante alors le TBD souhaite mettre en avant la collaboration et demanderait de faire ces modifications en pair ou en mob programming. Enfin, les revues de code se doivent d'être traitées rapidement (dans la demi-journée) et doivent durer que quelques minutes (15 maximum à peu près).
Quid des modifications importantes ?
Le TBD n'empêche pas le développement de fonctionnalités importantes qui demandent donc de lourdes modifications du code. En revanche, cette stratégie va favoriser la collaboration via du pair ou du mob programming mais ce n'est pas la seule solution. Il existe également les Feature Flags.
Un Feature Flag est une technique de développement logiciel permettant de masquer, activer ou désactiver une fonctionnalité dans un environnement de production sans avoir à redéployer le code. Cette technique offre un contrôle en temps réel des fonctionnalités, représente une sécurité contre les problèmes potentiels de nouvelles fonctionnalités et, surtout, permet de travailler sur de nouvelles fonctionnalités directement dans la branche principale sans interrompre le fonctionnement normal de l'application.
Dans le cadre de l'approche TBD, où toutes les modifications sont effectuées directement sur la branche principale, l'utilisation de Feature Flags de fusionner le code pour de nouvelles fonctionnalités qui ne sont pas encore terminées ou testées. La fonctionnalité peut être développée et fusionnée dans le tronc sans être exposée aux utilisateurs jusqu'à ce qu'elle soit prête, où le Feature Flag à ce moment-là, peut être activé.
Le recours à des Feature Flags apporte une flexibilité considérable au processus de développement et constitue une composante essentielle pour atteindre un déploiement continu et un flux de travail efficace dans le TBD.
Mais à quoi ça ressemble concrètement ?
Ce sont ni-plus ni-moins des booléens :
.png)
Et à l'usage, par exemple pour du React mais le principe est le même pour n'importe quel environnement :
.png)
Il est tout à fait possible de mettre en place un système de Feature Flags contrôlable à distance via un backoffice ou des outils tout prêt à l'usage qui existe sur le marché comme Firebase Remote Config, PostHog ou Harness par exemple.
Pré-requis
Pour une implémentation efficace du TBD, plusieurs éléments sont généralement requis :
- Intégration Continue (CI) : c'est une stratégie qui bénéficie grandement de l'utilisation de la CI étant donné quelle est souvent sollicité pour de petites modifications. La CI permet d'assurer que le tronc commun est toujours en état de fonctionner correctement et qu'elle continue à être deployable à tout moment.
- Tests automatisés : les tests automatisés vont de pair avec la CI, ils assurent, si ils sont correctement mis en place, de la qualité du code.
- Revues de code : comme mentionné précédemment, les revues de code sont une composante essentielle pour maintenir la qualité et le partage de connaissance.
- Feature flag : comme expliqué précédemment, il est important de savoir mettre en place les features flag parce qu'ils sont souvent utilisés.
- Culture de la collaboration : enfin, l'environnement de travail est très important, toute l'équipe doit être impliqué, connaître et appliquer ce processus. L'équipe doit également se responsabiliser et doit être prête à collaborer étroitement et à partager ses connaissances.
Résumons les bénéfices
Maintenant que nous avons expliqué le TBD comment il fonctionne et dans quel contexte, nous pouvons en ressortir les bénéfices suivants :
- Intégration continue (CI) : grâce à l'intégration fréquente de petits changements, les problèmes sont détectés et résolus plus rapidement. De plus, cela limite les éventuels conflits de fusion.
- Déploiements plus rapides : avec une seule branche principale toujours prête à être déployée, le TBD peut faciliter des déploiements plus rapides et plus réguliers.
- Simplification du processus : la stratégie TBD supprime la nécessité de gérer de nombreuses branches à long terme, simplifiant le flux de travail de l'équipe.
- Qualité du code : les revues de code régulières contribuent à maintenir la qualité du code et à anticiper les problèmes.
- Flexibilité grâce aux Feature Flags : l'utilisation de Feature Flags permet de tester de nouvelles fonctionnalités en production sans les exposer aux utilisateurs finaux, contribuant à un lancement plus sûr et contrôlé des nouveautés.
Un dernier bénéfice que nous allons voir en détail dans le dernier point de cet article, c'est la facilité avec laquelle le TBD favorise l'atteinte de performances élevées selon les métriques DORA, un ensemble de mesures reconnues pour évaluer l'efficacité des équipes.

Et les inconvénients dans tout ça ?
La mise en œuvre de la stratégie TBD présente également certains défis ou inconvénients :
- Gestion rigoureuses des fusions : les modifications doivent être fusionnées en continu dans le tronc commun, ce qui nécessite que les développeurs synchronisent fréquemment leur travail avec la branche principale pour éviter les conflits de fusion.
- Culture : pour certaines équipes, l'adoption de cette stratégie peut nécessiter un changement significatif dans leurs pratiques de travail, notamment l'intégration continue et les revues de code constantes.
- Déploiements risqués sans tests adéquats : sans une couverture de test adéquate, le risque d'introduction de bugs en production peut être plus élevé, car tout le code est fusionné directement dans la branche principale qui est déployée.
- Complexité des Feature Flags : bien que les Feature Flags offrent plus de flexibilité, leur gestion peut ajouter une certaine complexité. Une mauvaise utilisation des feature flags peut entraîner de la dette technique.
En dépit de ces défis/inconvénients, il est globalement reconnu que les avantages valent les efforts nécessaires pour mettre en œuvre le TBD. Comme pour beaucoup de choses de la vie, il est important de déterminer si cette stratégie est adaptée au contexte spécifique de votre équipe et de votre projet.
DORA Metrics et Trunk-Based Development
Les DORA Metrics (ou DevOps Research and Assessment metrics), sont une série de mesures de performance pour les équipes de développement logiciel.
Ces mesures incluent :
- Le temps de cycle de déploiement (Mean Lead Time for Changes - MLTC) : Le temps moyen nécessaire pour qu'un commit passe à la production.
- La fréquence de déploiement (Deployment Frequency - DF) : À quelle fréquence une organisation déploie du code en production.
- Le temps de rétablissement (Mean Time to Restore - MTTR) : Le temps nécessaire pour récupérer d'une panne ou d'un incident de production.
- Le taux d'échec des modifications (Change Failure Rate - CFR) : La proportion de déploiements causant un incident de production ou un échec de service.
Le TBD est lié aux DORA Metrics car c'est une méthode de développement qui peut potentiellement améliorer ces mesures. Il encourage des cycles d'intégration et de déploiement plus courts, ce qui peut accélérer le délai de déploiement et augmenter la fréquence de déploiement.
- MLTC et DF : La fusion fréquente de petites modifications permet de réduire le temps de cycle de déploiement et d'augmenter la fréquence de déploiement, car la branche principale est toujours dans un état deployable.
- CFR : Avec des revues de code régulières et des tests automatisés, on peut s'attendre à ce que le pourcentage de modifications ratées diminue, car les problèmes sont souvent découverts et corrigés avant le déploiement.
- MTTR : Comme les problèmes sont généralement plus petits et plus localisés avec cette approche, il est généralement possible de corriger et de restaurer le service plus rapidement.
En résumé, l’approche Trunk-Based Development est bien alignée avec l’amélioration des métriques DORA, ce qui en fait une stratégie de choix pour les équipes axées sur le DevOps.
Ainsi, le développement basé sur la stratégie TBD peut contribuer à l'amélioration des DORA metrics.

Le mot de la fin
Cet article a examiné en profondeur la stratégie de Trunk-Based Development (TBD) en la comparant à Git Flow et en mettant en avant ses nombreux avantages. Nous avons analysé comment le TBD favorise des cycles de développement plus rapides, une meilleure qualité de code grâce aux revues de code constantes, et une plus grande flexibilité par l'utilisation de feature flags. Nous avons également expliqué comment le TBD facilite l'atteinte de performances élevées selon les DORA Metrics.
Cependant, nous avons également souligné que le TBD n'est pas sans défis. Il nécessite une gestion rigoureuse des fusions, un changement culturel significatif dans certaines équipes, une bonne couverture de tests pour minimiser les risques associés au déploiement constant.
Pour conclure, le TBD est un modèle puissant qui peut accélérer la livraison de valeur, améliorer la qualité du code et favoriser l'optimisation continue des performances de l'équipe. Cependant, comme pour toute stratégie, son adoption doit être précédée d’une évaluation approfondie des besoins, contextes et capacités spécifiques de l’équipe.
Les dédicaces

Origine
Git a été inventé et développé par Linus Torvalds en 2005. Il s’agit un logiciel libre et gratuit permettant aux développeurs de gérer les changements apportés au code au fil du temps. Linus Torvalds c’est aussi le petit génie qui est à l’origine du noyau Linux qu’il a commencé en 1991, donc bien avant Git.
Linux c’est un projet plutôt conséquent et il a donc dû nécessiter l’usage d’un outil de gestion de version. Cet outil, à l’époque, c’est BitKeeper. Le problème de BitKeeper, c’est qu’il s’agit d’un logiciel propriétaire et que toute la communauté qui gravite autour de Linux, elle n’aime pas vraiment les logiciels propriétaires. Alors que BitKeeper n’est déjà pas totalement apprécié par la communauté Linux, ils vont faire une annonce qui va déclencher la colère de toute cette communauté et surtout de Linus Torvalds. Ils vont cesser, du jour au lendemain, d’être gratuit. C’est à ce moment précis que Linus Torvalds décide de développer lui même son propre système de gestion de version du code source et tout comme Linux, ce système sera libre et gratuit.
Système de contrôle de version (VCS)
Git est donc un système de contrôle de version, il permet tout simplement de suivre l’évolution du code au fil du temps, à l’aide de branche, de fichiers et d’opérations sur ces fichiers.
Git est structuré comme suit :
- on y retrouve des fichiers (le code source)
- des branches (correspondant à une arborescence de fichiers)
- et des opérations pour faire évoluer les fichiers dans les branches
Grâce à ces opérations, git permet de savoir qui a touché à quel fichier, à quel moment et comment.
GitHub, GitLab, Bitbucket, etc.
Git est un logiciel qui permet de sauvegarder et de gérer localement l’évolution du code source au fil du temps. GitHub, GitLab, Bitbucket, etc. sont des plateformes (web) qui se servent du logiciel git pour gérer le code source. Les dépôts ne sont alors plus gérer localement mais sur des serveurs distants et permettent donc notamment la collaboration avec plusieurs personnes. Ces plateformes proposent également de nombreuses fonctionnalités de gestion de projets et d’équipes (wiki, affectations de tâches, suivi des problèmes, roadmap, statistiques, etc.).
Les bases
Git Flow
Git Flow est une organisation de travail basé sur la capacité de Git à gérer des branches. Par défaut il existe une branche principale qui s’appelle main (anecdote : anciennement master, ce nom par défaut a changé pour des raisons culturelles, ne plus assimiler la notion de master/slave à l’industrie du développement face aux nombreux cas de racisme dans le monde). Il existe une deuxième branche que nous allons créer et qui sera également considérée comme principale, il s’agit de la branche develop.
Nous avons donc 2 branches principales :
- main (anciennement master), qui représente le code source utilisé sur la production
- develop, qui contient les dernières fonctionnalités dont la phase de développement est terminée

Tout au long du développement du projet, de nombreuses branches seront créées lors du développement des fonctionnalités et des corrections diverses. Ces branches respecteront des conventions de nommages comme suit :
- feature/*, pour les branches de fonctionnalités
- hotfix/* ou bugfix/*, pour les branches de corrections
- refactor/*, pour améliorer la qualité du code

Conventional Commits
Conventional Commits est une spécification dont le but est d’améliorer la lisibilité des commits et l’historique des modifications du code source. À l’aide de ces conventions on peut identifier immédiatement le type, le contexte et l’objectif des modifications apportées au code sur un commit (nota bene : Cela permet aussi d’être compris par des outils automatisé pour générer de la documentation en autres).

Les types de commits les plus utilisés sont :
- feat, développement d’une feature
- fix, correction d’un bug
- refactor, amélioration du code
- test, ajout ou mise à jour de tests
- chore, tâche technique non assimilée à une feature
- remove, revert, style, ci, docs, etc.

Workflow : merge vs rebase
Avec Git Flow on travaille donc sur des branches partant de develop (ou autre) et une fois le travail terminé on met à jour develop pour qu’il ai connaissance des modifications apportées.
Il existe plusieurs façons de ramener les modifications d’une branche vers une autre. On peut utiliser la politique de merge ou bien la politique de rebase. Ces deux méthodes ont des avantages et des inconvénients.
Politique de merge
Lorsque le travail de développement est terminé sur une branche (de feature, de refactor, etc.), la branche contient un certain nombre d’opération qui n’existent pas sur la branche d’origine. Le principe de la politique de merge est simple : récupérer les modifications faites sur une branche et les ramener sur une autre branche qui n’a pas connaissance de ces modifications. Ces modifications sont ramenées telles quelles.

Avantages :
- traçabilité totale, l’historique du code source correspond totalement à ce qui a été fait
- résolution des conflits en une seule fois (peut être un inconvénient dans certains cas)
Inconvénients :
- historique du code source vite pollué par des opérations inutiles “wip” ou des opérations qui s’annulent
- historique peu fiable et difficile à debugger
- résolution des conflits en une seule fois (peut être un avantage dans certains cas)
Politique de rebase
Lorsque le travail de développement est terminé sur une branche (de feature, de refactor, etc.), la branche a donc un certain nombre d’opération qui diverge de la branche principale. Lorsqu’on suit une politique de rebase, notre objectif va être de nettoyer ces opérations en les réécrivant jusqu’à avoir le nombre minimum d’opérations pertinentes.

Avantages :
- historique du code source linéaire et lisible qui peut servir de documentation
- messages de commit clairs et respectant les conventions, plus de “wip”
- plus de commits qui s’annulent et donc une fiabilité de l’historique
- facilité pour revenir en arrière et trouver l’origin d’un bug car l’historique n’est pas pollué
- facilité pour revoir une feature complète, pour la modifier ou l’annuler
- résolution des conflits opération par opération (peut être un inconvénient dans certains cas)
Inconvénients :
- demande une grande rigueur car on réécrit en permanence l’historique
- demande une bonne communication ou des règles précises si on travaille en équipe sur la même branche
- la réduction d’une nombre d’opération au minimum est parfois trop extrême et atténue la clarté du contexte dans certains cas
- résolution des conflits opération par opération (peut être un avantage dans certains cas)
Nettoyage avec rebase Interactif
Avec la politique de rebase on réécrit l’historique des opérations faites sur le code source. Pour cela on peut utiliser des outils comme GitKraken ou autre, mais on peut également utiliser la commande git rebase interactive.
Les rebases réécrivent l’historique et donc écrasent totalement ce qui existait avant. En équipe il est donc indispensable de bien communiquer, de bien se mettre à jour et de prendre le soin de ne pas travailler sur la même branche. Si ces règles ne sont pas respecter, les pertes de code sont plus que probables !
Le processus classique de développement pour ne pas rencontrer de problèmes et profiter de la puissance du rebase est le suivant (en plus :
- travailler en local en faisant autant d’opérations que nécessaires
- lorsque le travail est terminé et que tout fonctionne comme il faut, créer une pull request et demander une revue de code en gardant l’historique de code tel qu’il est pour garder du contexte et donner à l’auteur de la revue de code un moyen de comprendre le cheminement de pensé qui a amené à ces modifications
- une fois la revue de code terminée et acceptée, il faut utiliser le rebase interactive pour nettoyer le code et ne garder que les opérations nécessaires
- intégrer les modifications sur la branche d’origine et supprimer la branche créée précédemment
🧑💻 Démonstration
Supposons nous avons un dépôt git avec une seule branche main et un seul fichier hello.ts qui contient une fonction “Hello World !” comme suit :

Maintenant, nous devons développer la fonctionnalité “Good Bye World!”.
Pour cela, nous allons donc commencer par créer une branche qui respecte les conventions de nommage : git checkout -b feature/good-bye
Puis, nous allons créer un fichier good-bye.ts et écrire la fonction suivante :

Et nous allons créer un commit contenant cette fonctionnalité : git commit -m “feat: good bye world”.
Vous l’avez peut-être remarqué, une erreur s’est glissée dans la fonction, nous allons donc faire un commit pour la corriger :

Avec le commit suivant : git commit -m “fix(good-bye): typo”.
Nous avons donc 2 commits alors qu’il serait plus pertinent d’en avoir qu’un seul. Nous allons donc utiliser le git rebase interactive pour réécrire l’historique des modifications.
Pour initialiser le rebase interactive on utilise la commande suivante : git rebase interactive HEAD~2
Cette commande va ouvrir l’interface suivante :

Sur cette interface on voit les 2 derniers commits de mon dépôt git (parce qu’on a utilisé HEAD~2). On y retrouve également une documentation des commandes qu’on peut utiliser devant l’identifiant de chaque commit.
Dans notre cas, on veut fusionner les modifications du deuxième commit avec le premier commit. C’est donc la commande fixup qui nous intéresse, nous allons donc remplacer pick devant le commit fix(good-bye): typo par fixup.
On enregistre et on obtient l’historique suivant (un seul commit) :
7f077f4 (HEAD -> feature/good-bye-world) feat: good bye world
Liens utiles
- https://wikipedia.org/wiki/Linus_Torvalds
- https://wikipedia.org/wiki/BitKeeper
- https://wikipedia.org/wiki/Git
- https://git-scm.com/book/
- https://nvie.com/posts/a-successful-git-branching-model/
- https://www.conventionalcommits.org/en/v1.0.0/
- https://ray.so
- https://www.atlassian.com/git/articles/git-team-workflows-merge-or-rebase

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é.

- 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.
- 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.
- 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 :
- Given, la condition préalable au test
- When, l'exécution du système testé
- 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 :
- When, la condition préalable au test
- 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 :
- La partie Arrange contient la logique de configuration du test. C'est ici qu'on initialise le test.
- 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.
- 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.
.png)
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.
.png)
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.
.png)
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.
.png)
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.
.png)
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.
.png)
Le test échoue, on va maintenant gérer le cas du Fizz dans la fonction.
.png)
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.
.png)
Le test échoue, on met à jour le code.
.png)
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.
.png)
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.
.png)
.png)
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.
.png)
.png)
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
- Kent Beck - Wikipédia
- TDD Manifesto
- "Test-Driven Development by Example" de Kent Beck
- "Clean Code: A Handbook of Agile Software Craftsmanship" de Robert C. Martin
- Artisan Développeur - Benoit Gantaume
- Wealcome - Michaël Azerhad
- Craft Academy - Pierre Criulanscy

Le database branching est une approche d’organisation de base de données qui permet de reproduire la dynamique et le fonctionnement des branches Git.
On va alors pouvoir à partir d’une base de données appelé “master” pouvoir dupliquer une “branche” avec un certain nom. Cette nouvelle base de données se vera hériter des données ainsi que des migrations de la branche source.
Les cas d’usages de ce principe sont multiples et variés. Si nous reprenons l’analogie avec Git flow, lorsque vous allez créer une nouvelle branche de feature, vous serez amené à devoir développer puis appliquer une migration de données ou bien tout simplement altérer les données contenues dans cette base. Elle devient à partir de là un bac à sable tout en partant d’un environnement déjà prédéfini.
Grâce à la nouvelle base de données mise en place pour votre feature, vous n’allez impacter aucun environnement de production / staging / dev mis en place et accessible par tous les développeurs.
Votre base de données sera alors unique et éphémère, une fois la feature terminée, celle-ci pourra être supprimée.
Elle peut aussi servir de base de données temporaire pour une démonstration client, alimentée de données bien précises pour cette dite démonstration.
Pour terminer cette introduction, j’ajouterai que le database branching est présent avant tout pour améliorer la “DX” des développeurs au quotidien.
Pourquoi ne pas alors simplement produire une base de données sur ma machine ?
Il est autant possible que l’infrastructure du projet mette à disposition un cluster de base de données sur un serveur ou bien qu’un développeur puisse créer son cluster sur sa machine.
Avec un provisionnement type Docker vous pouvez déployer rapidement une base de données sur votre machine avec un script de seeding permettant d’alimenter cette base en données. Cependant, vous allez perdre une composante essentielle au database branching qui est la synchronisation de la branche Git avec les données. En effet, si vous êtes plusieurs développeurs à intervertir sur cette feature / environnement, aucune manipulations supplémentaires ne sera à faire lors du passage sur la branche Git. Vous récupérez la base de données déjà préparée par le précédent développeur.
Vous allez aussi avoir la problématique d’espace disponible sur votre machine, si vous travaillez sur plusieurs branches en même temps, cela implique de pouvoir posséder un conteneur d’une base de données unique par branche. Donc, une grande quantité de données en local.
Comment s’intègre le Database branching dans le workflow du développeur
Comme n’importe quel outil s’ajoutant sur une stack d’un projet, le database branching viens complexifier quelques aspects techniques de celui-ci.
Alors, il est nécessaire d’automatiser le maximums d’aspects du database branching afin de ne pas augmenter le nombre de tâches à réaliser par les développeurs lors de la création d’une nouvelle feature.
En laissant certaines tâches manuelles, nous risquons de frustrer nos collègues développeurs. En effet, il est très facile d’oublier d’exécuter une certaine commande après un changement de branche.
Dans la deuxième partie de l’article nous nous intéresseront à réaliser un environnement de développement fluide avec l’exemple d’une stack web.
Je dirai alors que le database branching idéal est celui qui est complètement transparents pour les développeurs.
Dans la finalité ce principe est plus ou moins une idéologie, le degrés de l’implémentation peut dépendre de l’envergure du projet et du nombre de développeurs.
Tutoriel: Mise en place du database branching sur une stack Typescript, Prisma
Initialisation du projet et de la base de donnée
La première étape de ce tutoriel sera de se munir d’une base de données avec un utilisateur ayant l’autorisation de créer des database supplémentaires.
Voici plusieurs providers proposant ce service:
Actuellement nous utilisons une base de données hébergée Aurora Serverless hébergée sur AWS déployée depuis Terraform avec le module suivant.
Pour la suite de ce tutoriel nous avons choisis d’utiliser une base de données PostgreSQL. Il est aussi tout à fait possible de l’intégrer sur une base de données MongoDB, MySQL, …
Pour passer rapidement sur les étapes d’initialisation du projet TS avec Prisma je vous redirige vers la documentation officielle de Prisma.
Après toutes ces étapes vous devriez avoir dans la racine de votre projet un fichier d’environnement nommé .env qui possède une url de base de données DATABASE_URL.
À présent nous pouvons remplacer cette url par celle de notre base de données provisionnée un peu plus haut.
DATABASE_URL="postgresql://gabriel:password@db-branching.cluster-xxxxxxx.eu-west-3.rds.amazonaws.com:5432/master?schema=public"
La database pointée (master dans ce cas-là) importe peu, elle sera mise à jour par la suite automatiquement.
Automatisation du changement de branche
Afin de faciliter le passage sur une nouvelle base de données à chaque changement de branche git, il est possible de créer un hook sur le projet git, qui sera exclusivement lancé lors d'une commande git checkout.
Pour celà nous utiliserons un outil facilitant la création de hook git nommé Husky.
Voici les commandes d’installation que vous pouvez retrouver dans la documentation officielle:
.png)
Cette dernière commande va alors créer un script bash dans le dossier suivant.husky/post-checkout.
On ajoutera ces trois lignes de bash permettant de récupérer la branche git lors d’un checkout et de mettre à jour le fichier .env
.png)
Et voilà !
Maintenant à chaque changement de branche en local votre .env sera mis à jour automatiquement.
Il est possible d’aller plus loin en ajoutant l’application automatique des migrations de la base données et/ou le seeding de data.

Découvrons aujourd’hui l'univers captivant de l'architecture hexagonale. Cette approche du développement d'applications mobiles repose sur des principes fondamentaux, offrant une structure robuste et évolutive. Dans cet article, explorez les bases de l'architecture hexagonale, découvrez des exemples concrets sur GitHub et apprenez à l'intégrer avec Spring Boot. Optimisez votre code, maîtrisez l'inversion des dépendances et transformez votre façon de concevoir des applications mobiles.
Bienvenue dans le futur du développement logiciel !
Qu'est-ce que l'architecture hexagonale ?
L'architecture hexagonale redéfinit la conception des applications mobiles. À la base de cette approche novatrice se trouvent des principes clés, sculptant une structure en forme d'hexagone. Cette méthode se distingue par son agilité, son adaptabilité et son aptitude à créer des applications robustes. Découvrons les fondements de l'architecture hexagonale pour comprendre comment elle redéfinit le développement logiciel.
L'architecture hexagonale transcende les schémas conventionnels de développement logiciel. Imaginons-la comme une vue aérienne de votre application, où un hexagone représente le cœur, le noyau de votre système. Plongeons dans les détails de cette approche novatrice.
Au centre de cette structure, nous trouvons l'hexagone central. C'est le cœur, le noyau où réside la logique métier de votre application. Cet espace défini par l'hexagone représente l'essence même de ce que votre application offre à ses utilisateurs.
Les côtés de l'hexagone représentent les couches périphériques. Chacune de ces couches a un rôle spécifique dans l'interaction de l’application avec le monde extérieur. De la gestion des entrées/sorties à la persistance des données, ces couches entourent le noyau central, mais sans créer de dépendances directes avec lui.
Les interactions entre le cœur et les couches périphériques se font à travers des ports et adaptateurs. Les ports définissent des interfaces au sein du noyau, tandis que les adaptateurs fournissent des implémentations concrètes pour ces interfaces. Cette modularité offre une flexibilité essentielle, permettant à l'application de s'adapter sans altérer sa logique métier.
Enfin, l'inversion des dépendances est le principe qui gouverne l'architecture hexagonale. Plutôt que d'avoir des dépendances directes, le cœur de l'application dépend d'abstractions définies par les ports. Cette inversion crée un environnement flexible permettant des modifications sans impacter la stabilité du système.
Pour comprendre pleinement l'architecture hexagonale, explorons des exemples concrets.
L'architecture hexagonale ne se contente pas de suivre les sentiers battus du développement logiciel. Imaginez-la comme une vue aérienne de votre application, où un hexagone représente le cœur, le noyau vibrant de votre système. Plongeons dans les détails pour rendre cette approche plus tangible.
Au cœur, l'hexagone central incarne la logique métier de votre application. C'est là que réside l'essence de ce que votre application offre à ses utilisateurs. Autour de ce noyau, les côtés de l'hexagone représentent les couches périphériques. De la gestion des entrées/sorties à la persistance des données, chaque couche a un rôle précis dans l'interaction de l'application avec le monde extérieur.
Exemples concrets
Imaginons une application de gestion de tâches où le cœur de l'hexagone représente la logique de gestion des tâches, des deadlines, etc. Les côtés de l'hexagone pourraient inclure une couche d'interface utilisateur, une couche de persistance des données, et une couche de services externes.
Les interactions entre le cœur et les couches périphériques s'effectuent à travers des ports et adaptateurs. Les ports définissent des interfaces au sein du noyau, tandis que les adaptateurs fournissent des implémentations concrètes pour ces interfaces. Cette modularité offre une flexibilité essentielle, permettant à l'application de s'adapter sans compromettre sa logique métier.
Supposons que le port "GestionTâchesPort" définisse les opérations nécessaires à la gestion des tâches. L'adaptateur "GestionTâchesAdapter" fournirait l'implémentation concrète de ces opérations, interagissant avec la base de données et les services externes.
Enfin, l'inversion des dépendances règne en maître dans l'architecture hexagonale. Plutôt que des dépendances directes, le cœur dépend d'abstractions définies par les ports. Cette inversion crée un environnement souple, permettant des modifications sans secouer la stabilité du système.
Plutôt que d'avoir des dépendances directes vers la base de données, le cœur dépendrait d'interfaces définies dans le port "PersistancePort", laissant les détails d'implémentation à l'adaptateur "PersistanceAdapter".
En résumé, l'architecture hexagonale offre une vision stratégique du développement logiciel. Elle place la logique métier au centre, entourée de couches flexibles facilitant l'interaction avec le monde extérieur. Cette approche, avec son hexagone central et ses principes fondamentaux, ouvre la voie à des applications mobiles robustes, adaptables et pérennes.
Les principes de l'architecture hexagonale
L'architecture hexagonale repose sur des fondements solides, formant une structure en forme d'hexagone pour créer des applications mobiles robustes. Décortiquons les principes clés qui définissent cette approche innovante :
- L'architecture hexagonale est structurée en couches fondamentales. De la couche d'infrastructure à celle de persistance, chaque strate joue un rôle crucial. Cela offre une organisation claire, favorisant la stabilité et la modularité.
- Le point d'entrée représente l'accès initial à l'application, tandis que la logique métier dicte son fonctionnement interne. Cette dualité assure une expérience utilisateur fluide, équilibrant l'interaction extérieure avec la logique interne.
- Fondamentale à l'architecture hexagonale, l'inversion des dépendances renverse les schémas traditionnels. Cette approche permet à l'application de s'adapter aux changements sans compromettre sa stabilité. Elle crée un environnement où la logique métier guide les détails d'implémentation.
Mise en pratique de l'architecture hexagonale
Découvrons comment concrètement mettre en œuvre l'architecture hexagonale dans le développement d'applications mobiles. Plongeons dans des exemples tangibles pour comprendre son impact réel.
Explorez un exemple concret sur GitHub où le code source d'une application est dévoilé. Chaque composant, de la couche d'infrastructure à la couche de persistance, est clairement défini. Visualisez comment ces éléments s'entremêlent pour former une structure cohérente. Cette transparence simplifie le processus de développement, permettant une compréhension facile et une évolution efficace de l'application.
L'intégration pratique de l'architecture hexagonale est facilitée avec Spring Boot. Cette union offre une approche concrète pour développer des applications mobiles robustes. Elle simplifie la gestion des dépendances et maintient la flexibilité, permettant aux développeurs de se concentrer sur la création plutôt que sur des considérations techniques.
L'architecture hexagonale dans le contexte du Domain-Driven Design
Plongeons dans la synergie puissante entre l'architecture hexagonale et les principes du Domain-Driven Design (DDD), développant ainsi des applications mobiles de plus grande qualité.
L'architecture hexagonale et le Domain-Driven Design (DDD) fusionnent harmonieusement pour définir des modèles de domaine robustes offrant ainsi une approche complète du développement logiciel.
Lorsque nous plongeons l'architecture hexagonale dans le contexte du Domain-Driven Design (DDD), une collaboration symbiotique émerge. Ces deux approches, axées sur la compréhension profonde du domaine métier, se renforcent mutuellement.
1. Collaboration Harmonieuse
Imaginons une application de commerce électronique. Dans l'architecture hexagonale, le cœur de l'hexagone représente la gestion des commandes, des transactions, et des stocks, constituant la logique métier centrale. Dans le contexte du DDD, ces entités deviennent les agrégats du domaine, chacun avec son propre cycle de vie et ses règles métier spécifiques. Ainsi, l'hexagone central et les agrégats du DDD collaborent harmonieusement pour façonner le modèle de domaine.
2. Réflexion sur le Contexte Limité
Poursuivons avec la réflexion sur le contexte limité du DDD. Supposons que notre application de commerce électronique ait également un module de gestion des utilisateurs. Dans l'architecture hexagonale, cela devient une autre zone centrale, avec ses propres ports et adaptateurs. Dans le contexte limité du DDD, ce module représente son propre sous-domaine avec ses règles métier distinctes. Cette approche permet une séparation claire des préoccupations et une meilleure compréhension du modèle de domaine, alignant ainsi l'architecture hexagonale avec les principes du DDD.
3. Alistair Cockburn et les Fondements
Alistair Cockburn, un pionnier du Domain-Driven Design, souligne l'importance de définir des interactions précises entre les entités du domaine. Dans l'architecture hexagonale, cela se traduit par la définition précise des ports et adaptateurs, offrant une interface bien définie pour chaque interaction. Cette synchronicité entre les principes de Cockburn et l'architecture hexagonale garantit une compréhension approfondie du domaine et une mise en œuvre logicielle qui reflète fidèlement la réalité métier.
L'architecture hexagonale et le Domain-Driven Design forment une alliance puissante. En utilisant des exemples concrets, nous avons vu comment ces approches complémentaires collaborent pour créer des modèles de domaine clairs, des contextes limités bien définis, et des applications mobiles riches en fonctionnalités métier.
Nos conseils pratiques et astuces
Explorez des conseils concrets et des astuces judicieuses pour optimiser l'utilisation de l'architecture hexagonale dans le développement d'applications mobiles.
Dans la mise en œuvre de l'architecture hexagonale, privilégiez la clarté. Des noms de classes explicites aux commentaires informatifs, assurez-vous que chaque composant de votre application est compréhensible. La transparence facilite la collaboration et la maintenance à long terme.
Investissez dans des tests unitaires approfondis. L'architecture hexagonale favorise la testabilité, alors profitez-en. Des tests solides garantissent la stabilité de votre application et facilitent l'identification rapide des problèmes potentiels.
Accompagnez votre code d'une documentation complète. Décrivez les choix architecturaux, les interactions clés, et les modèles de domaine. Une documentation détaillée facilite l'intégration de nouveaux membres dans l'équipe et assure une compréhension globale du projet.
Soyez sélectif quant aux dépendances. Limitez-vous aux dépendances nécessaires pour éviter la complexité inutile. Une architecture hexagonale bien conçue privilégie la simplicité, ce qui facilite la maintenance et l'évolutivité.
Adoptez une approche itérative. L'itération continue associée au réajustement est essentielle. Recueillez les retours, identifiez les améliorations possibles, et évoluez constamment. Cette approche flexible s'aligne parfaitement avec les principes de l'architecture hexagonale.
L'architecture hexagonale se révèle comme une approche incontournable pour le développement d'applications mobiles. Avec ses principes solides, sa mise en pratique transparente, et sa synergie avec le Domain-Driven Design, elle offre une solution robuste et flexible.
Priorisez la clarté, investissez dans des tests unitaires approfondis, documentez judicieusement, évitez les dépendances superflues, et adoptez une approche itérative pour un succès continu.
En embrassant l'architecture hexagonale, vous développez des applications mobiles plus résilientes et créez une base pour l'innovation future. Restez agile, apprenez constamment, et évoluez avec votre application.
L'architecture hexagone est le socle sur lequel repose l'avenir du développement logiciel mobile.