L’Architecture Hexagonale sur un projet Web + Mobile (Partie 1 sur 5)

Explorons comment la logique métier peut être partagée et gérée efficacement à travers différentes plateformes.

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.

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.

➜ npx create-nx-workspace@latest

✔ Where would you like to create your workspace? · broney
✔ Which stack do you want to use? · none
✔ Package-based monorepo, integrated monorepo, or standalone project? · package-based
✔ Enable distributed caching to make your CI faster · Yes

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.

➜ nx g @nx/js:lib libs/core

✔ Which unit test runner would you like to use? · vitest
✔ Which bundler would you like to use to build the library? Choose 'none' to skip build setup. · rollup

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

name: CI
on:
	push:
	branches:
	- main
	pull_request:

jobs:
	main:
		runs-on: ubuntu-latest
		steps:
			- uses: actions/checkout@v4
				with:
					fetch-depth: 0
			# Cache node_modules
			- uses: actions/setup-node@v3
				with:
					node-version: 20
					cache: 'yarn'
			- run: yarn --no-progress --frozen-lockfile
			- uses: nrwl/nx-set-shas@v4.0.4

			- run: npx nx format:check
			- run: npx nx affected -t lint,test,build --parallel=3

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.

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

Ne manquez rien
Abonnez-vous à notre newsletter

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

Nos experts vous parlent
Le décodeur

Laravel vs Symfony : quel Framework choisir ? Le guide
4/12/2023

Bienvenue dans l'univers du développement web, où chaque choix compte. Laravel et Symfony, deux géants du langage serveur PHP, se disputent la première place. Dans cet article, nous plongeons dans les détails, examinant performances, sécurité, et courbes d'apprentissage.

Prêts à choisir le Framework idéal pour votre projet ? 

Laravel et Symfony : Les titans du développement PHP

Dans l'arène du développement serveur PHP, deux titans émergent : Laravel et Symfony.

Laravel, créé par Taylor Otwell, séduit par son architecture élégante basée sur le modèle MVC (pour Modèle-Vue-Contrôleur), ses outils puissants, et une courbe d'apprentissage conviviale.

De l'autre côté, Symfony, de SensioLabs, brille par sa modularité et des composants réutilisables. Avant de choisir votre champion, explorons en détail ce que chaque Framework peut vous offrir.

Laravel

Laravel est un Framework PHP qui a su captiver la communauté des développeurs. Imaginé par le développeur américain, Taylor Otwell, Laravel séduit par son architecture claire et élégante, basée sur le modèle architectural MVC. Cette structure facilite la conception d’applications et le développement en offrant une séparation nette entre les composants d’un projet.

Laravel ne fait pas que promettre, il délivre des performances remarquables. Les temps de réponse sont optimisés pour offrir une expérience utilisateur plus fluide. La gestion intelligente des bases de données et les outils intégrés font de Laravel un choix judicieux pour des applications performantes.

Dans le monde numérique d'aujourd'hui, la sécurité est primordiale. Pour cela, Laravel intègre des systèmes robustes garantissant la protection à long terme de vos applications web modernes. Des mécanismes de sécurité avancés sont mis en place pour contrer les menaces potentielles.

La courbe d'apprentissage est souvent un obstacle, mais pas avec Laravel. Son approche conviviale permet aux développeurs de rapidement maîtriser le Framework. La documentation détaillée et la communauté active font de l'apprentissage une expérience fluide.

Exemple de code concret : Gestion des utilisateurs avec Laravel

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

  • Laraval utilise l’ORM (pour Object Relational Model) Eloquent pour simplifier les opérations d’interactions avec la base de données.
  • La fonction bcrypt () sécurise le mot de passe avant son enregistrement.
  • La réponse est renvoyée au format JSON.

Laravel est votre allié dans la création d'applications web dynamiques et performantes.

Symfony

L’univers du Framework PHP Symfony est tout aussi passionnant. Renommé, riche et modulaire, Symfony est développé et maintenu par la société française SensioLabs. Symfony se démarque par son approche modulaire et ses composants réutilisables, offrant une flexibilité remarquable dans la conception d’application web.

Symfony ne se contente pas d'une architecture flexible, il excelle également en matière de performances. Les temps de réponse compétitifs et la gestion efficace des ressources font de Symfony un choix judicieux pour réaliser des applications PHP performantes.

La sécurité étant une priorité dans le paysage numérique actuel, Symfony intègre des mécanismes de sécurité assurant la protection de vos applications contre les menaces. La courbe d'apprentissage de Symfony est également conçue pour faciliter l'adoption du Framework. Les développeurs bénéficient d'une documentation exhaustive et d'une communauté active, simplifiant ainsi l'exploration des fonctionnalités avancées de Symfony.

Exemple de code concret : gestion des utilisateurs avec Symfony

Une image contenant texte, capture d’écranDescription générée automatiquement

  • Symfony utilise l’ORM Doctrine ainsi que les méthodes setName(), setEmail(), et setPassword() pour définir les propriétés de l'objet utilisateur.
  • Le mot de passe est sécurisé à l’aide de password_hash().
  • La méthode flush() persiste les changements en base de données.
  • La réponse est renvoyée au format JSON.

En somme, Symfony est un partenaire fiable pour le développement web.

Comparaison directe

Plongeons dans la comparaison directe entre Laravel et Symfony, examinant de près les éléments clés qui pourraient influencer votre décision dans le choix du Framework PHP idéal.

Performance : la quête de la réactivité

La performance est cruciale pour une expérience utilisateur optimale. Nous comparons les temps de réponse de Laravel et Symfony pour vous aider à choisir le Framework qui offre la réactivité nécessaire à votre projet.

  • Temps de Réponse : Laravel excelle avec des temps de réponse moyens de 250 millisecondes, offrant une expérience utilisateur rapide. Symfony, bien que compétitif, tend à se situer légèrement au-dessus, aux alentours de 300 millisecondes.
  • Exemple : Un site e-commerce nécessitant une navigation rapide pourrait bénéficier des performances de Laravel, assurant une réponse quasi-instantanée lors de la recherche de produits.

Architecture : MVC sous le microscope

L'architecture MVC (Modèle-Vue-Contrôleur) est le pilier du développement web moderne. Analysons comment Laravel et Symfony abordent cette structure fondamentale et en quoi cela peut impacter la gestion de votre code.

  • Laravel : Son modèle MVC clair offre une structure fluide. Les développeurs peuvent facilement segmenter les responsabilités, améliorant la maintenabilité du code.
  • Symfony : Une approche modulaire permettant une personnalisation avancée. Les composants réutilisables simplifient le développement, mais cela peut entraîner une complexité accrue pour les petits projets.
  • Exemple : Un projet nécessitant une structure claire et simple pourrait préférer Laravel, tandis qu'un système complexe pourrait tirer parti de la modularité de Symfony.

Command Line Interface (CLI) : L'art de la ligne de commande

La ligne de commande est l'alliée du développeur moderne. Comparons comment Laravel et Symfony s'engagent dans le royaume de l'interface en ligne de commande (CLI), facilitant ainsi le flux de travail du développeur.

  • Laravel : La CLI de Laravel simplifie les tâches courantes telles que la génération de code, facilitant le flux de travail du développeur.
  • Symfony : Une CLI robuste, mais avec une courbe d'apprentissage plus prononcée. Elle offre une personnalisation avancée, mais peut sembler complexe pour les débutants.
  • Exemple : Pour un développeur qui privilégie la simplicité et la rapidité, la CLI de Laravel serait un choix naturel.

Migration de base de données : Gestion intelligente des données

La migration efficace de la base de données est un défi incontournable. Jetons un regard attentif sur la manière dont Laravel et Symfony simplifient ce processus critique pour garantir une gestion fluide des données.

  • Laravel : Les migrations simplifient les changements de schéma de base de données. Les développeurs peuvent versionner et partager ces modifications facilement.
  • Symfony : Des migrations intégrées offrant également une gestion efficace des changements de base de données. Les bundles Symfony facilitent la modularité.
  • Exemple : Un projet nécessitant des mises à jour fréquentes de la base de données pourrait bénéficier de la simplicité des migrations de Laravel.

N’hésitez pas à plonger davantage dans ces détails pour faire un choix éclairé entre Laravel et Symfony, en alignant les forces de chaque Framework avec les exigences spécifiques de votre projet.

Frameworks PHP : Un choix déterminant pour le développement web

Explorez l'impact déterminant que le choix entre Laravel et Symfony peut avoir sur votre projet de développement web.

Choisir le bon Framework : un dilemme crucial

La sélection du bon Framework PHP est un dilemme majeur, influençant directement la réussite de votre projet. Laravel et Symfony offrent des avantages uniques, mais lequel répond le mieux à vos besoins spécifiques ?

  • Laravel : Excellant dans la simplicité et la rapidité de développement, Laravel est souvent le choix préféré pour les projets de taille moyenne nécessitant une mise en œuvre rapide.
  • Symfony : Connu pour sa modularité et ses composants réutilisables, Symfony brille dans des projets plus complexes où la personnalisation et la réutilisation de code sont essentielles.
  • Exemple : Un site vitrine pour une petite entreprise pourrait privilégier la simplicité de Laravel, tandis qu'un système de gestion complexe opterait probablement pour la modularité de Symfony.

Forces et faiblesses : un examen critique

Chacun des Frameworks a ses points forts et ses faiblesses. Examinons en détail les avantages et les limitations de Laravel et Symfony pour vous guider dans cette décision cruciale.

  • Laravel : Points forts dans la simplicité, la documentation claire et la courbe d'apprentissage conviviale. Cependant, sa modularité peut être moins flexible pour des projets très spécifiques.
  • Symfony : Excellant dans la modularité, Symfony offre une flexibilité maximale, mais sa courbe d'apprentissage peut être plus abrupte pour les débutants.
  • Exemple : Un projet nécessitant des fonctionnalités spécifiques pourrait bénéficier de la flexibilité de Symfony, tandis qu'un projet plus simple pourrait opter pour la simplicité de Laravel.

Taille du projet : l'importance du contexte

La taille de votre projet est un facteur déterminant. Nous évaluons comment Laravel et Symfony s'adaptent aux projets de différentes envergures, vous permettant ainsi de choisir en fonction de vos besoins spécifiques.

  • Laravel : Idéal pour des projets de taille moyenne, où la rapidité de développement est cruciale.
  • Symfony : Convient particulièrement aux projets de grande envergure, offrant la modularité nécessaire pour gérer la complexité.
  • Exemple : Un blog personnel pourrait tirer parti de la simplicité de Laravel, tandis qu'un système de gestion d'entreprise complexe pourrait profiter de la robustesse de Symfony.

Performance attendue : Une réflexion essentielle

Quelles performances attendez-vous de votre application web ? Laravel et Symfony offrent des approches différentes. Décortiquons ces approches pour vous aider à prendre une décision éclairée.

  • Laravel : Performances élevées pour des projets de taille moyenne, avec des temps de réponse compétitifs.
  • Symfony : Excellentes performances également, mais peut être plus adapté à des projets plus vastes.
  • Exemple : Un site de portfolio artistique pourrait privilégier les performances de Laravel, tandis qu'un site e-commerce à fort trafic pourrait opter pour Symfony.

Préférences des développeurs : Un facteur humain

L'adhésion des développeurs à un Framework peut être un critère déterminant. Découvrez comment Laravel et Symfony sont perçus dans la communauté des développeurs, un aspect clé pour le succès à long terme de votre projet.

  • Laravel : Apprécié pour sa simplicité et son approche élégante, attirant souvent les développeurs cherchant une courbe d'apprentissage plus douce.
  • Symfony : Adopté par des développeurs expérimentés cherchant une modularité étendue et une personnalisation avancée.
  • Exemple : Une équipe de jeunes développeurs débutants pourrait se sentir à l'aise avec la simplicité de Laravel, tandis qu'une équipe expérimentée pourrait être attirée par la puissance de Symfony.

Après avoir exploré les nuances de Laravel et Symfony, il est temps de conclure. Chaque projet a des besoins uniques, et votre décision devrait être ancrée dans une évaluation minutieuse des forces et des faiblesses de chaque Framework.

En conclusion, gardez un œil sur l'horizon du développement web. Les Frameworks évoluent, les tendances changent. Votre choix devrait également être orienté vers l'avenir, en tenant compte des mises à jour futures, de la communauté active et des innovations à venir.

Votre choix entre Laravel et Symfony déterminera la trajectoire de votre projet. Explorez les possibilités infinies offertes par ces Frameworks PHP et prenez votre décision en connaissance de cause. Votre aventure de développement web commence ici. Bonne exploration !

Trunk Based Development (TBD) vs Gitflow
16/11/2023

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 :

Et à l'usage, par exemple pour du React mais le principe est le même pour n'importe quel environnement :

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

Git : initiation, merge vs rebase, démo
22/6/2023

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

Format Conventional Commits

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.
Exemples de commits suivant la convention

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

Échangeons sur votre projet !

Développement web
Application mobile
Design & Product
Nous contacter

Simulateur

Bienvenue dans le
simulateur d’estimation

Sélectionnez
vos besoins

Sélectionnez un ou plusieurs choix

Définissez les
fonctionnalités

Sélectionnez un ou plusieurs choix

Dernière
étape !

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

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

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