Il panorama delle tecnologie e dei modelli architetturali delle applicazioni web è cambiato molto negli ultimi anni. Le nuove tecnologie e i vari framework permettono di realizzare applicazioni ad alto valore aggiunto e in cui il livello di interazione con l’utente è notevolmente aumentato rispetto a una classica applicazione web della generazione precedente. Tramite il modello Rich Internet Application è possibile realizzare applicazioni web il cui comportamento è molto simile a quello di una applicazione stand-alone desktop. Ma il proliferare di applicazioni di questo genere introduce una serie di aspetti legati a problematiche tecnologiche, architetturali e anche mentali.
Dal giorno della sua prima definizione, ad opera di Macromedia nel 2002, il termine di Rich Internet Application è divenuto uno dei più usati e abusati sul web; da allora nuove tecnologie e nuovi modelli di programmazione si sono avvicendati sullo scenario con l’obiettivo, fra le altre cose, di aumentare la potenza e l’interattività delle GUI delle applicazioni al fine di far si che la cosiddetta user experience fosse paragonabile a quella di una comune applicazione desktop. Probabilmente l’invenzione di Ajax (anche se a volte mi piace usare il termine “scoperta” visto che la nascita di questa tecnologia è stata più o meno casuale grazie all’uso sapiente di alcuni coponenti JavaScript già presenti nei vari JSEgine dei corrispettivi browser) ha rappresentato il “boost” principale per la diffusione di sempre nuove e migliori tecnologie dalla interfaccia ricca.
L’obiettivo di questo articolo non è tanto quello di analizzare dettagliatamente le principali tecniche, linguaggi, framework di programmazione per fare RIA, quanto piuttosto quello di proporre un confronto fra le principali caratteristiche di una applicazione web e una RIA, prendendo in considerazione sia aspetti tecnologici che più prettamente operativi.
Per addentrarci all’interno di questa trattazione comparativa può essere utile fare un breve ripasso delle terminologie e concetti di base che ci hanno accompagnato in tutti questi anni.
L’evoluzione del modello di programmazione delle applicazioni web
Partendo dall’idea originaria di web proposta da Tim Berners Lee, la maggior parte del lavoro fatto nell’area delle web application ha avuto come obiettivo quello di far evolvere il modello statico del www della prima ora verso un meccanismo dinamico e application based (i contenuti non sono più semplicemente prodotti e “stampati” con un qualche tool, ma sottostanno a precise funzioni di business). Questo processo evolutivo è stato in più modo classificato e dettagliatamente descritto; limitatamente al mondo delle web application una possibile classificazione si basa sul modello organizzativo e architetturale delle applicazioni stesse.
Model 1
Produzione diretta di pagine ipertestuali che permettono la visualizzazione di dati in modo dinamico. La navigazione è realizzata tramite link diretti fra le varie pagine.
Model 2 o MVC
Nel Model 2, in pratica il pattern architetturale Model View Controller, i link non mettono in contatto direttamente le varie pagine, ma la navigazione viene mediata e configurata grazie all’introduzione di un controller che permette di centralizzare le operazioni di controllo per ogni cambio pagina a di eseguire in questo caso le varie operazioni di business logic.
MVC basato su componenti
Alcuni autori parlano anche di Model 3 per questo modello che rappresenta una evoluzione del modello precedente in cui la parte di rappresentazione dei dati (View) viene realizzata grazie a sofisticati e potenti framework a componenti dentro i quali è possibile inserire della logica di traduzione, validazione e limitatamente anche di business. Tali framework spesso introducono la possibilità di abilitare un modello a eventi e, dal punto di vista dello sviluppo, di usare tool RAD. Sono il primo passo verso tecniche di ricaricamento parziale delle pagine e quindi di una prima forma molto semplice di web asincrono.
Modello asincrono
L’introduzione di AJAX in modo architetturale (e non come semplice tecnica di gestione di componenti), grazie alla invocazione asincrona, ha permesso la creazione di applicazioni realmente asincrone (non solo per certe operazioni di refresh grafico ma anche per le invocazioni di operazioni di business). È questa sicuramente una importante evoluzione sia del modello di programmazione che della modalità di interazione utente-applicazione, tanto che alcuni parlano apertamente di Model 4, mentre più cauti si limitano a considerarlo una minor version del precedente (a volte si trovano in rete riferimenti al Model 3.5).
In questo scenario, limitatamente al mondo Java, siamo passati dai classici framework e tecnologie per lo sviluppo di applicazioni web dinamiche (serlvet/JSP), all’uso di framework MVC che consentono la razionalizzazione delle varie componenti (Struts, Webwork, SpringMVC). L’introduzione delle tecnologie a componenti (JSF 1.0) ha facilitato la composizione della pagina. L’evoluzione verso il modello asincrono infine si è avuto grazia alla nascita di framework a componenti da un lato (RichFaces, IceFaces solo per citarne un paio) unitamente ai nuovi framework asincroni JavaScript (come EXT-JS) o Java (GWT). Lo scenario attuale è sicuramente molto articolato e complesso tanto da mettere in imbarazzo nella scelta della soluzione migliore per la propria applicazione.
Figura 1. L’affollato palcoscenico dei web-frameworks.
RIA: un nuovo modo di intendere le applicazioni per tutte le stagioni?
Una applicazione RIA è spesso più bella, più ricca, più intuitiva da usare, in breve è una applicazione migliore. Ma cosa caratterizza una applicazione Rich? Il termine RIA è sicuramente piuttosto vago, e riferirsi alla tecnologia utilizzata spesso non è sufficiente per dare una buona classificazione; il set di funzionalità e delle caratteristiche che una applicazione Rich dovrebbe avere:
- applicazione client side
- browser embedded
- modello a eventi sulla GUI
- asincronia delle invocazioni sulla parte server
- rich user interface
Non di rado si sente dire che, se lo scopo è quello di realizzare una applicazione a pagine, il modello RIA non va bene; sebbene il contesto vada sempre valutato attentamente, la prima cosa che ci si dovrebbe chiedere è se realmente il vincolo dello schema a pagine sia quello necessario, oppure se non vediamo alternative alle pagine perche‘ ormai sono più di dieci anni che ci troviamo a ragionare con un web pensato e implementato a pagine; non mi sentirei quindi di scartare a priori l’adozione di una applicazione Rich anche nei contesti più insoliti.
Quindi possiamo dire che tale modello sia quello da adottare in maniera universale in tutti i contesti in cui si abbia da scrivere una applicazione web? Forse si, anche se è bene ricordare che il modello RIA si differenzia molto da quello a pagine e che alcuni aspetti dello sviluppo di applicazioni per il web rappresentano ancora delle importanti limitazioni. Vediamo un po’ i dettagli.
SPI vs page flow
La prima differenza sostanziale è data dalla modalità con cui si “compongono” o si scrivono le due tipologie di applicazioni: in un caso, il modello delle web app si basa su una serie di pagine HTML prodotte con una qualche tecnologia o linguaggio: ogni pagina rappresenta una vista parziale del sistema nel suo complesso e la visione completa si ha solo grazie alla navigazione ipertestuale pagina dopo pagina.
Una applicazione RIA invece non offre una visione parzializzata page-oriented del sistema; essendo basata sul concetto di stato invece che di pagina/vista, la applicazione rich in genere è eseguita all’interno del browser e interagisce in modo dinamico con il sistema tramite la proposizione di una GUI ricca di componenti e comportamenti; l’utente interagisce con la GUI cambiando lo stato della applicazione non il passaggio di pagina. Per questo motivo spesso questo tipo di applicazione viene identificata anche con il termine di Single Page Interface (SPI). Questa è probabilmente la caratteristica più importante di una applicazione web stile RIA, fatto che ne condiziona pesantemente lo sviluppo, come riportato nel punto successivo.
Uso della sessione
Una applicazione web tradizionale è normalmente organizzata secondo una sequenza di pagine HTML e usa il protocollo HTTP come canale di flusso delle informazioni, protocollo che come noto è connectionless (e quindi stateless); abitualmente per risolvere questo vincolo, in tutti quei casi in cui sia necessario mantenere lo stato, si usa il concetto di sessione virtuale (la HTTP Session) per memorizzare temporaneamente dati di stato o informazioni utente, così come ad esempio per coordinare il flusso dati fra le varie pagine tramite “il parcheggio” di strutture dati in sessione. Normalmente questo approccio influisce pesantemente sul lavoro del programmatore web che da sempre è abituato a usare e interagire con la sessione e il flusso di pagine, cercando di prevenirne i tipici problemi: un caso tipico è dato dagli effetti della pressione dei pulsanti back/fwd del browser o dall’uso della history, che portano a sovrapporre la linea temporale con il normale flusso applicativo, sovrapposizione spesso deleteria per il buon funzionamento della applicazione (e per questo motivo spesso sono disabilitati).
In una applicazione RIA SPI questo problema è totalmente assente, dato che l’applicazione vive tutta all’interno di una sola pagina HTML (a patto che non si sia volutamente deciso di spezzarla su più pagine, cosa che normalmente porta alla nascita di più applicazioni separate che possono comunque colloquiare tramite la sessione HTTP). Volendo condividere dati fra le varie parti della GUI sarà sufficiente definire tali variabili a scope globale sulla applicazione.
Un’altra importante problematica di cui tener conto è quella che deriva dalla intersezione del normale flusso applicativo con l’uso di oggetti in sessione quando l’applicazione web deve poter visualizzare pagine la modalità multi window: si pensi ad esempio al caso in cui una web application debba aprire popup o permettere la prosecuzione del flusso in finestre diverse da quella principale; in questo caso possono insorgere conflitti o inconsistenze sullo stato delle variabili in sessione dato che il normale flusso ipertestuale si biforca (utente potrebbe poter vedere risultati diversi nelle varie view).
In questi casi normalmente si cerca di ridurre la parallelizzazione dei flussi impendendo che l’utente possa aprire link in altre finestre (per esempio, disabilitando il tasto destro del mouse) oppure cercando ove possibile di ricorrere all’uso di popup visualizzati in modalità modale grazie al JavaScript (anche se in questo caso si dovrebbe parlare di RIA e non di web app).
Questo problema è del tutto assente nelle applicazioni RIA che infatti non sono organizzate secondo il concetto di flusso ipertestuale, non hanno da sincronizzare le varie parti di GUI con una sessione (o meglio la sincronizzazione è realizzabile in modo automatico grazie a sofisticati meccanismi di push asincrono, vedi il data binding di GXT), ne tantomeno devono ricorrere a stratagemmi particolari per implementare finestre di dialogo modali, disponibili in genere in maniera nativa.
Ciclo di vita della applicazione: start/stop
In una SPI Application la applicazione vive nella pagina e con la pagina: visualizzando la pagina si “esegue” l’applicazione. Questo significa che in tale schema l’applicazione non è legata alla history del browser e la pressione sul tasto back/forward porta l’utente alla pagina precedente o successiva uscendo dalla applicazione. Ricaricando la pagina che “incapsula” la rich application (p.e. per un reload o per una sequenza back e forward utente) si causa il restart della applicazione stessa perdendo lo stato di avanzamento dell’utente. Questo comportamento, spesso non voluto e che rompe la magia della Richness&Asycronicity, può essere risolto o con l’uso della sessione HTTP (cosa che “sporca” la pulizia del modello RIA che è “scollato” dal protocollo e dalla vicinanza di un browser), oppure con tecniche di mantenimento dello stato tramite la rirscrittura degli URL per mezzo di caratteri speciali (come il “#” negli URL che in HTTP viene usato per indicare un link interno alla pagina e che non provoca il ricaricamento della pagina stessa). Questo è un problema tipico ad esempio in quei casi in cui si voglia inserire il supporto per la internazionalizzazione di una applicazione GWT: il cambio lingua in questo caso è reso possibile grazie al ricaricamento della applicazione con un URL differente (inserendo come parametro di request un identificatore della lingua o del locale); per cambiare lingua quindi l’applicazione deve ricaricare il proprio URL ovvero deve ripartire da capo perdendo di fatto lo stato accumulato fino a quel punto. Questo cane che si morde la coda (si deve mantenere uno stato ma per cambiare qualche attributo si deve far ripartire l’applicazione perdendo tutto lo stato che però potrà essere ricomposto fino al punto un cui il giro dovrà essere eseguito di nuovo) può essere risolto in genere con il posizionamento di informazioni in sessione accessibili dalla applicazione GWT o con un cookie di lingua nel browser.
Rich Experience
Dopo l’analisi delle differenze interne (tecnologiche e architetturali), dal punto di vista dell’utilizzatore, passiamo a considerare in cosa una RIA-SPI si differenzi rispetto a una applicazione web tradizionale per quanto concerne il modello di interazione utente. In questo contesto la differenza maggiore e più evidente risiede nella ricchezza della GUI e nella capacità di interagire con l’utente senza la necessità di ricaricare la pagina per ogni click o azione utente. La RIA può spesso agire dietro le quinte (asincronia) per reperire dati dallo strato server mentre l’utente svolge qualche altro compito. Per questo una RIA in genere è più intuitiva e più gradevole da usare e permette all’utente di svolgere il proprio lavoro in maniera più rapida (meno ping pong fra il browser e il server).
Problematiche derivanti dall’uso di RIA-SPI
A fronte della migliore user-experience, il modello rich introduce (in alcuni casi re-introduce) alcuni problemi di cui è necessario tenere conto.
Dipendenza dal client
La prima cosa che viene in mente è la reintroduzione della dipendenza dal browser: il modello server centrico (tipico delle applicazioni servlet/JSP/JSF) consente di concentrare i rischi e di ridurre la indeterminazione, sulle caratteristiche e capacità del client; usare le applicazioni rich client, anche se sulla carta permette una maggiore scalabilità (il carico di lavoro computazione per il rendering grafico della GUI è uno-a-uno sul client), introduce il vincolo di dover disporre di browser con VM JavaScript adeguatamente moderne e sufficienti risorse di macchina. È comunque vero che, nella maggior parte dei casi (almeno nell’ambito di applicazioni JavaEE), per ogni client rich in esecuzione nel browser, ci sarà sempre una controparte server side in esecuzione all’interno dell’application server; anche senza scomodare componenti server side come EJB, si pensi al caso di GWT in cui la stessa applicazione è in genere divisa in due parti, una client (in esecuzione nel browser) e una server (in esecuzione nel web container).
Usabilità, ottimizzazione, navigazione
Una sfera in cui il modello RIA al momento pare pagare dazio nei confronti delle applicazioni a pagina tradizionali è quello relativo alle problematiche di usabilità, web search, navigazione. Di seguito sono elencati alcuni aspetti di cui tenere conto.
Bookmarking
Essendo una applicazione rich completamente inglobata in una pagina HTML e potendo cambiare stato senza dover cambiare URL di appartenenza (in fondo è una SPI appunto) risulta difficile se non impossibile permettere il bookmark di un determinato stato della applicazione. Si può solo salvare il bookmark della home della applicazione. Dato che spesso nel caso di una applicazione non ha molto senso “atterrare” direttamente nella applicazione funzionante in un determinato stato (ma è più sensato ripartire dall’inizio, per esempio dal login) questo è spesso un non problema.
Search Engine Optimization (SEO)
Per lo stesso motivo di cui prima (SPI), una rich application difficilmente può essere scandagliata da un crawler di un motore di ricerca. La applicazione agli occhi del motore di ricerca non esiste (viene vista come una sterile pagina HTML+JS) per cui difficilmente potrà raccogliere e indicizzarne i contenuti. Spesso questa limitazione è risolta con la duplicazione in HTML di quelle parti che contengono informazioni interessanti o che si vuole siano rintracciabili via search-engine. Questo aspetto può essere considerato un vantaggio (replicando in HTML si può decidere esattamente cosa pubblicare all’indicizzatore), anche se spesso viene visto come una limitazione (almeno agli occhi del cliente al quale stiamo proponendo una applicazione fantastica per il suo lavoro, ma che potenzialmente potrebbe non essere rintracciabile con una ricerca). Purtroppo non ci sono molte via di uscita, almeno al momenti: tutti i produttori affermano che stanno lavorando per risolvere questo aspetto.
Security
Il problema è analizzabile da due punti di vista: iniettare regole e profilazione all’interno della applicazione e proteggere l’applicazione stessa. Nel primo caso la maggior parte degli strumenti attualmente a disposizione faticano ancora non poco nel cercare di offrire lo stesso livello di funzionalità disponibili nell’ambito di una applicazione web tradizionale. È probabile che presto vedremo colmare questa carenza. Il secondo aspetto è legato al fatto che eseguire una applicazione remotamente e presso il client fa nascere una serie di problematiche tipiche di attacchi tipo “Man in the middle” o “JS-Injection”. L’argomento è sicuramente molto ampio, degno di una serie di articoli dedicati tematici. Per il momento possiamo dire che la maggior parte degli strumenti “seri” offrono un serio supporto al problema.
Considerazioni in ordine sparso
Dopo quanto visto, elenco qui di seguito alcune considerazioni relative all’uso del modello web app in confronto con quello RIA. In entrambi i casi non posso purtroppo vantare una conoscenza globale e onnicomprensiva e per questo motivo le mie valutazioni, pur di carattere generale, sono limitate dalle esperienze maturate dall’uso dei framework più importanti e famosi.
Framework, OOP, datamodel e DDD (Domain Driven Design)
La presenza di un layer di HTML più o meno magicamente generato (dalle pagine JSP ai framework a componenti come JSF o ZK) ha da sempre generato in me un innato fastidio nel momento in cui si deve eseguire il rendering di oggetti modello; il dover usare un formato basato su tag o custom tag più o meno proprietari obbliga il programmatore a pensare (quindi trasformare) secondo uno schema di scripting-gerarchico e non in OOP vero e proprio. Molto più semplice ragionare a oggetti e lasciare al framework il compito di tradurre il tutto in HTML e JS: in una parola se il modello dei dati è il vostro pallino, e il DDD è la vostra fede, il mio consiglio è di scegliere una soluzione alla GWT (o Flex) piuttosto che uno dei tanti paradigmi JSP.
Component libraries
Anche in questo caso mi trovo a dover spezzare una lancia a favore di soluzioni RIA GWT like, dove l’uso di librerie di componenti standard o estensioni particolari non mi ha mai creato problemi particolari ne‘ per l’inclusione nel tool di sviluppo ne‘ per l’uso a runtime. Non posso certo dire lo stesso dei vari Woodstock, IceFaces, RichFaces, etc. dei quali si può avere una buona considerazione se presi singolarmente, ma per i quali diviene una esperienza esoterica il tentativo di convivenza. Il fatto che un componente grafico abbia una veste HTML, una da custom tag, una da widget RAD (o presunta tale) e una da classe Java non fa che aumentare il mio senso di disagio.
Layout definition
Discorso ribaltato per la parte di templating e rapid UI definition; il mondo delle web application è costellato di strumenti atti a risolvere questo problema, con soluzioni più o meno eleganti e rapide. Nel mondo delle RIA questo ancora manca, se non si considera il tentativo di GWT-UIBuilder che però mi pare un po’ lasciato a se stesso (di fatto i super-framework come Ext-GWT non lo hanno ancora implementato e forse non lo faranno).
Supporto maturità dei tool
Qui tutti più o meno sono deboli; le promesse di RAD, Two-Way-Programming (dal codice alla UI drawing e viceversa) sia in ambito web application XHTML che di RIA sono tutte piuttosto deboli e portano lo sviluppatore a passare alla scrittura del codice direttamente a mano. I plugin di Eclipse o NetBeans più usati sono quelli che si limitano a creare la struttura di progetto.
Gestione delle singole risorse
Similmente a quanto detto per la parte di sicurezza, la gestione e il controllo delle singole componenti (pagine o servlet o beans per le applicazioni tradizionali, così come pannelli, window dialog per le RIA) risulta più dettagliatamente definibile per una applicazione web che non per una applicazione monolitica. Attivare un filtro o un log su determinati sottoinsiemi di pagine è una operazione semplice come scrivere poche righe di XML; attivare un controllo tramite la AOP di Spring su un component web è altrettanto semplice. Per una applicazione RIA la cosa è meno semplice perche‘ l’assenza della risorsa singola (la pagina o l’URL mappato su un singolo bean o servlet) impedisce di personalizzare la gestione e il controllo. Probabilmente l’introduzione di AOP alla Spring potrebbe essere “la soluzione” e per questo molto promettente appare essere il progetto ROO che punta fra le molte cose anche alla unificazione di Spring con GWT.
Conclusione
In conclusione possiamo dire che le applicazioni RIA sono migliori per quanto concerne la modalità di utilizzo da parte dell’utente e per alcuni aspetti implementativi. L’utilizzo di queste applicazioni porta con se alcune problematiche spesso derivanti dal fatto che per anni siamo stati abituati a ragionare con applicazioni a pagine, che funzionano come macchine a stati per le quali ci siamo inventati trucchi e barbatrucchi per risolvere i problemi di questo modello. Tali soluzioni non funzionano con il modello RIA: probabilmente è il modello stesso che se affrontato con una mentalità a pagine si troverà in difficoltà. Non è illogico pensare che cambiando approccio (da page oriented a state oriented), spariranno molti dei problemi per i quali le soluzioni derivanti dal modello web non funzionano con l’approccio rich.
Alcune problematiche (bookmarking o mantenimento dello stato al reload della pagina) restano in effetti poco gestibili nel modello rich per cui c’è da attendersi che presto verranno rese disponibili soluzioni ufficiali e integrate.
Riferimenti
[FWKS] Confronto fra web frameworks
http://www.slideshare.net/jmarranz/how-to-choose-a-web-framework-and-be-surprised
[AJX] “Ajax: un nuovo approccio per le applicazioni Web”
http://read.melodycode.com/tutorials/158/ajax_un_nuovo_approccio_per_le_applicazioni_web.html
[CRW] “A proposal for making AJAX crawlable”
http://googlewebmastercentral.blogspot.com/2009/10/proposal-for-making-ajax-crawlable.html
[ASYNC] Stephen Maryka, “What is the Asynchronous Web, and How is it Revolutionary?”, The Server Side
http://www.theserverside.com/news/1363576/What-is-the-Asynchronous-Web-and-How-is-it-Revolutionary
[MVC] Model-View-Controller
http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller