Archivi tag: Architetture

Firebase

Architetture web two-tier

Esiste un approccio standard per realizzare applicazioni web,  che tutti noi, nerd programmatori, abbiamo imparato ad utilizzare negli anni senza discutere. Si tratta dell’architettura three-tier, che consiste in: una parte di presentazione, che gira sul client ed è solitamente realizzata in html/css con qualche spruzzata di javascript; una parte di business logic, che gira sul server e viene realizzata nella gran parte dei casi in Java EE, ma anche in Python, Node.js e, perché no, il caro vecchio PHP; una parte di storage, ovvero un database relazionale MySQL, Oracle (se il cliente ha soldi da spendere), Postgres, fino ai più recenti database NoSQL (Not only SQL).

La tecnologia avanza, le mode cambiano ma, spesso, a cambiare sono soltanto i linguaggi o i prodotti utilizzati in ognuna delle tre parti dell’applicazione. Suddividere logicamente un’applicazione in livelli distinti, anche più di 3 livelli, è qualcosa di naturale e utile. Suddividere fisicamente un’applicazione in 3 componenti sviluppate separatamente con linguaggi e tecnologie diverse… dipende !

È possibile fare a meno di tutta questa complessità e realizzare un’applicazione web a singolo strato ? La risposta, ovviamente, si chiama html, css, javascript e Web Storage oppure Indexed DB. Le ultime due tecnologie servono a colmare il gap, sempre esistito, tra applicazione desktop e applicazione web, permettendo il salvataggio di dati su un’area di storage privata del proprio browser. L’applicazione, così, non ha proprio bisogno di server, ovvero, potrebbe essere distribuita attraverso un web server che si occupa di fornire i soli asset statici, ma il server non conterrebbe alcuna logica applicativa. Altro metodo di distribuzione di applicazioni web singolo strato è l’app mobile: sono sempre più diffuse le app Android che constano solamente di una WebView che visualizza il contenuto html5 fornito in bundle con l’app.

Il problema è che questo tipo di approccio non consente di realizzare applicazioni web che possano essere universalmente ritenute tali. Si tratta, più che altro, di un ottimo metodo per realizzare applicazioni cross-platform, spesso mobile, con delle tecnologie standard. In applicazioni del genere, la condivisione delle informazioni con il resto del mondo (comprese postazioni di lavoro diverse dello stesso utente) è quasi impossibile. Ma se sostituissimo il Web Storage, o l’Indexed DB con uno storage esterno ?

Dopo mille parole di premessa, arrivo al punto: Firebase, uno strumento (gratuito, per piccole applicazioni) che nasce come servizio utile a semplificare di almeno 10 volte lo sviluppo di applicazioni web. Ed è davvero così !

Si tratta di nient’altro che un database cloud NoSQL utilizzabile da molti linguaggi diversi, compreso, ovviamente javascript. Sul sito ufficiale parlano di Node.js ma, utilizzandolo così, torniamo all’architettura a 3 strati classica. Dopo la procedura di registrazione e la creazione di un database privato sul sito di Firebase, l’integrazione prevede qualche semplice passaggio.

Importare lo script di integrazione al servizio:

<script src="https://cdn.firebase.com/js/client/1.0.6/firebase.js"></script>

A questo punto, basta creare un oggetto che consenta il collegamento al servizio remoto di Firebase.


var firebaseStorage = new Firebase('https://il-mio-db.firebaseio.com/');

Il database è un tipico NoSQL document oriented, senza schemi, né vincoli, che può essere utilizzato con oggetti JSON come file di interscambio. Le funzioni per operazioni CRUD sui dati sono molto semplici da imparare, una volta capita la struttura.


// Modificare un documento esistente (creandolo, se non esiste)
firebaseStorage.child("percorso/al/documento").set({name: "Ciccio", type="Human"});

// Inserimento di un documento con un id creato da Firebase
var obj = {text: "Hello world"};
var location = firebaseStorage.child("home/documents");
var id = location.push().name();
obj.id = id; // salvo l'id all'interno del contenuto del documento stesso (tipico in contesti NoSQL)
location.child(id).set(obj); // Inserisco

// Cancellazione di un documento
firebaseStorage.child("home/documents/ilmioiddeldocumento123").remove();

// Recupero di un documento (sempre asincrono)
firebaseStorage.child("home/documents/doc123").once("value", function(documentRef) {
var document = documentRef.val();
alert(document);
});

// Recupero di un insieme di documenti (sempre asincrono)
firebaseStorage.child("home/documents").once("value", function(documentsRef) {
documents = documentsRef.val();
});
// Ovvero uguale a prima, ma nella posizione home/documents ci sono più figli

// Ricevere (in real time) una notifica quando qualche altro utente modifica un dato
firebaseStorage.child("home/documents/xxx123").on("value", function(documentChangedRef) {
//...
});
// Ovviamente, si spegne con off(...)

// Query .. si può ..

Il numero di funzioni è sufficiente per sostituire in toto un server di backend di tipo CRUD e non solo. Firebase supporta anche, come visto, la comunicazione real-time dei cambiamenti sui dati ai browser collegati e le transazioni (al contrario di molti altri prodotti NoSQL).

Veniamo al nodo cruciale: sicurezza. Dovendo semplificare al massimo lo sviluppo dell’applicazione web, firebase ha al suo interno dei moduli di sicurezza oAuth configurabili (es. Facebook login, twitter) e supporta anche la registrazione mediante username e password con verifica tramite email. Una volta configurato un sistema di autenticazione, e integrato questo all’interno dell’applicazione web, si possono impostare dei criteri di sicurezza per l’accesso ai dati, direttamente nella console di amministrazione.

{
"rules": {
"home": {
"$user": {
".read": "$user == auth.uid",
".write": "$user == auth.uid"
}
}
}
}

Con la configurazione precedente, ho indicato che solo l’utente con un un certo UID (unique identifier, fornito dal sistema di autenticazione di firebase, può accedere al percorso “home/{uid-utente}” in lettura o scrittura. Ho creato così, una cartella privata. Al momento della creazione, il database viene configurato perché chiunque possa scrivere e leggere i dati in qualsiasi posizione, anche gli utenti senza autenticazione.

Si può configurare il servizio in modo da creare delle posizioni condivise tra utenti specifici. La configurazione non è complessa ma richiede un po’ di lavoro aggiuntivo.

Conclusioni

Creare un’architettura web a due strati, eliminando completamente il livello di logica applicativa lato server è possibile e, per alcune tipologie di applicazioni, anche auspicabile.

Spesso realizziamo diversi moduli Java EJB, con livelli di persistenza per il mapping ORM, con una serie infinita di classi e interfacce per… fare semplici operazioni CRUD sui dati. In queste occasioni, un pensiero alla possibilità di eliminare completamente il server è d’obbligo.

In particolare, per quel tipo di applicazioni di tipo SaaS, in cui l’utente ottiene un servizio dall’applicazione e, per nessun motivo al mondo, cercherebbe di fare un “tamper” dell’applicazione al fine di corrompere i dati, va assolutamente bene.

Se, invece, l’integrità dei dati è fondamentale per l’applicazione, un approccio del genere sarebbe sicuramente dannoso per la buona riuscita del progetto.