Visualizzazione post con etichetta gui. Mostra tutti i post
Visualizzazione post con etichetta gui. Mostra tutti i post

giovedì 31 luglio 2008

Echo2, aka "Swing su web"

Nel progetto a cui sto lavorando, oltre a Castor per il marshaling/unmarshaling dell'xml (di cui ho già parlato qui), si usa Echo2 per la GUI.

In maniera concettualmente simile a quello che fa Google web toolkit, Echo2 funziona che si scrive in Java e lui, in maniera completamente invisibile a noi programmatori, produce il codice HTML + Javascript + AJAX; a differenza di GWT, però, Echo2 produce il codice "al volo" in una servlet anzichè essere compilato "a bocce ferme"...non che faccia sta differenza abissale comunque, visto anche che GWT può essere eseguito in hosted mode che funziona circa come Echo2 ma con un browser apposito.

Ad ogni modo, la figata di Echo2 è che quasi tutte le classi dei componenti si chiamano esattamente come quelle di Swing, per cui del codice come questo:
Button update = new Button("Update");
update.setToolTipText("Update");
update.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
doUpdate();
}
});
Valido in Swing, è perfettamente valido anche in Echo2, a patto ovviamente di importare le classi dai package giusti.

Come in Swing, ci sono praticamente tutti i componenti GUI più comuni (e alcuni di quelli meno utili ma presenti in quasi ogni framework, tipo l'AccordionPane) e tutti hanno performances assolutamente ottime, il che è una cosa positiva visto che il pannellino di "please wait" che compare quando una richiesta AJAX ci mette troppo tempo a ricevere risposta è aberrante e neppure troppo semplice nè flessibile da customizzare.

Di fatto, quindi, Echo2 consente di realizzare applicazioni web con interfaccia grafica molto, ma proprio molto simile a quella delle applicazioni desktop, mascherando praticamente tutti gli sbattimenti della programmazione web tipo:
  • Casini dovuti alla discordia tra i browser web e Internet Explorer
  • Casini dovuti alla difficoltà di implementare in HTML + Javascript comportamenti standard delle GUI desktop, tipo il drag & drop
  • Casini per noi sviluppatori Java alle prese con un linguaggio spesso criptico come Javascript
Oltre a tutto ciò, ha anche una serie di cazzimmine carine pensate proprio per le applicazioni web, tipo il meccanismo di server push, che è fondamentalmente una richiesta AJAX nascosta che continua a interrogare il server, dando all'utente l'impressione che sia il server ad aggiornargli il client spontaneamente anzichè su richiesta come previsto dall'HTTP, o tipo la gestione integrata del download di file sul client.

Per chi volesse lucidarsi un po' gli occhi, qui c'è la demo che fa vedere un po' tutto quello che si può fare e, ora che ci lavoro da qualche mese, mi sento in grado di dire che non è neanche esageratamente incasinata ma anzi è roba che si può rifare in pochissimo tempo.

Unico difetto non di poco conto, essendo un framework di nicchia la documentazione non è nè molta nè esaustiva (in pratica c'è solo il support forum sul sito ufficiale) e la situazione non è destinata a migliorare, visto che Echo3 è già in beta e consente di sviluppare anche direttamente in Javascript mantenendo la stessa API del Java lato server, per cui c'è il rischio che all'uscita della nuova versione la community di sviluppatori si concentri sulla parte client-only e trascuri quella Java; tuttavia, lo scope del framework è abbastanza ristretto, dato che si limita alla GUI, per cui anche lo scope di possibili problemi è piuttosto limitato.

lunedì 26 maggio 2008

Il BackgroundWorker di .NET

E' un bel po' che non scrivo qualcosa di veramente nerd, per cui devo vedere di darmi un tono, che qua se no tra emo, tette e culi e gommisti che fanno l'happy hour sembra quasi un brog di quelli lascivi.

Lo spunto me l'ha offerto un mio amico a cui serviva un giochino .NET che eseguisse un'operazione lunga e ripetitiva (un send broadcast su un socket UDP...don't ask) pescando dati dalla gui e aggiornando la gui stessa; problema classico dei client grafici stand-alone è che quando esegui qualcosa di pesante nello stesso thread che dovrebbe anche aggiornare la gui, questa si freeza dando all'utente la sensazione di un crash.

Dato che è un problema stranoto, il .NET framework offre la soluzione, elegantemente spiegata in questo video:



Fondamentalmente, la classe BackgroundWorker fornisce un'interfaccia relativamente semplice per le operazioni di "Crea un thread - fagli fare quello che vuoi in background - a intervalli regolari fagli notificare il suo stato - alla fine fagli notificare che ha finito" mettendo a disposizione 3 delegate: con le 3 istruzioni

bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);

Si settano i delegate (o, per gli anziani che parlano in C, i callback) rispettivamente per le operazioni di "fai quello che devi fare", "notificami il tuo stato" e "hai finito il tuo compito".

Il delegate più importante, quello che fa tutto il lavoro sporco da fare in background, è il primo, la cui signature è
void bw_DoWork(object sender, DoWorkEventArgs e)
I due parametri rappresentano, rispettivamente, il BackgroundWorker che sta lavorando (upcastato a object per convenzione) e i parametri passati dall'applicazione al thread del lavoro sporco; a intervalli - si spera - regolari, in questo metodo comparirà una chiamata a sender.ReportProgress(int, object) con la quale si riporteranno al thread principale la propria percentuale di esecuzione e il proprio stato o altri dati interessanti, per esempio da riportare sulla gui.

La presentazione in gui dello stato del BackgroundWorker, infatti, viene implementata nel delegate associato all'evento ProgressChanged, scatenato ogni volta che DoWork chiama ReportProgress con una percentuale di esecuzione diversa da quella della chiamata precedente: in questo modo, è possibile separare completamente il layer di logica di business da quello di presentazione, con somma gioia di grandi e piccini :)

Una volta finito tutto il lavoro sporco in background, il BackgroundWorker spara l'evento RunWorkerCompleted, che fa eseguire i delegate associati e manda tutti negli spogliatoi per una doccia.

Come se non bastasse, è possibile fermare il BackgroundWorker a metà del suo operato senza alcuna ripercussione sulla fluidità della gui: è sufficiente, da qualche parte nel codice (per esempio nel metodo associato al click di un pulsante), chiamare il metodo CancelAsync del BackgroundWorker e, nel delegate associato a DoWork, controllare se è stata richiesta la cancellazione dell'esecuzione testando la proprietà CancellationPending.

Morale, con questo giochino si riesce a ottenere una gui fluida e sempre rapida nelle risposte all'utente anche quando, sotto sotto, il programma sta facendo qualcosa di pesante e noioso.

E io sono sempre un nerd, anche se qualche volta parlo di argomenti frivoli.