Home / Indice sezione
 www.icosaedro.it 

 bt_ - Implementazione

Realizzare siti WEB dinamici è ancora oggi un'attività piuttosto complessa. bt_ è una serie di concetti e di codice di uso immediato che permettono di realizzare in breve tempo e con ottimi risultati, complessi siti WEB dinamici. bt_ si occupa di gestire le sessioni e mantiene i collegamenti tra le diverse finestre. Con bt_ il programmatore può pensare alle singole finestre che compongono la sua applicazione WEB come se si trattasse di funzioni che si richiamano le une con le altre e si passano dei valori. In questo modo la gestione di ancore, bottoni, maschere di input e tutta la complessa catena di finestre collegate, si riconducono a semplici funzioni del programma. Viene presentata una implementazione in Bash dei concetti di bt_.

Storico degli aggiornamenti

2004-02-14
Resa disponibile l'implementazione in Bash di bt_.
2003-03-31
Prima edizione dell'articolo.

Indice

Introduzione
Call-forward e call-backward functions
Il bt_file
Il bt_stack
Sessioni
Il nostro esempio in funzione
Conclusioni
Bibliografia
Argomenti correlati

Introduzione

Il WEB è nato come strumento per la presentazione di documenti multimediali, dunque come puro strumento di consultazione: la presenza di ancore permette di spostarsi rapidamente e in modo intuitivo attraverso un intrico di pagine le cui interconnessioni sono rigidamente prederminate. Ad ogni "click" sul browser, il client stabilisce una nuova connessione con il server, attende la sua risposta, presenta il documento risultante all'operatore, e quindi termina il collegamento. Il browser si mette quindi in attesa del prossimo click per ripetere il ciclo ancora una volta.

Solo successivamente, con diverse estensioni del linguaggio HTML e del protocollo HTTP, è diventato possibile scambiare informazioni nei due sensi tra client e server: i link ipertestuali opportunamente estesi con dei parametri, le maschere di inserimento e i bottoni, e il concetto di cookie, danno la possibilità al client di inviare informazioni al server attraverso una serie di meccanismi e di aggirare la restrizione legata alla mancanza di una connessione permanente tra client e server.

Se tutto questo ha risolto il problema di potenziare l'interattività lato client, dal lato server le cose si sono complicate parecchio. La generazione dinamica delle pagine WEB richiede un programma, ma si pone il problema di interfacciare tali programmi con il server e il client. La prima risposta dei produttori di server WEB è stata di tipo minimalista: tutti i dati e i parametri provenienti dal client vengono passati all'applicazione WEB sfruttando i meccanismi canonici di comunicazione tra processi del sistema operativo ospite. In ambiente Unix e simili abbiamo allora il CGI, mentre in ambiente Microsoft abbiamo ASP. In realtà sia CGI sia ASP ben poco fanno per il programmatore: interpretare i parametri provenienti dal client e generare le pagine WEB richiede ancora una quantità di codice di basso livello e spesso ripetitivo. I linguaggi di scripting come Perl, Bash e le Java Servlet operano in questo modo.

Sono nati allora degli strumenti di sviluppo tesi a semplificare la generazione delle pagine WEB dinamiche, e capaci di permettere la collaborazione tra il grafico e il programmatore, due figure chiave della produzione WEB. L'idea di base è la seguente: ogni singola pagina WEB viene prodotta come normale codice HTML; nei punti della pagina destinati ad ospitare le parti dinamiche del sito, il programmatore aggiunge il codice necessario in un qualche linguaggio di programmazione; è poi compito del server estrarre da ogni pagina le parti HTML ed eseguire le parti di programma prima di consegnare il tutto al client. Ad esempio, PHP, JSP e IIS operano in questo modo. Anche per altri linguaggi sono disponibili soluzioni che permettono di miscelare codice HTML e codice di programma.

Nel quadro di tutte queste soluzioni per la generazione di siti WEB dinamici, bt_ si inserisce come strumento essenzialmente rivolto ai programmatori. Infatti, in bt_ la programmazione WEB viene ricondotta alla logica della programmazione funzionale: ogni pagina WEB corrisponde a una funzione che ha dei parametri e che restituisce dei risultati. Dunque bt_ si occupa del meccanismo di chiamata, del passaggio dei parametri e del ritorno dei risultati, liberando il programmatore dall'onere di gestire gli aspetti di basso livello del WEB quali le sessioni, l'autenticazione dell'utente, il passaggio dei parametri, ecc.

Vedremo negli esempi quanto sia facile, con bt_, realizzare pagine WEB tra loro interconnesse, gestire ancore e bottoni, gestire la logica di chiamata delle pagine e dei relativi ritorni in base alle ancore e ai bottoni azionati dall'utente.

Call-forward e call-backward functions

Proviamo ad immaginare una generica pagina WEB di un sito dinamico: l'unico meccanismo che l'utente ha per esprimere la sua volontà sono i link ipertestuali e i bottoni. Premendo un'ancora il browser invia al server una richiesta GET completa degli eventuali parametri inseriti nell'URL; premendo un bottone il browser invia al server una richiesta POST completa dei vari campi del form. Questo è tutto ciò che offrono l'HTTP e l'HTML, oltre ai cookie. Immaginiamo allora di disegnare su di un foglio le varie pagine che compongono il nostro sito WEB, evidenziando ancore e bottoni; ogni pagina viene generata da una apposita funzione del nostro programma. Ogni volta che l'operatore preme un'ancora o un bottone, il server dovrà attivare la funzione opportuna che elabora la nuova pagina. Nel nostro schema, tracciamo allora una freccia che va da ogni ancora e ogni bottone verso la corrispondente funzione che deve essere attivata quando l'utente aziona quell'ancora o quel bottone. Il disegno qui sotto rappresenta uno schema siffatto:



Lo schema illustra la catena delle chiamate delle varie funzioni che compongono il nostro sito WEB dinamico. La funzione "menu" genera una pagina contenente un menu di scelte, ciascuna costituita da un'ancora. In particolare, il link "Arte astratta" deve rimandare alla funzione "arte", che produce un altro menu dal quale l'utente può scegliere il colore del quadro e il colore della cornice (nel nostro esempio banale, dunque, l'arte astratta si riduce alla scelta di due colori). Se l'utente clicca sull'ancora di scelta del colore del quadro, viene invocata la funzione "colore" che presenta una tavolozza di colori tra cui scegliere. Se l'utente clicca sull'ancora di scelta del colore della cornice, viene invocata ancora la funzione "colore". Fino a questo punto abbiamo descritto le chiamate "in avanti" delle funzioni (call-forward).

La funzione "colore" ritorna al chiamante il codice del colore scelto. In questo caso si tratta di una "chiamata all'indietro" (call-backward) che restituisce anche un valore (il colore scelto). Osserviamo che la funzione "colore" presenta anche un bottone "Annulla" con il quale l'operatore può rinunciare alla scelta: dobbiamo ricordarci di codificare con un valore particolare questa azione. Osserviamo anche che la funzione "arte" sfrutta la funzione "colore" per ottenere due informazioni diverse: il colore del quadro e il colore della cornice. In altri termini, stiamo utilizzando una pagina WEB come se fosse una funzione di libreria: com'è facile immaginare, questo apre la possibilità di realizzare pagine WEB (ovvero funzioni) di uso generale inseribili in una specie di libreria di pagine WEB di utilità. Infine, sia la funzione "arte" che la funzione "menu" generano un bottone "OK" che in realtà ha lo scopo di ritornare al chiamante originario. Osserviamo infine che la funzione "colore" non ha alcuna cognizione della esistenza delle altre funzioni, ed è quindi del tutto indipendente. Anche la funzione "arte" non ha alcuna cognizione della esistenza della funzione "menu". In altri termini, le funzioni che compongono il nostro sito WEB sono organizzate in una gerarchia. Per programmi più complessi e articolati avremo decine o centinaia di funzioni che si potranno organizzare in moduli indipendenti.

Vediamo subito come le funzioni si possono realizzare con bt_. Userò il linguaggio Bash, che ha una sintassi molto semplice e che dovrebbe risultare comprensibile anche a coloro che non conoscono questo linguaggio. Cominciamo con la funzione "menu":

function menu()
{
    echo "<HTML><HEAD><TITLE>Menu</TITLE></HEAD><BODY>"
    bt_alink "Arte astratta" arte
    bt_return_to menu
    bt_alink "Xxx xxx"       xxxx
    bt_return_to menu
    bt_form
    bt_button Logout logout
    echo "</FORM>"
    echo "</BODY></HTML>"
}

Il comando "echo" genera in output il contenuto dei suoi parametri. Usiamo questo comando per generare il codice HTML "statico".

bt_alink è invece una funzione di bt_, la prima che vediamo: essa genera un'ancora e permette di associare a questo link anche la funzione da richiamare. Il primo parametro di bt_alink è il testo che deve apparire nell'ancora; il secondo parametro è il nome della funzione da richiamare se quest'ancora viene cliccata dall'utente; gli eventuali ulteriori parametri sono gli argomenti da passare alla funzione quando questa sarà chiamata (nel nostro caso non ci sono parametri).

bt_return_to informa bt_ che, nel caso venga attivata la call-forward indicata in bt_alink, desideriamo che il ritorno venga eseguito sulla funzione menu: in altri termini, con bt_alink abbiamo indicato la call-forward, mentre con bt_return_to abbiamo indicato la call-backward corrispondente.

Tra un'ancora e l'altra dovremo probabilmente inserire uno spazio verticale, magari con un tag "<P>": dettagli come questo li ho omessi dai sorgenti di esempio per meglio evidenziare la sostanza del nostro discorso.

bt_form è una funzione di bt_ che apre un FORM HTML. Il FORM aperto deve poi essere chiuso con il solito tag di chiusura "</FORM>". Ormai abbiamo capito che tutte le funzioni che iniziano con "bt_" sono proprie di bt_, per cui nel seguito non mi ripeterò.

All'interno del FORM inseriamo il bottone "Logout" con la funzione bt_button. I parametri della funzione sono: il testo da fare apparire dentro al bottone, la funzione da chiamare nel caso che l'utente azioni questo bottone, e gli eventuali argomenti da passare a questa funzione. In questo esempio, il bottone Logout produce l'invocazione della funzione omonima di cui non abbiamo parlato, ma della quale possimo immaginare lo scopo.

Ecco come si presenta la pagina HTML generata dalla funzione "menu":

<HTML><HEAD><TITLE>Menu</TITLE></HEAD><BODY>
<P>
<A href="/bt_/bt_-bash.cgi?i=1">Arte astratta</A>
<P>
<A href="/bt_/bt_-bash.cgi?i=2">Xxx xxx</A>
<CENTER>
<FORM method=post action="/bt_/bt_-bash.cgi">
<INPUT type=hidden name=i value=3>
<INPUT type=submit name=button value="Logout">
</FORM>
</CENTER>
</BODY></HTML>

La funzione "arte" è sostanzialmente identica alla funzione "menu". L'unica differenza rilevante è il bottone "OK" che produce l'invocazione della funzione bt_return: è questa funzione speciale di bt_ che realizza la call-backward che ci fa ritornare alla funzione "menu":

function arte()
{
    echo "<HTML><HEAD><TITLE>Arte</TITLE></HEAD><BODY>"
    bt_alink "Colore quadro"  colore
    bt_return_to arte colore_quadro
    bt_alink "Colore cornice" colore
    bt_return_to arte colore_cornice
    bt_form
    bt_button OK bt_return
    echo "</FORM>"
    echo "</BODY></HTML>"
}

Dunque, se il navigatore clicca sull'ancora "Colore quadro" viene invocata la funzione "colore". Il ritorno viene impostato di nuovo sulla funzione "arte" stessa, ma con degli argomenti: "colore_quadro" è preimpostato, mente gli altri argomenti sono i valori ritornati dalla funzione "colore".

Per semplificare il codice dalle parti non essenziali, la funzione "colore" ci permette si selezionare solo tre colori: rosso, verde o blu:

function colore()
{
    echo "<HTML><HEAD><TITLE>Colore</TITLE></HEAD><BODY>"
    bt_alink "ROSSO" bt_return ok "#ff0000"
    bt_alink "VERDE" bt_return ok "#00ff00"
    bt_alink "BLU"   bt_return ok "#0000ff"
    bt_form
    bt_button OK bt_return cancel
    echo "</FORM>"
    echo "</BODY></HTML>"
}

Premendo l'ancora del rosso, ad esempio, viene chiamata la funzione bt_return con argomenti "ok" e "#ff0000". A sua volta la funzione bt_return ritorna questi argomenti all'originale chiamante, cioè alla funzione "arte". Premendo invece il bottone "Annulla", la funzione "arte" viene richiamata con l'argomento "cancel". In definitiva, se il navigatore ha scelto il colore rosso per il quadro, la funzione "arte" verrà richiamata con questi argomenti:

arte("colore_quadro", "ok", "#ff0000")

mentre se il navigatore ha premuto il bottone "Annulla" nella finestra di selezione colore, la funzione "arte" verrà richiamata con questi argomenti:

arte("colore_quadro", "cancel")

A sua volta la funzione "arte" dovrà contenere all'inizio una parte di codice che analizza i suoi eventuali argomenti e si comporta di conseguenza, per esempio salvando il colore scelto e visualizzando direttamente il nostro quadro col colore scelto. Nel nostro esempio della funzione "arte" ho omesso questa parte di codice.

Osserviamo che bt_ è particolarmente potente se usato con linguaggi che permettono un numero variabile di argomenti nelle funzioni, come Bash, PHP, Perl, C, ecc. Con altri linguaggi bisogna ricorrere ad accorgimenti che complicano un pò il lavoro del programmatore, ma non cambiano nella sostanza le cose.

Per comprendere meglio il meccanismo delle call-forward function e delle call-backward function, che sta al centro di bt_, occorre spiegare cosa sono il bt_file e il bt_stack.

Il bt_file

Abbiamo visto che ogni funzione genera una pagina WEB e tutte le ancore e i bottoni necessari. Per ogni ancora e bottone dobbiamo chiamare una apposita funzione di bt_ che predispone la call-forward da realizzare se quell'ancora o bottone viene azionato. bt_ memorizza le call-forward nel bt_file. Ogni volta che l'utente preme un'ancora o un bottone, il browser invia una richiesta al server, il server riporta questa richiesta a bt_, bt_ legge il bt_file e da questo ricava la call-forward da invocare, e quindi richiama tale funzione.

Bisogna a questo punto anche spiegare come fa bt_ ad associare un'ancora o un bottone a una data call-forward. Il meccanismo è piuttosto semplice: ogni ancora e ogni bottone generato da una funzione viene numerato progressivamente da bt_. Un nuovo numero viene generato ogni volta che si chiama la funzione bt_alink o la funzione bt_button. In questo modo l'unica informazione che viene inviata al client per ogni ancora e bottone è solo questo numero. Le altre informazioni, come il nome della funzione e i suoi argomenti, rimangono nel bt_file sul server, e non vengono mai trasferiti al client. Questo fatto ha importanti implicazioni di sicurezza e di efficienza.

Quando l'utente preme su di un'ancora o un bottone, tutto quello che ritorna a bt_ è il numero a suo tempo assegnato a quell'ancora o bottone: questo numero indice consente di ritrovare nel bt_file l'entrata corrispondente.

Ogni volta che una funzione genera una nuova pagina, il bt_file viene svuotato e predisposto ad accogliere le nuove call-forward.

Nel bt_file vengono archiviate anche le eventuali call-backward inserite con la funzione bt_return_to: se l'utente aziona una data call-forward, la corrispondente call-backward viene inserita in cima al bt_stack, così predispondendo il corretto ritorno.

Il bt_stack

Si tratta di un file dove sono memorizzate le call-backward da invocare da parte della funzione bt_return. Le entrate nel bt_stack vengono aggiunte quando l'utente preme su di un'ancora o bottone e per questa ancora o bottone era stata predisposta una call-backward con la funzione bt_return_to. La chiamata alla funzione bt_return produce l'estrazione dal bt_stack della call-backward e la sua invocazione. Se la funzione bt_return specifica dei parametri addizionali, questi vengono aggiunti agli argomenti della call-backward.

Il bt_stack è inizialmente vuoto.

Riassumiamo tutto il meccanismo: le nostre funzioni, ciascuna specializzata nella generazione di una pagina WEB, producono varie ancore e vari bottoni; la funzione che genera la pagina non può conoscere in anticipo su quale ancora o bottone l'utente farà click, e pertanto occorre salvare nel bt_file tutte le possibili call-forward per ogni ancora e per ogni bottone. Per ogni ancora e per ogni bottone possiamo anche predisporre la call-backward, cioè la funzione che desideriamo invocare al ritorno dalla call-forward.

Bisogna anche aggiungere che bt_ permette di manipolare il bt_stack per inserire o togliere delle call-backward. Tutto ciò permette di costruire percorsi arbitrari da una pagina all'altra con assoluta libertà (spaghetti WEB programming). Ci sono molti casi della programmazione WEB nei quali la spaghetti WEB programming risulta più efficace del modello puramente funzionale. Uno di questi casi è il ciclo di compilazione maschera / validazione / segnalazione errori di compilazione / ritorno alla maschera: basta disegnare il relativo schema delle chiamate per rendersene conto.

Sessioni

Siccome le pagine possono essere consultate da parecchie persone contemporaneamente, bisogna prevedere un bt_file e un bt_stack per ciascuna di esse dove conservare lo stato di bt_. Il problema si risolve facilmente sfruttando un cookie: al momento del primo ingresso nel programma, bt_ genera un cookie contenente una stringa casuale e la invia al client, quindi presenta al nuovo utente la pagina iniziale. Il valore del cookie viene usato da bt_ per creare una directory dentro la quale salvare il bt_file e il bt_stack specifici di quell'utente. L'insieme di queste informazioni costituisce la sessione. Ogni volta che il client richiede una nuova pagina come conseguenza di un click su di un'ancora o su di un bottone, il client invia al server anche il cookie a suo tempo registrato. bt_ ha così modo di recuperare la corretta sessione per ogni click successivo.

Lo strumento delle sessioni è utile anche per riconoscere l'utente nei casi in cui l'accesso al sito WEB sia regolato da un login. Una volta che l'utente ha inserito il nome e a la password, il cookie di sessione permetterà anche di identificare quel particolare utente per tutta la durata della sessione.

Notare che bt_ solleva completamente il programmatore da tutta la complessa gestione della sessione, dei cookie e della identificazione dell'utente.

Il nostro esempio in funzione

La prima implementazione dei concetti di bt_ la feci in Bash, un diffuso linguaggio di shell scripting in ambiente Unix. Ho riutilizzato lo stesso codice per realizzare l'esempio presentato in questo documento. Ecco cose ne è saltato fuori:

ESEMPIO IN FUNZIONE

Si aprirà una nuova finestra dove potrai vedere al lavoro i concetti di bt_ qui esposti. Noterai che certi link riportano il parametro "i=2" o altro numero: questo è l'indice della call-forward nel bt_file.

Il codice del programma puo' essere scaricato qui:

Altre risorse e documentazione che possono tornare utili:

Conclusioni

Abbiamo visto che bt_ offre un approccio funzionale allo sviluppo dei siti WEB dinamici, e abbiamo visto come gli argomenti delle funzioni, che possono diventare molto ingombranti in applicazioni complesse, non vengono mai passati al client, ma rimangono sempre solo sul server nel bt_file o nel bt_stack. Quello che viene passato al client è un indice per ciascuna ancora e bottone.

Tutto ciò ha evidenti vantaggi dal punto di vista della efficienza (risparmio di banda, velocità nella presentazione della pagine, ecc.), ma offre anche un grande vantaggio dal punto di vista della sicurezza, perché dal lato client non è possibile in alcun modo falsificare lo stato interno di bt_. Un utente malizioso che tentasse di generare indici arbitrari, otterrebbe solo di selezionare una delle entrate già predisposte nel bt_file se l'indice è compreso tra quelli previsti, oppure otterrebbe un bel messaggio di errore "finestra fuori sequenza" se l'indice non è tra quelli previsti nel bt_file. Inoltre il programmatore ha la certezza che gli argomenti con i quali le sue funzioni vengono chiamate sono validi, poichè li ha generati il suo stesso programma prima di inserirli nel bt_file. Dunque, niente più valanghe di codice intricato per verificare che i dati provenienti dai metodi GET o dai campi HIDDEN siano validi.

Implementare bt_ in Bash è stato facile e veloce, e questo linguaggio si è dimostrato ancora una volta uno strumento molto efficace per la realizzazione di prototipi e piccole applicazioni. Sfortunatamente, Bash non è il massimo come linguaggio di programmazione: è lento, non dispone di strutture dati degne di questo nome, non supporta un metodo per la serializzazione dei dati che sarebbe molto utile per implementare bt_. L'implementazione in Bash è comunque servita per mettere a punto tutti i concetti fondamentali di bt_.

In previsione di importanti applicazioni pratiche, ho tradotto bt_ in PHP. Il PHP è decisamente più efficiente, supporta la programmazione ad oggetti e la serializzazione, e dispone di ricchissime librerie di funzioni di utilità. Integrato con una serie di funzionalità ulteriori, in questa nuova veste bt_ si è confermato un efficace strumento di sviluppo per siti WEB dinamici.

I concetti alla base di bt_ non sono legati a un particolare linguaggio o sistema di sviluppo, ma si possono facilmente implementare su qualsiasi sistema.

Bibliografia

NOTA: i documenti RFC sono reperibili in www.rfc-editor.org.

Argomenti correlati

NOTA: i documenti RFC sono reperibili in www.rfc-editor.org.


Umberto Salsi
Commenti
Contatto
Mappa
Home / Indice sezione
An abstract of the lastest comments from the visitors of this page follows. Please, use the Comments link above to read all the messages or to add your contribute.

2006-11-30 by Vittorio "Molinari Bash" Cagnetta
e' artistico ma forse troppo granulare
L'implementazione dei concetti "bt_" in bash che lei ha scritto e' qualcosa piu' di "cleaver" (come dicono gli americani = "intelligente,furbo" ): costringere una semplice shell a creare pagine Web dinamiche e' "arte". L'unico problema, volendola usare per i miei bisogni, non e' costituito tanto dalle limitazioni di cui lei parla riguardo al linguaggio bash , ma dal fatto che, se voglio creare un semplice form di input, potrei non voler scendere tanto in basso come ha fatto lei (con la creazione dei singoli elementi della pagina, dei bottoni, ecc.). Per intenderci, per creare una applicazione NON WEB, o uso glade/qt o uso Xdialog. bash-bt_ (per rimanere in ambito bash) potrebbe essere il corrispettivo web di glade, ma il corrispettivo di Xdialog? Forse quello della estrema semplificazione non e' un obiettivo della sua ricerca, o magari va proprio nella direzione opposta del suo studio (piu' semplificazione = meno possibilita' di customizzazione)... in ogni caso questo bash/bt_ a mio av[...][more...]

2006-11-11 by Guest
non funziona se si preme 'aggiorna' sul browser.
Se premo 'aggiorna' o il tasto che ritorna indietro di una pagina sul browser, l'utente si ritrova su pagine inaspettate. Ovviamente se fosse lo sviluppatore dell'applicazione saprebbe perche': premendo 'aggiorna' in realta' non viene ricaricata la pagina, ma lanciata quella che ha l'id aggiornato nel bt_file. Occorre risolvere il problema :)[more...]