Apprivoiser le code rebelle : Feature Flags dans les projets Kotlin

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Préface : Pourquoi les fonctionnalités cassent-elles les releases ?

\n

Chaque développeur s'est au moins une fois retrouvé dans une situation où une nouvelle fonctionnalité brillante est déjà prête, mais ne peut pas être publiée. Soit elle n'a pas passé le QA complet, soit le marketing n'a pas encore préparé les bannières, soit on a simplement peur d'appuyer sur le bouton "Deploy" un vendredi soir. À ce moment-là, on commence généralement à écrire des if, à basculer des BuildConfig ou, pire encore, à commenter le code.

\n

Ça vous parle ? Bienvenue dans le monde des feature flags (ou feature toggles). Ce n'est pas juste "un truc architectural de plus". C'est votre bouée de sauvetage qui vous permet de déployer du code en production, mais de ne l'activer que pour certains. Dans cet article, nous allons voir comment implémenter des feature flags dans les projets Kotlin — des solutions simples aux systèmes avancés. Et oui, il y aura beaucoup de code.

\n\n

Qu'est-ce qu'un Feature Flag et pourquoi en avez-vous besoin ?

\n

Un Feature Flag (ou feature toggle) est un interrupteur logiciel qui permet d'activer ou de désactiver une fonctionnalité sans modifier le code et sans redéploiement. Imaginez que vous puissiez déployer un nouvel algorithme de recommandations en production, mais ne l'activer que pour 5% des utilisateurs. Ou l'activer uniquement pour les employés de l'entreprise pour des tests internes. Cool, non ?

\n

Voici quelques scénarios où les feature flags sont indispensables :

\n
    \n
  • Canary releases : Déployez une nouvelle fonctionnalité sur 1% des serveurs, surveillez les erreurs et augmentez progressivement le pourcentage.
  • \n
  • Tests A/B : Vérifiez quelle version de l'UI convertit le mieux, sans copier tout le projet.
  • \n
  • Kill switch : Si une nouvelle fonctionnalité commence à "bouffer" de la mémoire ou provoque un bug, vous la désactivez simplement d'un geste (ou d'une requête API).
  • \n
  • Séparation de la release et du déploiement : Le code est déployé, mais la fonctionnalité "dort" jusqu'à la date X.
  • \n
\n

En Kotlin, qui est activement utilisé à la fois pour le backend (Ktor, Spring Boot) et pour les applications mobiles (Android), les feature flags deviennent particulièrement pertinents en raison du typage strict et des exigences de propreté du code.

\n\n

Architecture : Comment ne pas transformer les flags en spaghetti

\n

La plus grande erreur des débutants est de disperser des if (flag.isEnabled()) { ... } else { ... } dans tout le projet. Cela conduit à ce qu'au bout d'un mois, vous ne puissiez plus comprendre quelles branches de code sont vivantes et lesquelles sont mortes. Nous avons besoin d'une gestion des fonctionnalités, pas d'interrupteurs chaotiques.

\n

Une bonne architecture repose sur le principe d'inversion des dépendances. Votre code métier ne doit pas savoir d'où vient la valeur du flag (d'un fichier, d'une base de données ou d'un service externe). Il demande simplement : "Hé, FeatureFlagService, la fonctionnalité new_checkout est-elle activée ?"

\n

Examinons deux approches : une simple (pour les petits projets) et une avancée (pour les microservices et Kubernetes).

\n\n

1. Approche simple : Configuration et Enum

\n

Si vous avez besoin de démarrer rapidement et que vous ne construisez pas un système avec un million de requêtes par seconde, vous pouvez vous contenter d'un simple enum class et d'un fichier de configuration (par exemple, application.conf pour Ktor ou application.yml pour Spring).

\n

Créons un enum de toutes les fonctionnalités :

\n
enum class Feature(val key: String) {\n    NEW_PAYMENT_FLOW("feature.new-payment-flow"),\n    DARK_MODE("feature.dark-mode"),\n    SMART_SEARCH("feature.smart-search")\n}
\n

Maintenant, le service qui lit la configuration :

\n
class FeatureFlagService(private val config: Map<String, Boolean>) {\n\n    fun isEnabled(feature: Feature): Boolean {\n        return config.getOrDefault(feature.key, false)\n    }\n\n    // Pour les tests A/B, on peut ajouter une randomisation\n    fun isEnabledForUser(feature: Feature, userId: String): Boolean {\n        if (!isEnabled(feature)) return false\n        // Hachage très simple pour diviser en groupes\n        val group = userId.hashCode() % 100\n        return group < 50 // 50% des utilisat                

Blogs

Book Recommendations