Wenn ein einfaches Ja/Nein nicht reicht: Feature Flags richtig im Code platzieren

Sie haben eine neue Funktion gebaut. Der Code kompiliert, die Tests laufen grün, und Sie sind bereit für den Rollout. Aber Sie wollen den Schalter nicht für alle gleichzeitig umlegen. Vielleicht zuerst nur für interne Tester. Vielleicht nur für Nutzer in Asien. Vielleicht nur für 10 Prozent des Traffics.

Hier kommen Feature Flags ins Spiel. Sie trennen Deployment von Release: Sie können neuen Code in Produktion bringen, ohne dass ihn alle sofort sehen. Aber wie platzieren Sie diese Flags in Ihrem Code, ohne dass ein undurchschaubares Konditionen-Gewirr entsteht?

Das einfachste Flag: Ein boolescher Schalter

Im Kern ist ein Feature Flag nichts anderes als ein bedingter Zweig. Ist das Flag an, läuft der neue Code. Ist es aus, läuft der alte. Die einfachste Form sieht so aus:

if fiturXEnabled:
    show_new_feature()
else:
    show_old_feature()

Hier ist fiturXEnabled eine boolesche Variable. Setzen Sie sie auf True, sehen die Nutzer die neue Funktion. Setzen Sie sie auf False, sehen sie die alte. Simpel.

Aber es gibt einen Haken: Der Wert des Flags muss vor der Ausführung des Codes feststehen. Wenn Sie ihn ändern wollen, ohne neu zu deployen, müssen Sie den Wert von außerhalb des Codes einlesen. Das kann eine Konfigurationsdatei, eine Umgebungsvariable oder ein entfernter Dienst sein. Die Fernsteuerung von Flags behandeln wir später. Konzentrieren wir uns zunächst darauf, wann ein einfaches boolesches Flag ausreicht.

Ein boolesches Flag funktioniert gut, wenn Ihre Funktion klein ist und Sie nur zwei Zustände brauchen: an oder aus. Stellen Sie sich einen „Bericht drucken“-Button vor, der bisher nur Admins vorbehalten war. Jetzt soll er für alle Nutzer sichtbar sein. Sie fügen ein Flag namens printReportForAllUsers hinzu. Bei True erscheint der Button für alle, bei False nur für Admins. Fertig.

Wenn einfach nicht reicht: Bedingte Flags

Manchmal brauchen Sie mehr Nuancen. Vielleicht soll die neue Funktion nur für Nutzer mit bestimmten IDs sichtbar sein. Vielleicht nur für Nutzer in einer bestimmten Region. Vielleicht nur für 10 Prozent des Traffics, zufällig ausgewählt. Ein einfacher boolescher Wert kann das nicht abbilden.

Sie brauchen ein bedingtes Flag. Das Flag selbst ist immer noch boolesch, aber die Logik, die seinen Wert bestimmt, hängt vom Kontext ab. Der einfachste Ansatz ist, Bedingungen außerhalb des Flags zu ergänzen:

if fiturXEnabled and user.id in trial_user_list:
    show_new_feature()
else:
    show_old_feature()

Das funktioniert, aber trial_user_list muss separat verwaltet werden. Ändert sich die Liste häufig, brauchen Sie einen Weg, sie ohne erneutes Deployment zu aktualisieren. Das erhöht die Komplexität.

Eleganter ist ein Flag Provider. Ein Flag Provider ist eine Funktion oder Bibliothek, die Kontext (wie Nutzer-ID, Region, Gerätetyp) entgegennimmt und anhand vordefinierter Regeln einen Flag-Wert zurückgibt. Ihr Code wird dann zu:

if flag_provider.is_enabled("featureX", user=current_user):
    show_new_feature()
else:
    show_old_feature()

Im Hintergrund prüft der Flag Provider die Regeln: Ist dieser Nutzer in der Testgruppe? Stimmt die Region? Wird das Traffic-Prozent erreicht? Sie müssen diese Logik nicht jedes Mal neu schreiben, wenn Sie das Flag verwenden.

Den Code sauber halten

Je mehr Flags Sie hinzufügen, desto mehr bedingte Zweige entstehen in Ihrem Code. Ohne Disziplin enden Sie mit verschachtelten if-Anweisungen, die schwer zu lesen und noch schwerer zu warten sind.

Ein paar Prinzipien helfen:

Ein Flag, eine Verantwortung. Stopfen Sie nicht mehrere Bedingungen in ein einzelnes Flag. Wenn Sie die Sichtbarkeit nach Region und nach Nutzerrolle steuern müssen, verwenden Sie zwei separate Flags. Das ist klarer und später leichter zu entfernen.

Flags auf der richtigen Ebene platzieren. Setzen Sie das Flag so nah wie möglich am Einstiegspunkt der Funktion. Bei einer UI-Komponente ist das die Render-Funktion. Bei einem API-Endpunkt ist es der Handler. Vermeiden Sie es, dasselbe Flag über mehrere Ebenen Ihres Codes zu streuen.

Planen Sie die Entfernung des Flags. Jedes Flag, das Sie hinzufügen, ist temporärer Code. Wenn die Funktion vollständig ausgerollt ist, entfernen Sie den alten Codepfad und das Flag. Schreiben Sie Ihre Flags so, dass sie leicht zu finden und zu löschen sind. Gruppieren Sie zusammengehörige Flags. Verwenden Sie konsistente Namen wie featureX_enabled oder featureX_percentage.

Eine praktische Checkliste

Bevor Sie Ihr nächstes Feature Flag schreiben, gehen Sie diese Punkte durch:

  • Kann diese Funktion mit einem einfachen booleschen Wert gesteuert werden, oder brauchen Sie bedingte Logik?
  • Woher kommt der Flag-Wert? Hardcoded, Konfigurationsdatei, Umgebungsvariable oder entfernter Dienst?
  • Ist das Flag auf der richtigen Ebene platziert, nahe der Stelle, wo die Funktion verwendet wird?
  • Hat das Flag eine einzige, klare Verantwortung?
  • Haben Sie geplant, wie Sie das Flag und den alten Codepfad später entfernen?

Was als Nächstes kommt

Sobald Ihr Flag im Code ist, stellt sich die nächste Frage: Wie ändern Sie seinen Wert, ohne neu zu deployen? Sie brauchen eine Möglichkeit, Flags fernzusteuern – sei es über eine Konfigurationsdatei, die neu geladen wird, über aktualisierte Umgebungsvariablen oder über ein dediziertes Dashboard. Hier zeigt sich die wahre Stärke von Feature Flags: Sie können Funktionen an- und ausschalten, schrittweise ausrollen und auf Probleme reagieren, ohne die Deployment-Pipeline anzufassen.

Aber das alles nützt nichts, wenn Ihre Flags chaotisch sind. Beginnen Sie mit sauberen, gut platzierten Flags in Ihrem Code. Der Rest ergibt sich daraus.