Separazione delle carriere in php

php è considerato un linguaggio “semplice” per lo sviluppo web, spesso contrapposto alle piattaforme “serie” come .NET e Java: questo è dovuto soprattutto all’uso semplice che la maggior parte degli sviluppatori ne fanno.
Ma anche in php si possono usare paradigmi di progettazione più evoluti del semplice incapsulamento nel codice html; ad esempio, si possono usare i template, per separare lo strato di visualizzazione da quello di elaborazione.
Il template è un file prototipo che non contiene (quasi) codice php e che può essere quindi gestito anche da chi non conosce il php: può essere un file html, xml, javascript o di qualunque altro tipo si voglia. La sua particolarità è quella di poter contenere eventuali segnaposto utilizzabili da php.
Il codice php può compilare il template con diverse tecniche (io ne mostrerò solo una, basata sulla funzione eval) e restituire il documento opportunamente modificato.

Ad esempio, si possono avere i tre file:

  • mondorux.php: la pagina che sarà richiesta dal browser e che controlla il processo;
  • component.php: contiene la classe Component, che incapsula il meccanismo di rendering dei contenuti;
  • template.html: il prototipo che “vestirà” mondorux.php.

Ecco il codice, che mi appresto a commentare.

template.html

<html>
    <head>
        <title>$titolo</title>
    </head>
    <body>
        <h1>$titolo</h1>
        <p>$saluto</p>
    </body>
</html>
Come si può vedere, in questa pagina html non c’è codice php, a parte quelle strane stringhe precedute da ‘$’: esse sono solo dei segnaposto (nota: questo non è l’unico modo per scrivere il template).

component.php

<?php
class Component{
    var $_template;
    var $_parameters_array;

    /* costruttore, imposta il template */
    function Component($template){
        $this->_template = str_replace("\"","\\\"",implode("",file($template)));
    }

    /* legge un array associativo di nomi di variabili e loro valori */
    function setParameters($parameters_array){
        $this->_parameters_array = $parameters_array;
    }

    /* esegue la resa del template */
    function render(){
        if(is_array($this->_parameters_array)){
            foreach($this->_parameters_array as $v_name => $v_value){
                eval("$v_name = \$v_value;");
            }
        }
        eval("\$compiled = \"".$this->_template."\";");
        return $compiled;
    }
}
?>
Questa classe (perdonate lo stile PHP4, un po’ obsoleto) incapsula il template e il meccanismo di rendering, che ruota tutto intorno alla funzione eval (nel metodo render), che valuta come codice php la stringa passata come parametro.
Il metodo getParameters raccoglie un array associativo di coppie (nome, valore) in modo che il codice cliente possa impostare i contenuti della pagina.

mondorux.php

<?php
require("component.php");
$pagina = new Component("template.html");
$pagina->setParameters(
    array(
        '$titolo' -> "Template php",
        '$saluto' -> "Ciao mondo, ma che belli i template!"
    )
);
$pagina->render();
?>

Come si può vedere, in questo codice non c’è traccia di come sarà reso il documento (in questo caso: html).

mondorux.php usa la classe Component, chiedendole di eseguire, tramite il template “template.html”, la resa dei contenuti, ossia i parametri $titolo e $saluto i cui valori sono assegnati nell’array.
Con questa tecnica abbiamo ottenuto una quasi completa separazione del codice di elaborazione (mondorux.php) dal codice di visualizzazione (template.html), implementando così il famoso (e utile) pattern Model-View-Controller.

LaTeX senza preamboli

Niente di pornografico, non è questo il luogo.

Come tutti sappiamo, LATEX è un linguaggio a marcatori per la preparazione di testi basato sul programma di composizione tipografica TEX.

Io trovo molto comodo il suo approccio WYSIWYM (What You See Is What You Mean, “ciò che vedi è ciò che intendi”) per pubblicazioni complesse e strutturate, e comodissimo il fatto che dalla compilazione di un unico documento .tex si possano ottenere prodotti dvi, ps, pdf, (x)html, docbook o persino odt, con piccoli accorgimenti nella composizione del preambolo.

Quello che trovo scomodo è invece la scrittura stessa del preambolo, che mi obbliga a ricordare una serie di comandi che non sono “What I Mean”. Per questo mi viene in aiuto LATEX stesso, perchè permette l’inclusione di file esterni nel file sorgente principale. Allora ho scritto una piccola libreria di comandi che permette di costruire di volta in volta il preambolo adatto al tipo di output che desidero.

La libreria (che ho chiamato preamble) è costituita da pochi file:

  • default.tex: un preambolo semplice, che definisce solo il tipo di documento, il titolo, l’autore e la data;
  • dvi.tex: permette la creazione di un dvi (e quindi un ps) con immagini; pensato per la compilazione mediante il comando:

    latex miodocumento.tex

  • pdf.tex: permette la creazione di un pdf ipertestuale; pensato per la compilazione mediante il comando:

    pdflatex miodocumento.tex

  • xml.tex: permette la creazione di documenti basati su xml, quali ad esempio:
    • html: htlatex miodocumento.tex
    • docbook: dblatex miodocumento.tex
    • odt: ooflatex miodocumento.tex

Il preambolo dei miei nuovi documenti diventerà semplicemente:

\input{preamble/pdf}
\makepreamble{article}{a4paper,12pt}{titolo}{autore}{oggi}
\setabstract{Una libreria per facilitare la scrittura del preambolo}
\setkeywords{LaTeX preambolo pdf html dvi odt}

La prima riga del preambolo imposta l’uso di ./preamble/pdf.tex.

Questo preambolo serve per produrre un pdf. Per cambiare il tipo di output, è sufficiente modificare la prima riga in
\input{preamble/dvi} oppure \input{preamble/xml}.

Il comando \makepreamble costruisce il preambolo per un articolo su foglio A4 con caratteri da 12 punti (i primi due parametri sono identici a quelli del comando \documentclass di LATEX), e imposta il titolo, l’autore e la data.

I comandi \setabstract e \setkeywords impostano rispettivamente le proprietà del pdf oggetto e parole chiave; anche se servono solo per il pdf, si possono lasciare nel sorgente senza danni perchè i file della libreria preamble rispettano tutti la stessa interfaccia, che definisce anche questi comandi.

Ecco come sono i sorgenti:

pdf.tex

\newcommand{\makepreamble}[5]{
 \RequirePackage{ifpdf}
 \ifpdf
   \documentclass[#2]{#1}
   \RequirePackage[hyperindex]{hyperref}
   \hypersetup{
     pdftitle={#3},
     pdfauthor={#4},
     pdfcreator={wordml2latex (Ruggero Dambra, http://www.mondorux.com)},
     colorlinks=true,
     linkcolor=red,
     anchorcolor=black,
     citecolor=green,
     filecolor=magenta,
     menucolor=black,
     urlcolor=blue,
     breaklinks=true,
     pdfstartview=FitH,
     pdfpagemode=UseOutlines
   }
   \usepackage[pdftex]{graphicx}
   \DeclareGraphicsExtensions{.pdf,.png,.jpg}
 \else
   \documentclass[#2]{#1}
   \usepackage{hyperref}
   \usepackage{graphicx}
   \DeclareGraphicsExtensions{.eps,.ps}
 \fi

 \usepackage[]{fontenc}
 \usepackage[latin1]{inputenc}
 \usepackage[italian]{babel}
 \frenchspacing
 \title{#3}
 \author{#4}
 \date{#5}
}

\newcommand{\setabstract}[1]{
 \RequirePackage{hyperref}
 \hypersetup{pdfsubject={#1}}
}

\newcommand{\setkeywords}[1]{
 \RequirePackage{hyperref}
 \hypersetup{pdfkeywords={#1}}
}

ht.tex

\newcommand{\makepreamble}[5]{
 \documentclass{#1}
 \usepackage[T1]{fontenc}
 \usepackage{hyperref}
 \usepackage{graphicx}
 \DeclareGraphicsExtensions{.gif,.png,.jpg}
 \usepackage[latin1]{inputenc}
 \usepackage[italian]{babel}
 \frenchspacing
 \title{#3}
 \author{#4}
 \date{#5}
}

\newcommand{\setabstract}[1]{}
\newcommand{\setkeywords}[1]{}

\newcommand{\href}[2]{\Link[#1]{}{} #2 \EndLink}
\newcommand{\hypertarget}[2]{\Link[]{}{#1} #2 \EndLink}
\newcommand{\hyperlink}[2]{\Link[]{#1}{} #2 \EndLink}

dvi.tex

\newcommand{\makepreamble}[5]{
 \documentclass[#2]{#1}
 \usepackage[T1]{fontenc}
 \usepackage{hyperref}
 \usepackage{graphicx}
 \DeclareGraphicsExtensions{.eps,.ps}
 \usepackage[latin1]{inputenc}
 \usepackage[italian]{babel}
 \frenchspacing
 \title{#3}
 \author{#4}
 \date{#5}
}

\newcommand{\setabstract}[1]{}
\newcommand{\setkeywords}[1]{}

default.tex

\newcommand{\makepreamble}[5]{
 \documentclass[#2]{#1}
 \title{#3}
 \author{#4}
 \date{#5}
}

\newcommand{\setabstract}[1]{}
\newcommand{\setkeywords}[1]{}

In realtà, la finalità di questa libreria non è di evitare la scrittura del preambolo, perchè prima di \begin{document} si potranno scrivere tutte le ulteriori direttive che servono al nostro documento; il vero pregio è la possibilità di modificare “al volo” quelle parti del preambolo che ottimizzano la produzione di un particolare tipo di output.

RFC: tutti i suggerimenti per migliorare sono benvenuti.

Il solito ri-tornello

Nel 2005 l’ATM (Azienda Tramviaria Milanese) incominciò la sostituzione dei vecchi tornelli per l’ingresso e l’uscita dalle stazioni della Metropolitana.

Tornello ATM

Tornello ATM

Agli utenti questa operazione fu venduta come:

  • miglioramento del servizio
  • miglioramento dell’accuratezza dei controlli
  • tecnologia più avanzata

A tre anni dall’inizio del “nuovo corso”, per gli utenti cosa è cambiato?

  • Il servizio è migliorato solo ed esclusivamente nel fatto che i nuovi terminali per la ricarica degli abbonamenti sono diffusi e, quando funzionano, veloci: insomma… ci hanno reso più facile pagare! Va bene. In cambio, la spesa per il cambiamento è pesata probabilmente sulla manutenzione di tutti gli altri sistemi, infatti i treni ora hanno una frequenza di malfunzionamenti semplicemente scandalosa (ed in continuo aumento).
  • L’accuratezza dei controlli avrebbe dovuto essere garantita dal controllo del biglietto anche in uscita; inoltre tutti, anche gli abbonati, avrebbero dovuto passare dai tornelli. La prima idea è stata subito abbandonata, forse perchè ci si è accorti che il blocco all’uscita avrebbe creato disordini vari, peraltro prevedibili. La seconda idea è in atto, con grande fastidio degli abbonati, che, mentre prima avevano un accesso veloce (basato sulla fiducia) alla stazione, ora devono mettersi in coda come tutti gli altri.
  • Ma il vero punto dolente è la tecnologia.
    I nuovi tornelli richiedono agli abbonati di far passare la tessera vicino al sensore per sbloccare il passaggio. Però c’è un eccessivo ritardo dello sblocco della sbarra dopo il riconoscimento della tessera; cosicchè può capitare, e capita spesso quando si ha fretta (e i milanesi ce l’hanno anche quando non serve), di accartocciarsi dolorosamente contro la sbarra.
    Quando la lettura della tessera fallisce, quasi sempre non è possibile rileggerla immediatamente, cosicchè bisogna farsi da parte e far procedere la coda. Di solito corre in aiuto il sensato agente di stazione che, con fare compassionevole e sconsolato, apre un varco d’ingresso per il malcapitato.
    I nuovi tornelli, essendo così all’avanguardia, sono molto delicati; così spesso sono inutilizzabili o in manutenzione.

In conclusione, considerando un sicuro aumento dei costi di manutenzione dei tornelli, un peggioramento complessivo delle prestazioni fornite agli abbonati e un “superlavoro” per l’agente di stazione, la domanda che sorge spontanea è:

“a chi è convenuto il cambiamento del sistema?”

La risposta sorge altrettanto spontanea: “all’azienda che ha l’appalto per l’installazione e soprattutto la manutenzione dei tornelli”, è ovvio.

Meno ovvio è capire chi in ATM ha deciso di mandare avanti il progetto e perchè.