Metodi di generazione dell'HTML
Thursday, 12 April 07
Una applicazione web e' un programma che ha come formato di output principale
l'HTML. La generazione di HTML e' pertanto una parte importante nella scrittura di applicazioni web: programmatori e web framework cercano di risolvere il problema in vari modi dagli albori della web programing. Alcuni linguaggi di programmazione quali il PHP hanno addirittura fatto della semplicita' di interpolazione tra l'HTML e i frammenti di programma uno dei loro punti di forza. Qual'e' ad oggi il modo migliore per generare l'HTML? Segue una
descrizione dei principali metodi e del perche' e' cambiato qualcosa
di importante nel contesto delle applicazioni web che determina la superiorita'
di uno di questi metodi.
Il template separa fisicamente l'HTML dal codice della applicazione e rende editabile la parte HTML anche da chi non ha alcuna competenza di programmazione. Poiche' offre questo vantaggio e perche' **fino a qualche anno fa assurdi layout fatti con le tabelle e la necessita' di specificare gli attributi di stile direttamente dentro i tag rendevano la produzione dell'HTML dall'interno della applicazione un incubo** il template e' stato considerato per un po' di tempo The Right Thing in relazione alla produzione di HTML.
Tanto e' vero che ancora oggi e' considerato un buon sistema, ma...
I template hanno profondi limiti. Nelle applicazioni web piu' complesse non si tratta soltanto di sostituire contenuti in posizioni prestabilite. Liste, tag cloud e molti altri elementi di una pagina vengono prodotti partendo da alcuni dati e nulla piu' e in questi casi ovviamente i template non aiutano o finiscono per diventare un incubo di piccoli frammenti di HTML da editare singolarmente.
Inoltre la produzione dell'HTML e' sparpagliata in tutto il codice. Se ad un certo punto si decide di emettere <strong> invece di <b> bisogna controllare ogni parte in cui c'e' un <b> e modificarla. Non c'e' alcuna centralizzazione nel modo in cui l'HTML viene prodotto.
Eppure questo modo di scrivere il codice e' molto diffuso: e' la cosa piu' immediata che si possa fare, per piccole applicazioni finisce per funzionare, e la semplificazione che ha visto l'HTML negli ultimi anni ha fatto diventare questo tipo di programmazione piu' gestibile nel lungo termine: basta emettere un po' di DIV e SPAN in relazione al contesto e poi lasciare tutto il lavoro sporco ai CSS. Tuttavia e' sconsigliabile utilizzare questa tecnica, ecco l'alternativa.
Il codice ora e' piu' chiaro, anche se abbiamo reso l'HTML generato piu' articolato rispetto all'esempio dell'interpolazione. Non puo' accadere di dimenticare tag aperti o fare altri errori di markup, e abbiamo un singolo set di funzioni per modificare in maniera centralizzata il modo in cui produciamo tutto l'HTML della applicazione.
Le funzioni proposte sono solo un esempio. Nello specifico quelle che utilizzo nelle mie applicazioni sono implementate in maniera generalizzata (finiscono per essere molto simili tra di loro a parte qualche eccezione) e permettono di passare una lista variabile di attributi inizialmente, ad esempio:
Se usate il PHP dovete accontentarvi (come sempre) ma almeno avrete fatto un bel passo avanti rispetto alla generazione diretta dell'HTML.
Credo che ad oggi questo sia il miglior modo per generare HTML. In passato non era esattamente fattible, avete presente la complessita' dei layout a tabelle e tutti gli hack necessari per far funzionare le cose in ogni browser? Non rendeva le cose molto pratiche e se c'era da cambiare un colore bisognava andare a toccare il codice sorgente della applicazione! Oggi per fortuna e' diverso, ma sarebbe stato ben difficile gestire codice simile al seguente:
E' possibile rendere le cose piu' rosee creando funzioni di piu' alto livello che usano quelle di creazione dell'HTML viste sopra per avere un nuovo layer di astrazione, ma a volte viene proprio la tentazione di inventare un formato piu' semplice che venga tradotto in HTML in maniera automatica. Ad esempio in questo blog quando scrivo un post e voglio fare una lista invece di scrivere a mano i tag ul e li mi basta scrivere cosi':
Questa e' una lista:
Chiaramente e' molto meno tedioso da scrivere a mano rispetto all'utilizzo diretto dell'HTML. Questa strategia di generazione dell'HTML e' assolutamente vincente quando bisogna trasformare in HTML l'input che proviene dall'utente: in queste circostanze non e' necessario disporre della piena potenza dell'HTML, e' molto piu' importante riuscire a rappresentare in maniera immediata alcuni elementi pre impostati.
In alcune applicazioni che generano nella pagina piu' o meno sempre lo stesso tipo di elementi questo sistema di generazione potrebbe essere benissimo esteso al programma stesso. In questo caso bisogna creare una funzione che traduce il nostro nuovo linguaggio di descrizione della pagina in HTML. Il linguaggio puo' essere specializzato molto in relazione al dominio della nostra applicazione.
Ad esempio se la nostra applicazione ha molto a che fare con i tag e' pensabile che il testo
Questo approccio ha sicuramente la sua validita', anche se puo' essere opportuno utilizzarlo solo quando l'applicazione finisce per generare un output che e' composto da sotto parti identificabili in maniera chiara. Inoltre e' opportuno implementare appositi meccansimi di caching perche' la traduzione dal nuovo linguaggio all'HTML potrebbe essere abbastanza dispendiosa in termini di CPU.
Questa tecnica e' l'unica tra quelle proposte che ha il vantaggio della reale astrazione dal formato di output. Se domani voglio implementare la possibilita' di scaricare gli articoli in formato PDF in questo blog non avro' da passare dall'HTML, potro' generare il formato finale in maniera diretta traducendo il post in PDF invece che in HTML.
Approcci diversi
I metodi piu' importanti per generare l'HTML sono i seguenti:- Generazione tramite template
- Generazione per interpolazione
- Generazione tramite funzioni di output
- Generazione per traduzione da un formato piu' astratto
Generazione tramite template
L'idea del template e' quella di avere un pezzo di HTML valido, separato dal programma, che contiene all'interno dei riferimenti che indicano dove sostituire il contenuto reale per generare l'HTML finale. Ad esempio il seguente frammento di HTML potrebbe essere un template:<div>Nome: <span class="name">%name%</span></div> <div>Cognome: <span class="surname">%surname%</span></div>Il compito della applicazione e' quello di caricare tale template da un file (dal DB, o da qualunque altra parte) e sostituire i markers con il contenuto reale: la stringa %name% sara' sostituita con il nome di una persona, e cosi' via per il cognome e per le altre eventuali parti da riempire con contenuto.
Il template separa fisicamente l'HTML dal codice della applicazione e rende editabile la parte HTML anche da chi non ha alcuna competenza di programmazione. Poiche' offre questo vantaggio e perche' **fino a qualche anno fa assurdi layout fatti con le tabelle e la necessita' di specificare gli attributi di stile direttamente dentro i tag rendevano la produzione dell'HTML dall'interno della applicazione un incubo** il template e' stato considerato per un po' di tempo The Right Thing in relazione alla produzione di HTML.
Tanto e' vero che ancora oggi e' considerato un buon sistema, ma...
Il modo in cui scriviamo l'HTML grazie ai CSS e all'XHTML e' cambiato
profondamente. La struttura logica della pagina non e' piu' strettamente
legata al suo aspetto, per tale ragione i sistemi di produzione dell'HTML
alternativi sono ad oggi una soluzione piu' pratica e potente dei template.
I template hanno profondi limiti. Nelle applicazioni web piu' complesse non si tratta soltanto di sostituire contenuti in posizioni prestabilite. Liste, tag cloud e molti altri elementi di una pagina vengono prodotti partendo da alcuni dati e nulla piu' e in questi casi ovviamente i template non aiutano o finiscono per diventare un incubo di piccoli frammenti di HTML da editare singolarmente.
Interpolazione
L'interpolazione tra codice ed HTML e' la tecnica spesso usata in applicazioni PHP, per cui quest'ultimo ha supporto diretto tramite la sintassi <? ?>. Immagino che tutti coloro che stanno leggendo questo articolo sanno di cosa si tratta. Il codice PHP viene miscelato e/o emette direttamente l'HTML. Per i grossi blocchi si usa appunto la sintassi <? ?> che se ci pensate un po' su non e' antro che zucchero sintattico per chiamate alla funzione echo(). Per le parti piu' brevi viene utilizzata la funzione echo() direttamente. Molti programmi PHP generano l'HTML piu' o meno cosi' (non ho provato il codice, e' solo un esempio):<h1>Evviva lo spaghetti code</h1> <? $a = Array("pomo","pera","arancio"); foreach ($a as $ele) { $bold = (strlen($ele) > 4) ? 1 : 0; if ($bold) echo("<b>"); echo (htmlentities($ele)); if ($bold) echo("</b>"); echo("<br/>"); } ?> <small>Copyright (C) 2007 BlaBlaBla</small>Anche se e' facile e immediato purtroppo questo non e' un buon modo di programmare perche' non scala. Quando l'output da produrre diventa complesso e' difficilissimo editare questo tipo di codice, si rischia sempre di non chiudere un tag e a colpo d'occhio la struttura dell'HTML che viene generato non e' evidente. Bisogna seguire i tag uno ad uno.
Inoltre la produzione dell'HTML e' sparpagliata in tutto il codice. Se ad un certo punto si decide di emettere <strong> invece di <b> bisogna controllare ogni parte in cui c'e' un <b> e modificarla. Non c'e' alcuna centralizzazione nel modo in cui l'HTML viene prodotto.
Eppure questo modo di scrivere il codice e' molto diffuso: e' la cosa piu' immediata che si possa fare, per piccole applicazioni finisce per funzionare, e la semplificazione che ha visto l'HTML negli ultimi anni ha fatto diventare questo tipo di programmazione piu' gestibile nel lungo termine: basta emettere un po' di DIV e SPAN in relazione al contesto e poi lasciare tutto il lavoro sporco ai CSS. Tuttavia e' sconsigliabile utilizzare questa tecnica, ecco l'alternativa.
Generazione tramite funzioni di output
L'idea di base e' quella di produrre l'output utilizzando delle funzioni che generano precisi elementi HTML. Solo tali funzioni avranno la necessita' di sporcarsi le mani con l'HTML, tutto il resto del codice chiamera' le funzioni di generazione. Un semplice esempio in PHP:function ul($content) { return "<ul>$content</ul>"; }
function li($content) { return "<li>$content</li>"; }
function div($content) { return "<div>$content</div>"; }
$a = Array("pomo","pera","arancio"); $list = ""; foreach ($a as $ele) { $list .= li(htmlentities($ele)); } echo(div(ul($list)));
Il codice ora e' piu' chiaro, anche se abbiamo reso l'HTML generato piu' articolato rispetto all'esempio dell'interpolazione. Non puo' accadere di dimenticare tag aperti o fare altri errori di markup, e abbiamo un singolo set di funzioni per modificare in maniera centralizzata il modo in cui produciamo tutto l'HTML della applicazione.
Le funzioni proposte sono solo un esempio. Nello specifico quelle che utilizzo nelle mie applicazioni sono implementate in maniera generalizzata (finiscono per essere molto simili tra di loro a parte qualche eccezione) e permettono di passare una lista variabile di attributi inizialmente, ad esempio:
$mydiv = div("id","foo","class","bar",$content);produce qualcosa come
<div id="foo" class="bar"> ... content ... </div>Purtroppo il PHP non e' abbastanza potete da rendere l'annidamento piu' semplice come invece accade in Ruby:
require "cgi" cgi = CGI.new("html3") # add HTML generation methods cgi.out{ cgi.html{ cgi.head{ "\n"+cgi.title{"This Is a Test"} } + cgi.body{ "\n"+ cgi.form{"\n"+ cgi.hr + cgi.h1 { "A Form: " } + "\n"+ cgi.textarea("get_text") +"\n"+ cgi.br + cgi.submit } } } }
Anche in questo caso i Ruby blocks mostrano la loro potenza. L'unica restrizione e' che ogni blocco restituisca una stringa, per cui
all'interno del blocco ci potrebbero essere anche dei cicli o altre
strutture di controllo complesse.
Se usate il PHP dovete accontentarvi (come sempre) ma almeno avrete fatto un bel passo avanti rispetto alla generazione diretta dell'HTML.
Credo che ad oggi questo sia il miglior modo per generare HTML. In passato non era esattamente fattible, avete presente la complessita' dei layout a tabelle e tutti gli hack necessari per far funzionare le cose in ogni browser? Non rendeva le cose molto pratiche e se c'era da cambiare un colore bisognava andare a toccare il codice sorgente della applicazione! Oggi per fortuna e' diverso, ma sarebbe stato ben difficile gestire codice simile al seguente:
font("color","#ff0000","face","Verdana","Attento! Questo codice e' una m...da");Se questo e' a mio avviso il metodo di riferimento per generare HTML ne esiste pero' un quarto fondamentale in certe applicazioni: la creazione di un linguaggio di piu' alto livello che viene tradotto in HTML.
Conversioni di formato
Tutto sommato l'HTML e' tedioso da generare. Pensate ad esempio ai form, ci sono sempre le stesse cose da scrivere, gli stessi controlli da fare sull'obbligatorieta' e la formattazione dei campi.E' possibile rendere le cose piu' rosee creando funzioni di piu' alto livello che usano quelle di creazione dell'HTML viste sopra per avere un nuovo layer di astrazione, ma a volte viene proprio la tentazione di inventare un formato piu' semplice che venga tradotto in HTML in maniera automatica. Ad esempio in questo blog quando scrivo un post e voglio fare una lista invece di scrivere a mano i tag ul e li mi basta scrivere cosi':
Questa e' una lista: . uno . due . tre . e quattro Mentre questa **e' una scritta in bold**Ecco come viene reso dal programma che implementa questo blog:
Questa e' una lista:
- uno
- due
- tre
- e quattro
Chiaramente e' molto meno tedioso da scrivere a mano rispetto all'utilizzo diretto dell'HTML. Questa strategia di generazione dell'HTML e' assolutamente vincente quando bisogna trasformare in HTML l'input che proviene dall'utente: in queste circostanze non e' necessario disporre della piena potenza dell'HTML, e' molto piu' importante riuscire a rappresentare in maniera immediata alcuni elementi pre impostati.
In alcune applicazioni che generano nella pagina piu' o meno sempre lo stesso tipo di elementi questo sistema di generazione potrebbe essere benissimo esteso al programma stesso. In questo caso bisogna creare una funzione che traduce il nostro nuovo linguaggio di descrizione della pagina in HTML. Il linguaggio puo' essere specializzato molto in relazione al dominio della nostra applicazione.
Ad esempio se la nostra applicazione ha molto a che fare con i tag e' pensabile che il testo
Questi sono tre tag: [blog],[web],[html]produca direttamente tag che sono degli span con la giusta classe ed un link alla pagina in cui vengono listate le risorse relative a quel tag.
Questo approccio ha sicuramente la sua validita', anche se puo' essere opportuno utilizzarlo solo quando l'applicazione finisce per generare un output che e' composto da sotto parti identificabili in maniera chiara. Inoltre e' opportuno implementare appositi meccansimi di caching perche' la traduzione dal nuovo linguaggio all'HTML potrebbe essere abbastanza dispendiosa in termini di CPU.
Quando invece si deve implementare un wiki, un blog, o un sistema di
commenti, la traduzione da un formato piu' semplice all'HTML e'
praticamente una scelta obbligata oltre che conveniente.
Questa tecnica e' l'unica tra quelle proposte che ha il vantaggio della reale astrazione dal formato di output. Se domani voglio implementare la possibilita' di scaricare gli articoli in formato PDF in questo blog non avro' da passare dall'HTML, potro' generare il formato finale in maniera diretta traducendo il post in PDF invece che in HTML.
Do you like this article?
Subscribe to the RSS feed of this blog or use the newsletter service in order to receive a notification every time there is something of new to read here.
Note: you'll not see this box again if you are a usual reader.
Subscribe to the RSS feed of this blog or use the newsletter service in order to receive a notification every time there is something of new to read here.
Note: you'll not see this box again if you are a usual reader.
Comments
13 Apr 07, 12:53:29
@davidonzo: ottima sintesi, concordo ma non ho presente lo stile di bbcode, domani ci guardo. Grazie!
10 May 07, 03:12:51
Ciao Antirez,
Ti seguo ormai da mesi, il tuo blog è una fucina di idee! Questo articolo mi ha colpito particolarmente, in quanto il problema della generazione di HTML mi opprime da un po'.. Così mi sono rimboccato le maniche ed ho iniziato a scrivere una classe in php per implementare la `Generazione tramite funzioni di output`. La sto testando su un sito che sto sviluppando, e la trovo davvero utile.
Se può interessare a qualcuno vi posto il link, appena la ultimo.
Ti seguo ormai da mesi, il tuo blog è una fucina di idee! Questo articolo mi ha colpito particolarmente, in quanto il problema della generazione di HTML mi opprime da un po'.. Così mi sono rimboccato le maniche ed ho iniziato a scrivere una classe in php per implementare la `Generazione tramite funzioni di output`. La sto testando su un sito che sto sviluppando, e la trovo davvero utile.
Se può interessare a qualcuno vi posto il link, appena la ultimo.
Sicuramente la tecnica tramite funzioni di output è buona nella misura in cui si è in fase di programmazione e si lavora sul codice.
Se l'applicazione prevede un'interfacciabilità utente attiva (come in un blog) ho sempre trovato lo stile bbcode immediato, facile e sicuro.
Non mi va, come succede in wordpress, che si possano usare direttamente dei tag html (anche se debitamente abilitati e filtrati).
La tecnica del tag proprietario la trovo molto implementata ancora oggi per grandi applicazioni.
L'uso dei file *.tpl ti aiuta a personalizzare lo stile, ma ti da grane se vuoi personalizzare funzioni dell'applicazione. Penso resterà in voga per tutte le applicazioni non open ancora per molto tempo.