Quand un simple vrai/faux ne suffit pas : placer les feature flags dans votre code
Vous avez développé une nouvelle fonctionnalité. Le code compile, les tests passent, et vous êtes prêt à livrer. Mais vous ne voulez pas activer l'interrupteur pour tout le monde en même temps. Peut-être voulez-vous d'abord des testeurs internes. Peut-être seulement des utilisateurs en Asie. Peut-être juste 10 pour cent du trafic.
C'est là que les feature flags entrent en jeu. Ils vous permettent de séparer le déploiement de la mise en production : vous pouvez mettre du nouveau code en production sans le rendre visible à tout le monde. Mais comment placer ces drapeaux dans votre code sans en faire un fouillis de conditions emmêlées ?
Le flag le plus simple : un interrupteur booléen
À la base, un feature flag n'est qu'une branche conditionnelle. Si le flag est activé, exécutez le nouveau code. S'il est désactivé, exécutez l'ancien code. La forme la plus basique ressemble à ceci :
if fiturXEnabled:
show_new_feature()
else:
show_old_feature()
Ici, fiturXEnabled est une variable booléenne. Mettez-la à True, et les utilisateurs voient la nouvelle fonctionnalité. Mettez-la à False, et ils voient l'ancienne. Simple.
Mais il y a un hic : la valeur du flag doit être déterminée avant l'exécution du code. Si vous voulez la changer sans redéployer, vous devez lire la valeur depuis un endroit extérieur au code lui-même. Cela peut être un fichier de configuration, une variable d'environnement ou un service distant. Nous aborderons le contrôle à distance des flags plus tard, mais pour l'instant, concentrons-nous sur le moment où un simple flag booléen suffit.
Un flag booléen fonctionne bien lorsque votre fonctionnalité est petite et que vous n'avez besoin que de deux états : activé ou désactivé. Par exemple, imaginez un bouton "imprimer le rapport" qui était auparavant réservé aux administrateurs. Vous souhaitez maintenant l'ouvrir à tous les utilisateurs. Vous ajoutez un flag appelé printReportForAllUsers. Quand il est à True, le bouton apparaît pour tout le monde. Quand il est à False, seuls les administrateurs le voient. Terminé.
Quand le simple ne suffit pas : les flags conditionnels
Parfois, vous avez besoin de plus de nuance. Peut-être que la nouvelle fonctionnalité ne doit être visible que pour les utilisateurs avec des identifiants spécifiques. Peut-être seulement pour les utilisateurs d'une région particulière. Peut-être seulement 10 pour cent du trafic, sélectionné aléatoirement. Un simple booléen ne peut pas gérer cela.
Vous avez besoin d'un flag conditionnel. Le flag lui-même reste un booléen, mais la logique qui détermine sa valeur dépend du contexte. L'approche la plus simple consiste à ajouter des conditions en dehors du flag :
if fiturXEnabled and user.id in trial_user_list:
show_new_feature()
else:
show_old_feature()
Cela fonctionne, mais trial_user_list doit être géré séparément. Si la liste change fréquemment, vous avez besoin d'un moyen de la mettre à jour sans redéployer. Cela ajoute de la complexité.
Une approche plus propre consiste à utiliser un fournisseur de flags. Un fournisseur de flags est une fonction ou une bibliothèque qui accepte un contexte (comme l'ID utilisateur, la région, le type d'appareil) et renvoie une valeur de flag basée sur des règles prédéfinies. Votre code devient :
if flag_provider.is_enabled("featureX", user=current_user):
show_new_feature()
else:
show_old_feature()
En coulisses, le fournisseur de flags vérifie les règles : cet utilisateur est-il dans le groupe d'essai ? Sa région correspond-elle ? Le pourcentage de trafic a-t-il été atteint ? Vous n'avez pas besoin de réécrire cette logique chaque fois que vous utilisez le flag.
Garder votre code propre
Plus vous ajoutez de flags, plus les branches conditionnelles apparaissent dans votre code. Sans discipline, vous vous retrouvez avec des instructions if imbriquées difficiles à lire et encore plus difficiles à maintenir.
Quelques principes aident :
Un flag, une responsabilité. Ne fourrez pas plusieurs conditions dans un seul flag. Si vous devez contrôler la visibilité par région et par rôle utilisateur, utilisez deux flags séparés. C'est plus clair et plus facile à supprimer plus tard.
Placez les flags au bon niveau. Mettez le flag aussi près que possible du point d'entrée de la fonctionnalité. Pour un composant d'interface utilisateur, cela pourrait être la fonction de rendu du composant. Pour un point d'API, cela pourrait être le gestionnaire. Évitez de disperser le même flag à travers plusieurs couches de votre code.
Planifiez la suppression du flag. Chaque flag que vous ajoutez est du code temporaire. Lorsque la fonctionnalité est entièrement déployée, vous supprimerez l'ancien chemin de code et le flag. Écrivez vos flags de manière à ce qu'ils soient faciles à trouver et à supprimer. Regroupez les flags connexes ensemble. Utilisez des noms cohérents comme featureX_enabled ou featureX_percentage.
Une checklist pratique
Avant d'écrire votre prochain feature flag, passez en revue ces points :
- Cette fonctionnalité peut-elle être contrôlée avec un simple booléen, ou avez-vous besoin d'une logique conditionnelle ?
- D'où viendra la valeur du flag ? Codée en dur, fichier de configuration, variable d'environnement ou service distant ?
- Le flag est-il placé au bon niveau, près de l'endroit où la fonctionnalité est utilisée ?
- Le flag a-t-il une seule responsabilité claire ?
- Avez-vous prévu comment supprimer le flag et l'ancien chemin de code plus tard ?
La suite
Une fois votre flag dans le code, la question suivante est de savoir comment changer sa valeur sans redéployer. Vous avez besoin d'un moyen de contrôler les flags à distance, que ce soit via un fichier de configuration qui est rechargé, des variables d'environnement mises à jour, ou un tableau de bord dédié. C'est là que la véritable puissance des feature flags se manifeste : vous pouvez activer et désactiver des fonctionnalités, les déployer progressivement et réagir aux problèmes sans toucher au pipeline de déploiement.
Mais tout cela ne sert à rien si vos flags sont en désordre. Commencez par des flags propres et bien placés dans votre code. Le reste suivra.