giovedì 23 febbraio 2012

Pensare in REST (Thinking in REST)

La progettazione di applicazioni Web based ha subìto una silenziosa rivoluzione quando nel 2000 Roy Fielding ha pubblicato la sua ormai celebre dissertazione dal titolo: "Architectural Styles and the Design of Network-based Software Architectures", e in particolare il capitolo cinque: "Representational State Transfer (REST)".

In cosa consiste questa rivoluzione? Esiste una modalità, diciamo così, "classica" di concepire un'applicazione per computer, e questa prevede la composizione di un algoritmo più o meno complesso che prende in input una serie di dati, li trasforma e poi li rende persistenti - ad esempio salvandoli su un database. L'essere umano interagisce con l'applicazione attraverso una "interfaccia utente" che viene aggiornata a seconda del cambiamento di stato - o dell'input o dell'output. Così, in modo appunto "classico", un'applicazione è costituita di un'interfaccia utente, una logica, e uno stato - cioè dei dati persistenti.

Le prime applicazioni Web complesse, rese possibili dalle primigenie tecnologie di trasformazione dinamica dell'HTML, lato server con ASP o PHP ad esempio e lato client con DOM/Javascript, implementavano questo modello classico. Vale a dire, presentavano all'utente un'interfaccia grafica con la quale inserire i dati, offrivano una serie di comandi associati a una logica di esecuzione, e infine persistevano i risultati su un database.

Il problema di questo approccio è che l'applicazione diventa un monolite che si può utilizzare solamente nel modo in cui è stata inizialmente concepita.

Con l'aumentare delle necessità di servizi Web, con l'aumentare dei device eterogenei che vi accedono - dai computer ai telefonini, dai videogiochi alle lavastoviglie - questo tipo di approccio è diventato controproducente: l'applicazione monolitica impedisce di utilizzare i dati e le informazioni che è in grado di veicolare appunto perché è concepita per essere utilizzata in un solo modo, che è quello inizialmente concepito dai suoi autori. La conseguenza di tutto ciò è che ogni nuova esigenza di accedere ad un dato o ad un servizio veicolato dall'applicazione necessita di un cambiamento nel codice applicativo o, peggio, nella creazione di una nuova applicazione ad hoc.

Oggi le aziende spendono moltissime risorse IT proprio perché hanno a che fare con applicazioni monolitiche che non riescono a "servire" il dato in maniera abbastanza neutra.

L'idea alla base del protocollo REST inventato da Roy Fielding è che le applicazioni Web devono essere progettate in modo tale per cui immettendo direttamente le URL (che così diventano URI) su un browser si ottengano immediatamente i dati che servono, e che queste URL possano essere "combinate" tra loro in un workflow per ottenere un'applicazione, allo stesso modo con cui nelle architetture SOA noi combiniamo i "servizi" per ottenere sempre nuove applicazioni.

La URL così richiamata deve essere in grado di rispondere in formato "neutro", possibilmente veicolando solamente "i dati", senza cioè alcuna informazione "grafica" di supporto. Le URL stesse devono specificare il formato dei dati che richiedono: se la URL finisce per ".xml" il dato verrà restituito in XML, per ".json" in JSON, e, naturalmente, di default rispondere con un HTML human readable.

Per finire un esempio. Supponiamo di scrivere un videogioco Web, magari per Facebook. Avremo da qualche parte una struttura dati che prende tutte le informazioni relative al giocatore (Player). Questa struttura dati raccoglie e persiste lo "stato" del giocatore durante il gioco. La modalità classica consiste nello scrivere un'applicazione che, a seconda dei comandi dati via web dal giocatore, cambia lo stato e aggiorna di conseguenza la tabella "Player". Esagerando, l'applicazione potrebbe essere costituita da un'unica "pagina" che, a seconda del comando HTTP ricevuto, risponde in un modo o in un altro. Ovviamente, così facendo, nessuno, ad esempio, potrebbe costruire un altro gioco a partire dai dati correnti dei giocatori: perché le informazioni di stato dei giocatori sono "chiuse", e utilizzabili solo dalla "pagina" di cui parlavamo prima.

Se volessimo applicare il protocollo REST all'entità "Giocatore" (Player), come prima cosa dovremmo definire le "URL" che accedono a ciascuna informazione del giocatore, e le URL che vanno a modificare lo stato del giocatore stesso. Ad esempio:

GET    /player/list(.:format)        player#list
POST   /player/list(.:format)        player#list
GET    /player(.:format)             player#index
POST   /player(.:format)             player#create
GET    /player/new(.:format)         player#new
GET    /player/:id/edit(.:format)    player#edit
GET    /player/:id(.:format)         player#show
PUT    /player/:id(.:format)         player#update
DELETE /player/:id(.:format)         player#destroy

Questa tabella fornisce un verbo HTTP e una URL associata. Queste URL, se chiamate con il rispettivo verbo HTTP, sono già in grado di descrivere le funzionalità di base con cui l'utente può ottenere le informazioni sui giocatori! La prima fornisce una lista dei giocatori, la seconda modifica la lista, la terza ottiene informazioni generiche, la quarta e la quinta inseriscono nuovi giocatori, la sesta permette di modificare i dati di uno specifico giocatore e via dicendo...

Se chiamo /player/list ottengo una pagina HTML, /player/list.json un array di giocatori, /player/list.xml un documento XML. Applicazioni sempre diverse accedono agli stessi dati in maniera omogenea. In questo modo, se l'applicazione è ben scritta, sarà sempre possibile immaginare nuovi modi per accedere ai dati, e produrre applicazioni nuove senza dover modificare il codice lato server.

Chiaramente, progettare un'architettura Web in modalità REST comporta un ribaltamento del modo di pensare: invece che partire dalle esigenze "funzionali", bisogna partire dai dati, e dal modo con cui si può manipolarli. Ma il vantaggio di farlo fin dall'inizio, con disciplina, produrrà significativi risparmi nella gestione evolutiva dell'applicazione, e darà l'opportunità di costruire nuovi modi d'uso di applicazioni esistenti praticamente senza sforzo.

Oggi esistono molti framework che producono applicazioni Web RESTful. Il più famoso è "Ruby On Rails". Seguono "Bowler" per Scala, "Jersey" per Java. E molti altri stanno nascendo.


1 commento:

Anonimo ha detto...

Bell'articolo. Complimenti