Seleziona una pagina

Oggi voglio parlarti dei Feature Flags, una metodologia di lavoro che puoi applicare a qualsiasi linguaggio di programmazione e che aumenterà di molto la qualità di quanto produci se non la utilizzi già. Tuttavia, lavorando in Android, la caleremo in questo contesto con esempi pratici. Esempi che potrai riportare facilmente anche in altri linguaggi.

Ne approfitto per ringraziare il nostro super mobile manager Andrea Mengoli 🙂 che ci ha proposto di utilizzarli sul nostro progetto e ci ha spronato a farci avanti nel portare questo argomento alla scorsa droidcon, la conferenza su Android italiana.

Abbiamo infatti parlato all’evento extra riguardo i Feature Flags, cosa sono, come utilizzarli con Android e soprattutto come avere un approccio funzionale in modo che la nostra applicazione reagisca in modo reattivo a questi Feature Flag.

In questo articolo voglio riassumere i contenuti di quell’intervento in italiano in modo che se hai difficoltà con l’inglese puoi comunque portarti a casa i punti chiave. Altrimenti, puoi vedere qui l’intervento integrale:

Se poi vuoi approfondire ulteriormente l’argomento, puoi leggere l’ottimo articolo di Martin Fowler al riguardo.

Cosa sono i Feature Flags

Partiamo dal cosa sono e del perché dovresti proprio utilizzarli nel tuo progetto. I Feature Flag sono un modo per creare delle funzionalità in modo condizionale all’interno del tuo progetto.

A un livello molto base, i feature flag sono qualcosa di questo genere:

if (flag == true) {
    // enable feature and have fun
} else {
    // reload old ui
}

Questa tipologia di Feature Flag è statica. Quello che vuol dire è che il comportamento è scritto nella pietra e non si può cambiare. Se flag è una variabile settata a true e l’app viene compilata, sarà sempre true.

A un secondo livello, possiamo rendere questa valutazione dinamica. In modo semplice, verrà qualcosa di questo genere:

if (isFeatureFlag(ENABLE_MULTI_ZONE)){
    // enable feature and have fun
} else {
    // reload old ui
}

Definiamo dunque una funziona isFeatureFlag che ha lo scopo di andare a caricare dalle preferenze o anche da un file XML le impostazioni del flag.

A un terzo livello ancora, possiamo rendere il tutto reattivo. Ovvero, potremmo definire un repository con un flow (un emettitore di eventi) e agganciarci a questo flow per reagire in modo coerente con quanto sta succedendo.

scope.launch {
    flow.collect { flag ->
        if (flag == true) {
            // enable feature and have fun
        } else {
            // reload old ui
        }
    }
}

In questo modo possiamo cambiare dinamicamente il valore di questo flag e senza dover reinstallare o ricaricare l’app, questa reagisce e ridisegna la UI o abilita una certa funzionalità piuttosto che disabilitarla.

Quali sono i vantaggi dei Feature Flags

i feature flag ti permettono di fare A/B testing

I Feature Flags sono qualcosa di molto utile che semplifica il lavoro degli sviluppatori specialmente quando parliamo di sviluppare funzionalità nuove in parallelo.

In particolare, ti permettono infatti di abilitare o disabilitare una funzionalità. Questo dunque permette a due sviluppatori di lavorare su due funzionalità nuove sullo stesso branch. Portando a casa per entrambi i miglioramenti sulla codebase comuni ma allo stesso tempo visualizzare l’applicazione senza alterazioni quando la funzionalità dell’altro sviluppatore è disattivata. Questo ti permette di lavorare senza regressioni e senza funzionalità incomplete che potrebbero rallentare o impedire gli sviluppi della nuova funzionalità.

Un altro vantaggio è la possibilità di fare A/B testing di nuove funzionalità. Ovvero dare ad alcuni utenti l’applicazione con un flag a true mentre ad altri con il flag a false. Questo ti permette di provare nuove interfacce in produzione con solo una ristretta popolazione di utenti. Lo stesso può valere per nuove funzionalità. In modo da poterle anche spegnere in caso di problemi.

Inoltre è anche possibile dare un’unica applicazione ai tester che quindi possono abilitare selettivamente solo le funzionalità che vogliono testare. Senza avere parti dell’applicazione instabili perché le funzionalità in sviluppo non sotto test sono spente. Questo ci permette di fare del testing in modo isolato senza dover per forza testare sempre tutto.

la linea dei nuovi robot Neato Robotics
La linea di robot D8, D9, D10

Per noi inoltre è cruciale perché abbiamo una multitudine di robot che l’app deve supportare. E i vari robot sono diversi sia come funzionalità che come scopo di utilizzo e molti altri arriveranno presto sul mercato. Questo ci permette quindi di avere un’app dinamica che a seconda del robot che è selezionato si riconfigura e permette all’utente di utilizzare le funzionalità specifiche di quel robot.

Un altro grande vantaggio è la possibilità di fare Continuous Delivery e Continuous Integration. Proprio perché possiamo sempre mergiare in master le modifiche man mano che vengono sviluppate senza avere dei branch di epica lunghi mesi con poi grande sofferenza nel fare merge alla fine. E allo stesso tempo possiamo rilasciare ogni settimana avendo tutte le funzionalità “protette” dietro questi feature flag disabilitati di default. Quindi ogni settimana rilasciamo una candidate interna che il nostro team di test valida e ci apre eventuali bug e regressioni.

Ma usare i branch come tutti no bro?

il branching per fare sviluppo di prodotto

L’usare i branch potrebbe essere una scelta molto intelligente in due casi:

  • devi fare un proof of concept quindi non sai se il codice su cui stai lavorando verrà effettivamente mergiato oppure no. Quindi per evitare di mischiarlo con il codice “ufficiale” può aver senso lavorarci a parte in un branch dedicato. E’ anche vero che spesse volte rimuovere il codice dei feature flag è abbastanza semplice, quindi sarebbe da valutare caso per caso.
  • devi fare un refactor importante e quindi preferisci tenere una funzionalità che comunque funziona in master e lavorare in un branch dedicato a questo refactor. E nel mentre aprire PR piccole che puntano a un branch di epica per permettere ai tuoi colleghi di fare review senza che ti inseguano armati di coltelli 🙂

In tutti gli altri casi è possibile usare il branching ma è generalmente una pratica svantaggiosa in termini sia di tempo di sviluppo che di tempo perso nel fare merge che poi in generale anche di gestione e possibile creazione di bug.

Ci sono degli svantaggi?

gli svantaggi dei feature flags

In realtà molto pochi, principalmente il fatto che è sconveniente avere molte funzionalità in parallelo. Per cui bisogna stare molto attenti a cancellare eventuali Feature Flag che non servono più sia dal codice che dalla lista dei Feature Flag. Inoltre, più hai Feature Flag più hai possibili versioni dell’app che vanno sia testate che mantenute. Quindi può crescere esponenzialmente il costo di manutenzione di questa pratica.

Con il branching invece ogni branch o va o non va, quindi non hai molte possibili combinazioni da testare.

E’ vero che comunque queste problematiche in più di un anno sono state davvero lievi nel nostro caso e solo raramente ci sono stati problemi o bug reali.

Conclusioni

Spero di averti incuriosito con questa tematica e se vuoi approfondirla in dettaglio incluso come implementarli su Android ti consiglio di guardare il nostro talk al riguardo che, per semplicità, ti rimetto qui sotto:

Se non vuoi perderti altri miei/nostri articoli su Android, ti invito a seguirmi su instagram e non perderti i prossimi aggiornamenti 🙂 se hai dubbi, scrivili pure qui sotto nei commenti. A presto!