Di fuoco: Rendere la configurazione remota di Firebase un po’ più confortevole

Il nuovo Firebase è stato rilasciato durante il Google I/O 2016, e una delle caratteristiche chiave si chiama Firebase Remote Config . Permette di sperimentare all’interno della propria app e di spedire più velocemente con meno rischi. Può essere utilizzato come telecomando asincrono nelle vostre app. E abbiamo aperto la nostra Firely Facade per facilitarne l’uso.

Firebase Remote Config

Il Remote Config è un archivio di configurazione di coppie di valori chiave che può essere sincronizzato con i dispositivi. E si possono applicare condizioni su tali configurazioni per distribuire valori diversi a seconda di molti criteri: paesi, lingue, nomi di pacchetti, pubblico, percentuale casuale di utenti…

Remote Config è ottimo per :

  • Test A/B
  • Configurazione remota
  • Bandiere caratteristiche

Integrazione di Firebase Remote Config

Questo è davvero facile e non è lo scopo di questo post del blog, ma è possibile trovare tutorial completi e esempi di app walkthrough su Firebase Remote Config Android Sample App Walkthrough

In Sapsbus, usiamo molto la configurazione remota Firebase Remote Config e soprattutto per i test A/B. Inizialmente abbiamo integrato Remote Config in modo molto semplice nell’applicazione, ma dopo alcuni mesi di utilizzo, abbiamo visto emergere dei modelli dall’uso di Firebase Remote Config: l’impronta nel codice non era così leggera . E non era decisamente ASCIUGATA.

Immaginiamo di voler integrare un flag di funzionalità (on/off) utilizzando Firebase Remote Config, da zero.

La configurazione di Firebase Remote Config è abbastanza semplice:

  • Per prima cosa è necessario integrare l’SDK (una riga di codice nel file dei gradini)
  • Poi è necessario inserire i propri valori predefiniti in un file XML
  • Poi è necessario impostare la propria istanza in un luogo che abbia un senso e che non faccia andare in crash Firebase (abbiamo incontrato qualche problema con il classico “FirebaseApp non è inizializzata”)
  • Poi bisogna chiamare il metodo asincrono fetch in un luogo che abbia senso, ad un ritmo che abbia senso
  • Poi è necessario creare una chiave per ogni voce che si ottiene nella configurazione remota
  • Poi bisogna collegarlo al proprio Tracking perché si sta usando qualcosa di diverso o in aggiunta a Firebase Analytics
  • ecc…

In realtà, si finisce per avere un po’ più di codice di quello che si era prefissato, quando tutto quello che si voleva veramente scrivere era:

Articolo molto interessante
Sapsbus raccoglie $1M Round

12345if (FirebaseRemoteConfig.isMyFeatureFlagOn(MyFeatureFlag)) {/// Facciamo così} altrimenti {/// Facciamo così}

Cosa ci serviva

Dopo poche iterazioni, volevamo qualcosa che:

  • È più semplice da configurare, definendo le chiavi e il loro valore di default una volta sola
  • È sicuro durante la rimozione dei test A/B: l’applicazione non dovrebbe compilare se rimuovo una chiave dalla mia configurazione iniziale (il che aiuta a ripulire i test A/B molto facilmente)
  • Fornito un comportamento ragionevole per il recupero della configurazione e il tempo di applicazione con la nostra applicazione
  • Ha metodi statici ovunque (o integrati con Dagger+2)
  • È indipendente dal tracciamento

Abbiamo finito con una libreria piccola e leggera chiamata Firely .

.
Niente di rivoluzionario qui, ma solo una facciata più bella, la nostra versione comoda di Firebase Remote Config.

Come funziona la Facciata Incendiata

Questa biblioteca, integrata nel vostro progetto di laurea, richiede solo:

  • Un file firely-config.json che contiene il tipo di elementi, le chiavi e il valore di default
  • Una chiamata a Firely.setup(Context context) dal metodo Application.onCreate()
  • Una regola proguardia

firely-config.json è organizzato in 3 sezioni principali (per noi, ma può avere i “nomi” che volete):

  • Caratteristica Bandiere
  • Configurazione
  • Esperimenti (o test A/B)

Ecco un esempio di firely-config.json:

{
 "configurare": [
 {
 "chiave": "android_version_code_min",
 "default": 0
 }
 ],
 "feature_flag": [
 {
 "chiave": "refer_a_friend",
 "default": vero
 },
 {
 "chiave": "promozione_url",
 "default": ""
 }
 ],
 "esperimento": [
 {
 "chiave": "xp_button_pay",
 "default": "controllo"
 }
 ]
}

Firely è una libreria Android che viene fornita con un plugin per gradini, firely-plugin. Genera un file FirelyConfig.java basato sul file firely-config.json, come l’androide R.java crea. Il file FirelyConfig.java conterrà Enum che corrispondono alla configurazione. Si possono quindi usare questi enum su Firely per ottenere LiveVariable, CodeBlock, OrderedArrayBlock.

LiveVariabile

Immaginiamo che io stia usando Remote Config per limitare il mio utente ad una versione minima di Android su cui può girare (altrimenti deve aggiornare l’app). Con Firely, posso istanziare una LiveVariable che utilizzerà questa impostazione:

LiveVariable<Integer> minAndroidRemoteVersion = Firely.integerVariable(FirelyConfig.Config.ANDROID_VERSION_CODE_MIN);

FirelyConfig.Config.ANDROID_VERSION_CODE_MIN viene generato dal plugin e il valore predefinito è 0.

Ora, ogni volta che ho bisogno di ottenere l’ultima versione che è stata recuperata, mi basta chiamare:

Integer lastVersion = minAndroidRemoteVersion.get();

Ecco un altro esempio con un flag di funzionalità:

123if (Firely.booleanVariabile(FirelyConfig.FeatureFlag.REFER_A_FRIEND).get()) {// Aggiungi la vista}

CodeBlock

Ora devo costruire un XP che cambierà il testo di un pulsante.

Firely.codeBlock(Remote.Experiment.XP_BUTTON)
	.conVariant("valuta_fatturata", "no_prezzo")
	.eseguire(
	() -> advance.setText(getString(R.string.bb_payment_cta)), // controllo
	() -> advance.setText(.getString(R.string.bb_payment_cta_2)), // valuta_fatturata
	() -> advance.setText(getString(R.string.bb_payment_cta_3))); // no_price

NOTA: utilizziamo sempre “controllo” come valore di default e come gruppo di controllo per i test A/B.

OrderedArrayBlock

Nella Sapsbus Android App, usiamo molti blocchi e liste. Immaginiamo di avere N blocchi di dati in una pagina.

Articolo molto interessante
Da Rio de Janeiro a Florianópolis in autobus

Si vuole testare A/B quale deve andare per primo e l’ordine per tutti gli altri.
Un approccio di base potrebbe essere quello di avere N! varianti.

Se abbiamo tre oggetti: 1-2-3, 2-1-3, 2-3-1, 1-3-2, 3-2-1, 3-1-2

E mentre si usano i CodeBlocks:

Firely.codeBlock(Remote.Experiment.XP_BUTTON)
	.conVariante("2-1-3", "2-3-1", "1-3-2", "3-2-1", "3-1-2")
	.eseguire(
	() -> {
		addOne();
		addTwo();
		addThree();
	}, // controllo
	() -> {
		addTwo();
		addOne();
		addThree();
	},
	... ecc.

Davvero inefficiente.

Un altro approccio è quello di utilizzare OrderedArrayBlock. Si utilizzerà una sola voce della Firebase:

{
 ...
 "esperimento": [
 {
 "chiave": "xp_mypage_order",
 "default": "uno, due, tre"
 }
 ]
}
OrderedArrayBlock mCheckoutXp =
		Firely.orderedArrayBlock(FirelyConfig.Experiment.XP_CHECKOUT_ORDER)
			.addStep("one", () -> addOne())
			.addStep("due", () -> addTwo())
			.addStep("tre", () -> addThree());

E potete controllare i vostri A/B Tests dal cruscotto di Firebase Remote Config cambiando il tasto xp_mypage_order.

tre,uno,due chiamerà poi addThree(), addOne(), addTwo(). Si può usare questo per controllare a distanza l’ordine delle liste.

Analisi

Uno dei punti salienti di Firebase è che tutto funziona insieme. Nella documentazione, Firebase propone di inserire i valori, manualmente, come proprietà dell’utente:

String experiment1_variant = FirebaseRemoteConfig.getInstance().getString("experiment1");
 AppMeasurement.getInstance(context).setUserProperty("MyExperiment",experiment1_variant);

È bello, ma non si adatta alle nostre esigenze. Mettere la proprietà a livello dell’utente significa che verrà cancellata nel tempo e perderemo le informazioni. Invece, preferiamo etichettare tutti gli eventi con tutti gli esperimenti che sono stati applicati nel momento in cui l’evento viene attivato.

Abbiamo aggiunto un metodo su Firely per aiutare in questo:

Firely.getAllPropsWithCurrentValue()

E questo metodo è chiamato ogni volta che inviamo un evento e si fonde nella lista delle proprietà.

Pertanto possiamo tenere traccia delle modifiche di configurazione nel tempo.

Profondità di fuoco

Firely è davvero semplice e contiene:

  • Il plugin groovy gradle, che è veramente semplice
  • La libreria Firely Java

Uno dei problemi chiave che abbiamo attualmente è determinare il momento migliore per FirebaseRemoteConfig.fetch() e seguire con FirebaseRemoteConfig.activateFetched() sulla locale Firebase Remote Config. E decidere anche la cacheExpiration.

Per vostra comodità, ecco come funziona Firebase Remote Config:

Firely è molto semplice. È collegato al registerActivityLifecycleCallback e recupera la configurazione solo quando l’utente utilizza l’app in modo attivo (cioè aprendo/chiudendo le schermate – se l’utente ha un’app che non ha un componente di attività, accettiamo contributi ).

FirebaseRemoteConfig.fetch() viene chiamato in onResume() e, in caso di produzione, la scadenza della cache è impostata a 0 fino a quando non si ottiene effettivamente una configurazione e poi è impostata a 1 ora. Per la cronaca, Firebase permette di fare 5 richieste all’ora per una data app. L’INITIAL_CHECK con la scadenza della cache a 0 viene resettato ogni volta che la vostra app viene aggiornata, per forzare l’ultima configurazione ad essere utilizzata il più velocemente possibile.

Articolo molto interessante
In viaggio per l'All-Star Game NBA 2016 a Toronto

FirebaseRemoteConfig.activateFetched() è un po’ più complesso perché volevamo travisare per l’analisi (non si vogliono inviare proprietà che non riflettono ciò che viene utilizzato nell’app) e che hanno senso come utente. Non si vuole che i propri utenti navighino in avanti attraverso l’app e poi scoprano mentre cercano di tornare indietro che ora si trovano in un’altra variante dello schermo che si aspettavano di trovare. Per fornire un’esperienza più stabile agli utenti, abbiamo deciso di FirebaseRemoteConfig.activateFetched() una volta che il task di root è stato distrutto, quindi la configurazione verrà applicata al prossimo lancio. Il motivo è che la nostra app si basa su un unico Task of Activities. Questo potrebbe non essere adatto a tutti i progetti.

Ma quando si sviluppa, si vuole che il fetch sia attivato il prima possibile. In debugMode, il FirebaseRemoteConfig.activateFetched() viene chiamato in onPause().

E questo è più o meno tutto!

Firely – cosa c’è dopo?

Si tratta di un primo taglio approssimativo, e l’idea alla base della biblioteca Firely è quella di mantenerla leggera e aperta.

Qui ci sono alcune idee:

  • Migliorando il FirebaseRemoteConfig.activateFetched() e il modo in cui può essere garantita la coerenza tra la variabile a cui si accede e ciò che viene inviato alle API di Analytics.
  • FirelyTextView per modificare automaticamente il contenuto del testo?
  • FirelyImageView : lo stesso con l’integrazione di tipo Picasso per poter caricare immagini remote
  • Avere la nozione di portata su un LiveVariable per essere sicuri che la configurazione non cambierà durante la vita dell’Attività / Presentatore / Frammento / Applicazione…

Un’ultima parola

Ci sono voluti circa 2 o 3 giorni di lavoro di sviluppo per trovare una soluzione che si adattasse meglio alle nostre esigenze.
Ci sono molte soluzioni complesse che esistono sul mercato, ma Firebase Remote Config è una di quelle che è quasi libera.

E mentre la configurazione remota di Firebase Remote Config è piacevole, potreste aver bisogno di qualcosa di più comico e di più asciutto per il vostro lavoro quotidiano. Non c’è niente di sbagliato nel rendere la vostra vita più facile, quindi provate Firely.

Potete trovare il codice open-source su github.

Fonte: Sapsbus engineering

Lascia un commento