giovedì, gennaio 07, 2016

Google e le ricerche di documenti in formato OpenDocument


LibreOffice cresce, e i documenti presenti "nella nuvola" sono sempre più svincolati dal monopolio di Microsoft. Bisognerebbe farlo sapere a Google, che nella propria pagina per la ricerca avanzata non propone i formati OpenDocument tra quelli presenti nella lista del tipo di file:


Strano, a dire il vero, anche perché la ricerca dei documenti LibreOffice e OpenOffice in realtà è supportata. È sufficiente aggiungere nella query di ricerca il parametro filetype:odt (oppure ods, odp, ecc.):


Basterebbe poco per cambiare l'interfaccia utente...



Licenza Creative Commons
Google e le ricerche di documenti in formato OpenDocument di Loris Tissino è distribuito con Licenza Creative Commons Attribuzione 4.0 Internazionale.

lunedì, novembre 09, 2015

Creative Commons, e se l'autore cambia idea?

Per chi se la fosse persa e fosse a digiuno di informazioni in merito alle licenze Creative Commons, segnalo l'interessante videolezione di Simone Aliprandi nell'ambito del progetto AndriaLearning curato da Francesco Leonetti.

Credo che alla trattazione manchi un punto fondamentale, quello delle variazioni dei dati nel corso della storia. Mi spiego con un esempio.

Immaginiamo che Tizio pubblichi nel 2015 un'opera nel suo sito web, attribuendo una licenza CC Share-Alike. Caio utilizza quest'opera, ne crea una derivata dopo aver consultato la licenza che lo autorizza, e la pubblica nel proprio sito web nel 2016. Fin qui, tutto bene.

Ma che cosa succede se Tizio, nel 2017, toglie dal proprio sito il riferimento alla licenza CC precedentemente applicata? Naturalmente, il comportamento sarebbe riprovevole ma non illecito (la licenza su un'opera può essere revocata, ma le opere già in circolazione rimangono con la licenza originaria); e comunque è tecnicamente fattibile. Se si tratta di un'opera che ha avuto una certa diffusione e che molti possono testimoniare di aver visto come rilasciata con licenza CC Share-Alike, nessun problema. Però immaginiamoci il caso in cui Tizio sia un autore poco noto, e che solo Caio abbia scaricato e utilizzato la sua opera. Come può fare Caio, nel 2018, a dimostrare che Tizio nel 2015 aveva pubblicato l'opera con una determinata licenza?

Il punto è che il web è stato pensato per essere costantemente aggiornato e modificabile e ciò comporta problemi non irrilevanti. Come fare, in generale, a provare che un certo contenuto, in un dato momento, era quello indicato? Una soluzione potrebbe essere quella di utilizzare servizi come archive.org o perma.cc, ma anche questi lasciano un po' a desiderare. Per dirne una, rimane il problema che ad uno stesso indirizzo di risorsa su web potrebbero corrispondere contenuti diversi a seconda di provenienza geografica della richiesta, lingua preferita nel browser, dimensioni e risoluzione dello schermo, ecc. Potrebbe ben succedere che il link ad una licenza (così come qualsiasi altro contenuto) compaia o scompaia anche a seconda del dispositivo usato per la lettura. Quindi Caio potrebbe vedere con lo smartphone che il contenuto di Tizio è rilasciato con licenza CC, mentre un'altra persona (o un servizio di archiviazione digitale automatico), anche nello stesso istante, potrebbe avere un'informazione diversa.

Insomma, possono insorgere problemi dovuti alla natura tecnica del web e al fatto che ciò che vediamo è cambiato, e non tutti i siti hanno, come Wikipedia, traccia di tutte le modifiche apportate ai contenuti. Anzi, quasi sempre queste informazioni non esistono. E l'onere della prova rimane comunque in capo a chi riutilizza l'opera.

Per completezza, riporto quanto Simone Aliprandi ha scritto nel suo libro Creative Commons: manuale operativo:
... l'utente che trova un'opera con il richiamo ad una licenza, la può riutilizzare facendo affidamento sul fatto che tale richiamo sia stato effettivamente apposto dal titolare dei diritti. Purtroppo, la comunicazione Internet non permette di tenere traccia di ogni passaggio e dunque può verificarsi la malaugurata ipotesi che il titolare dei diritti non voglia affatto rilasciare la sua opera con Creative Commons e che quindi la licenza sia stata aggiunta (in buona fede o in mala fede) da un altro soggetto non titolato a farlo.
Si tratta in verità di un caso abbastanza limite; e la dottrina giuridica comunque risolve i dilemma applicando la teoria dell'affidamento. Secondo questa teoria, un negozio giuridico è valido se vi è contrasto tra volontà e dichiarazione ma colui che riceve la dichiarazione non era in grado di accorgersi del contrasto usando l'ordinaria diligenza. 

Post modificato dopo la pubblicazione originale.

Licenza Creative Commons
Creative Commons, e se l'autore cambia idea? di Loris Tissino è distribuito con Licenza Creative Commons Attribuzione 4.0 Internazionale.

mercoledì, febbraio 18, 2015

Copia di cortesia, conforme o no?

Il recente post di Simone Aliprandi sul tema della richiesta, in alcuni tribunali, di una copia di cortesia, cartacea, di documenti consegnati on-line mi ha fatto tornare in mente una problematica che ho affrontato anni fa in tutt'altro ambito.

Il problema, ora come allora, deriva dal fatto che qualcuno (un privato, una controparte commerciale, un ente pubblico, un'istituzione: non fa differenza) chiede un documento in forma digitale, ma poi lo richiede, per propria semplicità di fruizione e di gestione, anche in forma stampata.

Immaginate un insegnante che chiede ai propri allievi di inviare il testo del compito sia via email sia consegnandone una versione cartacea; oppure l'ufficio tecnico di un comune che chiede una copia del progetto in forma di file vettoriale e una in versione stampata; oppure, come nel caso segnalato, un magistrato che, dovendo adeguarsi al nuovo processo telematico che impone la gestione degli atti tramite, appunto, l'invio telematico degli stessi, pensa bene di chiedere agli avvocati di depositare anche una copia di cortesia.

In tutti questi casi, si pone il problema del se e del come controllare la conformità dei due documenti che uno poi si trova in mano.

Che cosa succede, infatti, se un giudice decide in una causa alla luce di quanto trova stampato in un documento, e la copia cartacea dello stesso è diversa da quella depositata digitalmente? se il progetto per un nuovo edificio viene approvato in base a quanto l'impiegato vede nella versione cartacea dello stesso, con informazioni diverse rispetto a quelle presenti nel file inviato digitalmente? se l'insegnante mette un voto in base a quanto trova scritto nel documento inviato via email (giusto per fare l'esempio opposto) ma poi archivia quello ottenuto in versione cartacea?

Voglio trascurare qui il caso di chi - intenzionalmente e fraudolentemente - consegna due documenti diversi in una forma e nell'altra. La domanda piuttosto è: potrebbe succedere che, per mero errore materiale, le due copie non coincidano, oppure non appaiano allo stesso modo? La mia risposta è: certo. Alcuni casi plausibili, tutti con alla base comportamenti in piena buona fede, potrebbero essere i seguenti:

  • Tizio ha nel disco del computer due documenti, diciamo DocumentoA_versione1.pdf e DocumentoA_versione2.pdf. Invia telematicamente il primo e stampa, alcuni minuti dopo, il secondo.
  • Tizio sta lavorando su DocumentoA_versione_finale.odt. Il documento è ancora aperto e con alcune piccole modifiche non ancora salvate. Tizio non se ne accorge, effettua l'invio telematico, poi salva il documento con le modifiche e lo stampa.
  • Tizio sta lavorando su DocumentoA_versione_finale.odt. Stampa il documento, si accorge di qualche piccolo errore di battitura (un accento sbagliato, una virgola mancante), corregge il documento e invia telematicamente la versione corretta.
  • Il documento che Tizio sta guardando con il proprio calcolatore è una pagina web. La stampa. Poi salva la pagina web su disco, senza sapere che nelle pagine web è possibile (molto spesso accade) fare in modo che alcune parti vengano visualizzate o meno a seconda che lo strumento di fruizione sia una stampante o uno schermo.  
  • Il documento che Tizio ha sotto gli occhi è un file PDF, in cui tutto il testo è selezionabile / visibile / copiabile / elaborabile, anche quello con una pecetta nera che copre alcune scritte. Stampandolo, quelle scritte rimangono nere, perse per sempre. (Forse qualcuno si ricorda del caso del documento CIA declassificato dai lettori?)
  • Il documento PDF che Tizio ha sotto gli occhi contiene un'immagine posta sul bordo del foglio, con un particolare molto importante proprio vicino all'estremità della pagina. Nella versione stampata, consegnata a Caio, quel dettaglio manca, perché la stampante ha un margine di uno o due centimetri in cui non riesce a stampare. Caio vedrà il dettaglio o no? (I file PDF possono presentare molti altri problemi, ad esempio in caso di risoluzione non adeguata alla stampa, colori non adatti, font non incorporati, ecc.)
  • Il documento di Tizio ha qualche forma di intelligenza che lo rende diverso ogni volta che viene aperto. Non ci vuole granché: basta una formula di un foglio elettronico che si basi sul valore di ADESSO() o un piè di pagina di un documento che riporta la data corrente. Chi aprirà il documento si troverà qualcosa di diverso rispetto alla versione stampata.
  • Tizio invia un documento in forma telematica a Caio, e poi gli consegna anche una versione cartacea. Caio non considera la copia cartacea e legge il documento inviatogli digitalmente, dove però, in forma di revisione non cancellata, compare del testo non presente nel documento stampato. Tizio si lamenta quando scopre che Caio ha letto delle informazioni che nella versione cartacea non c'erano.

Tutti questi sono casi perfettamente plausibili di mancanza di conformità tra il documento in formato digitale e quello stampato. Quale dei due dovrebbe avere valore probatorio / legale?

Licenza Creative Commons
Copia di cortesia, conforme o no? di Loris Tissino è distribuito con Licenza Creative Commons Attribuzione 4.0 Internazionale.

domenica, ottobre 05, 2014

Programmazione in basic con LibreOffice

Se si vogliono fare degli esercizi di programmazione con strumenti multipiattaforma e senza avere la necessità di un ambiente di sviluppo troppo complesso, tra le alternative a disposizione c'è la suite LibreOffice / OpenOffice, che mette a disposizione un editor di macro e uno strumento di progettazione di finestre di dialogo che possono fare al caso nostro per piccoli esperimenti.

Quanto segue è stato testato su LibreOffice 4.2.6.3, ma dovrebbe funzionare senza problemi anche con altre versioni di LibreOffice / OpenOffice.

Creiamo un documento contenitore

Possiamo salvare il codice della nostra miniapplicazione sia nell'ambito del nostro spazio di lavoro personale sia in specifici documenti. Se vogliamo poter utilizzare ovunque il nostro codice, dovremo scegliere la seconda opzione.

Quindi, partiamo con il salvare un documento Calc (un foglio elettronico) con un nome, come ad esempio ProgrammareLOconVB.ods. Questo documento conterrà i nostri dati ma anche il codice che scriveremo e le finestre di dialogo che prepareremo.

Creare una finestra di dialogo

Per creare una finestra di dialogo, fare clic su Strumenti / Macro / Organizza finestre di dialogo....

Ci appare una finestra in cui possiamo lavorare con le nostre finestre di dialogo. Visto che ancora non ne abbiamo una, dobbiamo:

  1. selezionare il contenitore Standard del documento su cui stiamo lavorando;
  2. fare clic su Nuovo...;
  3. assegnare un nome alla finestra di dialogo (ad esempio, ShoppingListManager);
  4. fare clic su Modifica.

Si dovrebbe aprire l'editor delle finestre di dialogo, come nella seguente immagine:



Abbiamo a disposizione un insieme di controlli che potremo disporre nella finestra:



Se per caso non dovesse comparire, fare clic su Visualizza / Barre degli strumenti / Casella degli strumenti.

Aggiungere qualche controllo

Nella finestra di dialogo, aggiungiamo tre controlli, per preparare un esempio semplice: vogliamo una casella di testo in cui l'utente possa preparare una lista della spesa, scrivendo degli elementi in una casella di testo che verranno via via aggiunti alla lista (alla pressione di un pulsante).

Quando si seleziona un controllo, nella parte sinistra della finestra compare una scheda dove si possono definire le diverse proprietà. Attribuiamo un nome ai nostri tre controlli e impostiamo altre proprietà che desideriamo. Per selezionare la finestra di dialogo e cambiarne le proprietà, bisogna fare clic sul suo margine esterno.

Il risultato finale potrebbe essere simile al seguente:



Sono stati attribuiti i seguenti nomi ai controlli:

  • txtItem
  • cmdAddToItem
  • lstShoppingList

Far apparire la finestra

Il codice per far apparire la finestra, come riportato nel wiki di OpenOffice, è il seguente:

Dim oDialog AS Object

Sub StartShoppingListManagerDialog
  Dim oLibContainer As Object, oLib As Object
  Dim oInputStreamProvider As Object
  Const sLibName = "Standard"
  Const sDialogName = "ShoppingListManager"
  ' library container
  oLibContainer = DialogLibraries
  ' load the library
  oLibContainer.loadLibrary( sLibName )
  ' get library
  oLib = oLibContainer.getByName( sLibName )
  ' get input stream provider
  oInputStreamProvider = oLib.getByName( sDialogName )
  ' create dialog control
  oDialog = CreateUnoDialog( oInputStreamProvider )
  ' show the dialog
  oDialog.execute()
End Sub

Dove dobbiamo inserirlo? In un modulo, naturalmente. Nel documento Calc, fare clic su Strumenti / Macro / Organizza macro / LibreOffice Basic....
Selezionare il documento Calc, e fare clic su Nuovo. Viene chiesto un nome per il modulo. Possiamo confermare il nome Modulo1.
Sostituire il codice presente con quello riportato qui sopra. Si dovrebbe ottenere qualcosa di simile a questo:




Siamo pronti per far apparire la finestra di dialogo. È sufficiente, nel foglio di lavoro, fare clic su Strumenti / Macro / Esegui macro..., selezionare la macro StartShoppingListManagerDialog e fare clic su Esegui.

Se vogliamo, possiamo aggiungere un pulsante e un gestore di eventi al foglio elettronico Calc, in modo da velocizzare l'operazione. In Calc, far visualizzare i controlli per formulario (Visualizza / Barre degli strumenti / Controlli per il formulario), selezionare tra essi il pulsante e posizionarlo nel foglio di lavoro. Facendoci clic con il pulsante destro del mouse, si attiva la scheda per la definizione delle proprietà e degli eventi. Impostare un nome e un testo da far comparire; poi, nella scheda eventi, associare all'evento "Eseguire l'azione" la procedura di avvio della finestra di dialogo.



Attenzione: per poter provare il funzionamento del pulsante che abbiamo definito, bisogna fare clic su Modo bozza (sì/no) della barra degli strumenti Controlli del formulario.

Gestire gli eventi della finestra

Nella finestra di dialogo, possiamo associare al pulsante una macro per gestire l'evento "Eseguire l'azione". Visto che desideriamo che il valore presente nel campo di testo venga aggiunto alla lista, il codice sarà simile al seguente:

Sub cmdAddToList_click

  Dim txtItem as Object, lstShoppingList as Object
  txtItem = oDialog.getControl("txtItem")
  lstShoppingList = oDialog.getControl("lstShoppingList")

  lstShoppingList.addItem(txtItem.Text, lstShoppingList.getItemCount())

  txtItem.setText("")
  txtItem.setFocus()

End Sub

Dovremo poi associare la macro all'evento "Eseguire l'azione" del pulsante, come visto precedentemente.

Ulteriori informazioni

Una descrizione degli eventi gestibili per i vari controlli è disponibile nel wiki di LibreOffice.

Informazioni sulle proprietà e i metodi di caselle di riepilogo e caselle di testo sono nel wiki di OpenOffice.

Quando un oggetto viene istanziato, è possibile verificarne a tempo di esecuzione quali sono le sue proprietà, i suoi metodi e le sue interfacce.

Ad esempio, avendo a disposizione il nostro oggetto txtItem, potremo aggiungere al nostro codice

  MsgBox txtItem.dbg_methods
  MsgBox txtItem.dbg_supportedInterfaces
  MsgBox txtItem.dbg_properties
 
e far comparire i messaggi informativi che ci servono.

Note sulla sicurezza

L'esecuzione di una macro di cui non si conosce la provenienza è potenzialmente pericolosa. Per questo motivo, in LibreOffice / OpenOffice è disattivata.
Facendo clic su Strumenti / Opzioni / LibreOffice / Sicurezza e poi sul pulsante Sicurezza delle macro... viene offerta la possibilità di configurare il livello appropriato. Se si ricevono documenti con delle macro, ricordarsi di controllarne sempre il contenuto prima di eseguirle (impostando il livello di sicurezza su "Medio", all'apertura del documento viene chiesto se si vogliono eseguire, e potremo rispondere di no per dare un'occhiata al codice).

Esportazione del codice sorgente

Se si desidera esportare il codice sorgente di un'applicazione, ad esempio per utilizzare un sistema di controllo di versione, è possibile sfruttare il fatto che i file ods sono semplici file zip con all'interno dei documenti XML. In particolare, troveremo all'interno del file ods un file XML per ogni modulo visual basic e per ogni finestra di dialogo impostata.



File di esempio

Il file completo, ProgrammareLOconVB.ods, è disponibile nella sezione didattica / foglio elettronico del mio sito.

domenica, agosto 03, 2014

Le Frecce senz'apostrofo e senza trattini

Avete mai provato ad acquistare un biglietto ferroviario online, nel sito delle Frecce? La cosa è abbastanza semplice se, come capita a me, nome e cognome non comprendono caratteri particolari, dove per "particolare" intendo qualsiasi cosa non appartenga all'alfabeto latino/inglese A-Z. Quindi, ad esempio, niente lettere accentate e niente apostrofi.

Al momento della compilazione del campo del cognome, infatti, viene richiamato un piccolo codice Javascript che elimina i caratteri non validi. Immaginate di avere un cognome contenente un apostrofo e un trattino. L'apostrofo non riuscite a digitarlo, mentre il trattino è consentito.



Tutto bene? No, perché al momento del passaggio alla fase di pagamento non si riesce a procedere, ed un messaggio avverte che "Credentiale non e valido" (sic).


Che cosa si debba intendere per "credenziale", perché non sia valida, o come risolvere il problema non è dato sapere. Fra l'altro, dopo dieci minuti la sessione scade, e bisogna ricominciare tutto da capo, a partire dalla selezione delle stazioni di partenza e di arrivo.

Alla fine, l'acquisto è andato a buon fine, ma solo perché sono stati eliminati i trattini.



sabato, giugno 28, 2014

Visualizzazione di algoritmi

Bellissimo il post Visualizing Algorithms di Mike Bostock, che introduce con degli ottimi esempi l'importanza della visualizzazione dei risultati di un algoritmo, del grado di correttezza dello stesso o, semplicemente, dei passi che sono stati necessari per ottenere un determinato risultato.

Nella prima parte, dedicata alle tecniche di campionamento, Mike illustra tre diversi algoritmi per la generazione casuale di punti all'interno di un rettangolo, che si desiderano distribuiti in maniera da evitare pattern riconoscibili. Oltre a visualizzare il risultato, si può visualizzare a colpo d'occhio la bontà del risultato raggiunto. Si confrontino ad esempio queste due immagini

 

nelle quali le macchie più scure rappresentano le aree sottocampionate, e quelle più chiare le aree sovracampionate. Ci si rende conto facilmente che l'algoritmo alla base della seconda immagine è migliore.

Nella seconda parte, un'immagine mostra meglio di mille parole quale problema può nascere dall'utilizzo di un algoritmo usato per un mescolamento casuale di un mazzo di carte (o di qualsiasi altra cosa):

Se l'obiettivo è di avere una distribuzione equiprobabile delle carte, ci possiamo rendere conto, semplicemente visualizzando con diversi colori la distanza dall'obiettivo, quanto siamo lontani da un'implementazione corretta.

Nella terza parte Mark mostra come si possa visualizzare l'esecuzione "passo passo" di un algoritmo, tracciando un grafico che rappresenta la serie di scambi di un quick sort.

Nella quarta parte, forse la più divertente da vedere, sono poi presentati diversi algoritmi per la generazione di labirinti, con una rappresentazione di alberi e della lunghezza dei singoli percorsi basata su una scala di colori.

Come dice Mark, la visualizzazione degli algoritmi può essere un valido ausilio per l'intrattenimento (è divertente vedere gli algoritmi all'opera), per l'insegnamento, per il debugging e per la costruzione di un'interfaccia utente per l'input di dati che sono collegati reciprocamente tra di loro, come nel caso della scelta tra acquisto di una casa o affitto della stessa. Come dargli torto?


giovedì, giugno 05, 2014

Fatture in formato XML

Da domani chiunque emetterà fatture verso gli organi centrali della pubblica amministrazione in Italia, dovrà obbligatoriamente predisporre la fattura in formato XML.

Il Governo ha anche preparato un sito internet, www.fatturapa.gov.it, che offre la necessaria documentazione. E fin qui tutto bene.

Ma se si vanno a leggere le specifiche, si può vedere che tutti gli elementi previsti dal DTD sono in italiano, o in alcuni casi in un innaturale mix italiano-inglese. L'esempio di una fattura singola con una sola linea di fattura prevede elementi di questo tipo:


<CedentePrestatore>
<DatiAnagrafici>
<IdFiscaleIVA>
<IdPaese>IT</IdPaese>
<IdCodice>01234567890</IdCodice>
</IdFiscaleIVA>
<Anagrafica>
<Denominazione>Societa' alpha S.r.l.</Denominazione>
</Anagrafica>
<RegimeFiscale>RF01</RegimeFiscale>
</DatiAnagrafici>
<Sede>
<Indirizzo>Via Roma</Indirizzo>
<CAP>00166</CAP>
<Comune>Roma</Comune>
<Provincia>RM</Provincia>
<Nazione>IT</Nazione>
</Sede>
<StabileOrganizzazione>
<Indirizzo>Piazza Garibaldi</Indirizzo>
<CAP>00100</CAP>
<Comune>Roma</Comune>
<Provincia>RM</Provincia>
<Nazione>IT</Nazione>
</StabileOrganizzazione>
</CedentePrestatore>

racchiusi in improbabili elementi quali

FatturaElettronicaHeader e FatturaElettronicaBody.

Non sarebbe stato molto meglio avere uno standard informatico in inglese, magari condiviso a livello europeo / internazionale, in modo da agevolare la predisposizione di strumenti software comuni? Va bene la salvaguardia della lingua nazionale, ma questa dovrebbe riguardare l'interfaccia delle applicazioni, non la definizione degli standard con cui sono rappresentati i dati. Provate a pensarci: se un programmatore italiano volesse sviluppare un'applicazione per la generazione di fatture in formato XML per i vari paesi dell'Unione Europea, dovrebbe preoccuparsi di imparare il maltese, il finlandese, l'estone, il lituano, il greco, ecc.?

E poi, magari qualche standard per la definizione in formato XML delle fatture esiste. Per citarne uno, quello preparato dal Consorzio non-profit OASIS, disponibile all'indirizzo docs.oasis-open.org/ubl/os-UBL-2.1/UBL-2.1.html#T-INVOICE. Per quale motivo non si è seguito quello standard? Mi riprometto di indagare, ma per adesso noto che tra le FAQ non ci sono notizie in merito. (Se avete informazioni, segnalatemele e aggiornerò volentieri questo post.)


venerdì, dicembre 27, 2013

XML, JSON, ecc.

Pubblico questo post per presentare qualche semplice esempio di informazioni inviate da un server web ad un client in diversi formati.

L'esperienza comune degli utenti è l'interazione con un server web mediata da un browser. Il browser agisce come client, chiedendo una risorsa, il server gliela manda. La risorsa, tipicamente, consiste in un documento ipertestuale (una pagina web), oppure un file binario (un'immagine, un file PDF, ecc.).

Se si tratta di un file binario, esso viene presentato all'utente mediante qualche programma di visualizzazione (spesso integrato nel browser come plugin, o direttamente in esso incorporato). Le pagine HTML vengono semplicemente "rese".

Sempre più spesso, però, capita che le informazioni inviate dal server debbano essere elaborate da un'applicazione sul lato client, per i fini più diversi. Non solo rese, ma elaborate: questo significa che il modo in cui le informazioni arrivano sia studiato in modo che i dati siano facilmente elaborabili.

Immaginiamo che un server debba inviare l'elenco dei libri disponibili per il prestito, il cui autore è Manzoni.

Potrebbe inviare un testo semplice, con i titoli uno sotto l'altro:

Content-type: text/plain

Il Conte di Carmagnola
Adelchi
I promessi sposi

Oppure potrebbe inviare un file codificato in XML:

Content-type: text/xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book id="123"><title>Il Conte di Carmagnola</book>
  <book id="456"><title>Adelchi</book>
  <book id="789"><title>I promessi sposi</book>
</books>

Oppure ancora, inviare gli stessi dati in formato JSON:

Content-type: application/json

[{"id":123,"title":"Il Conte di Carmagnola"},{"id":456,"title":"Adelchi"},{"id":789,"title":"I promessi sposi"}]

Ci sono vantaggi e svantaggi nella scelta di una di queste soluzioni. Negli ultimi anni sta prendendo sempre più piede il formato JSON, anche in virtù del fatto che sia la codifica sia la decodifica di strutture dati da / verso questo formato è agevole in tutti i linguaggi di programmazione moderni, sia perché spesso ad elaborare i dati lato client sono applicazioni JavaScript, che trovano i dati disponibili in formato nativo.


lunedì, ottobre 28, 2013

Web application deployment with git-ftp

This post has been updated after its initial publication.

In web application development, it happens sometimes that you are stuck with an only way to upload files on your webserver: FTP. If you are used to push changes to a git server like and then pull the changes on your webserver through a SSH connection, there are chances you just can't do that.

I had this problem recently, but I luckily found a very nice shell, git-ftp, that allows me to push changes to the webserver via FTP, recognizing all the files that I updated (or added, or deleted) on my local git repository.

My development / deployment cycle goes now simply like this:

$ # the ordinary "git" stuff...:
$ git add files_to_add

$ git rm files_to_remove
$ git commit -a -m 'description of the changes'
$ git push

$ # now push the changes on the deployment server:
$ git-ftp push

The credentials that have to be used to access the deployment server are stored with the ordinary git config command. From the man page of git-ftp:

$ git config git-ftp.user john
$ git config git-ftp.url ftp.example.com
$ git config git-ftp.password secr3t
$ git config git-ftp.syncroot path/dir
$ git config git-ftp.cacert caCertStore
$ git config git-ftp.deployedsha1file mySHA1File
$ git config git-ftp.insecure 1

You can also use git-ftp in dry-mode, to just see what would happen, and in verbose mode, if you are curious about what actually happens.

Update: for a different project, I needed to use sftp, which is not supported by libcurl with a default Ubuntu installation. Anyway, I followed the instructions found on zeroset and I managed to have it working with no problems.

domenica, settembre 29, 2013

Treno + bici, assurdità tutte italiane

Viaggiare in treno con la bicicletta al seguito può essere un'esperienza molto piacevole, visto che si possono esplorare luoghi relativamente lontani sfruttando due tra i mezzi di trasporto più ecologici.

Purtroppo, per motivi che solo in Italia credo possano esistere, l'esperienza viene resa inutilmente difficoltosa.

1. Al momento della pianificazione del viaggio, bisogna naturalmente scegliere i treni giusti, ossia quelli che consentono il trasporto della bicicletta. Il sito di Trenitalia non consente, nemmeno accedendo alle opzioni avanzate, di effettuare una ricerca dei treni adibiti al trasporto biciclette:


I ciclisti italiani sanno, grazie ad un salutare passaparola, che per ottenere l'informazione desiderata si può però consultare il sito delle ferrovie tedesche, anche in italiano, il quale mostra gli orari di tutta Europa, con l'agognata casellina su cui mettere il desiderato segno di spunta:


2. Al momento di fare il biglietto, bisogna considerare che, per motivi misteriosi che qualcuno dovrebbe spiegare, le emettitrici automatiche presenti in tutte le stazioni non consentono l'acquisto del supplemento bici. Quindi, armatevi di pazienza e mettetevi in fila allo sportello (se è aperto dovete farlo, visto che la regola di acquistare il biglietto in treno senza sovrapprezzo vale solo quando in stazione lo sportello non c'è oppure è chiuso).

3. L'accessibilità delle stazioni ferroviare italiane (e dei treni stessi, a dire il vero) è quella che è, lo sappiamo. Dappertutto troviamo i cartelli "Vietato attraversare i binari. Servirsi del sottopassaggio". Basta aver fatto un viaggio piccolo piccolo al di là delle Alpi per capire che i sottopassaggi a cui si può accedere solo scendendo e salendo dei gradini non sono il massimo che la vita può offrire (soprattutto se la bicicletta è carica con qualche bagaglio sulle borse). Tra l'altro, l'accessibilità riguarda anche persone che devono usare una sedia a rotelle, genitori con un passeggino, ecc. Ma in Italia, naturalmente, le priorità sono altre.

4. Una volta arrivati al binario, rimane un ultimo problema da affrontare. Dove sarà la carrozza adibita al trasporto delle biciclette? In testa o in coda al treno? Non c'è modo di saperlo, perché evidentemente sarebbe troppo difficile comunicare questa informazione negli annunci audio, o nei display dove sono elencati i treni in arrivo/partenza. Quindi, non rimane che tirare una monetina e sperare di azzeccarci. Se non avete fortuna, e vi siete messi in coda quando invece la carrozza portabici è in testa, dovrete correre velocemente sul binario per arrivare a caricare il vostro mezzo in tempo. Però attenzione: non potete pedalare sul marciapiede.

Insomma: meno male che «Trenitalia da sempre si impegna per favorire chi sceglie di sostenere l’ambiente per viaggiare, forte della convinzione che treno+bici sia la soluzione di viaggio più eco-friendly, oltre che sempre più trendy», come afferma il sito web dell'azienda. Figuratevi altrimenti.


venerdì, agosto 30, 2013

PHP - Introduzione alle lezioni

Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

Introduzione

Le lezioni di questo corso sono strutturate con una serie di esempi e di esercizi per tuffarsi nel modo dello sviluppo di applicazioni web con PHP.
L'idea è di non presentare sistematicamente tutto ciò che serve: c'è molta altra documentazione al riguardo, a partire da www.php.net/manual e uno dei principi di base è quello di "non reinventare la ruota". Piuttosto, preferisco procedere per raffinamenti successivi, con refactoring costante delle cose prodotte.
Tenderei anche ad iniziare (quasi) fin da subito un'impostazione basata sull'approccio MVC (model/view/controller) e sul test-driven development, in modo da facilitare il passaggio allo sviluppo basato sull'uso di framework (personalmente, uso e raccomando symfony, ma molti concetti sono applicabili comunque).
La raccolta di esempi e di esercizi presentata qui viene normalmente integrata con spiegazioni in aula, quindi può essere che non tutto sia sempre chiaro se ci si basa solo su quanto letto qui. Se servono integrazioni, o se trovate errori, segnalatemelo.

Alcune buone pratiche

Riporto qui alcune buone pratiche per lo sviluppo di applicazioni web che mi vengono in mente basandomi sulla mia esperienza personale e su qualche buona lettura. Non c'è un ordine di priorità particolare, e probabilmente alcune cose dovranno essere aggiunte. Tra l'altro, ammetto di non riuscire a seguirle tutte neppure io. Ad ogni modo, sono i miei due centesimi...

  1. usare il design pattern MVC (model-view-controller)
  2. sviluppare codice sorgente in inglese: è meglio setSurname() di setCognome(), soprattutto se poi si chiede aiuto in un qualche tipo di forum internazionale
  3. usare strumenti che consentono l'internazionalizzazione (i18n) e la localizzazione (l10n) del codice
  4. essere ben disposti verso il refactoring
  5. usare un sistema di controllo versione (SVN, GIT...)
  6. scrivere il codice seguendo degli standard precisi (vedere, ad esempio, quelli di symfony, oppure quelle del progetto o del team in cui si è coinvolti)
  7. scrivere codice commentato
  8. scrivere codice autoesplicativo (pensare ai nomi delle funzioni e dei parametri)
  9. produrre documentazione con phpDoc o sistemi equivalenti
  10. lavorare con dati di esempio da ricaricare per ogni test (fixtures)
  11. predisporre test unitari
  12. predisporre test funzionali
  13. usare librerie di astrazione dal database
  14. usare librerie ORM (object-relational-mapping)
  15. usare framework di sviluppo per non reinventare la ruota
  16. usare un'interfaccia fluente per gran parte delle funzioni di una classe (tutti i setters, come minimo)
  17. non usare il metodo GET per cambiare lo stato delle informazioni sul server (niente link "normali" per cancellare un articolo, ad esempio)
  18. gestire le eccezioni con blocchi try... catch per tutte le operazioni che potenzialmente possono non andare a buon fine
  19. impostare l'error_reporting a E_ALL, e inizializzare tutte le variabili esplicitamente
  20. seguire le pratiche dell'usabilità, dell'accessibilità e dell'ottimizzazione per i motori di ricerca
Nell'ambito dell'uso di symfony, inoltre, vale sicuramente la pena di dare un'occhiata alle trenta buone pratiche raccomandate da Nicolas Perriault.

Nota per i puristi

In molti casi gli esempi iniziano con un codice come il seguente:

<pre>
<?php
    // istruzioni...

Ovviamente, il codice generato non è HTML valido, poiché mancano molti elementi obbligatori e il marcatore di chiusura </pre>.

Visto che l'obiettivo è di visualizzare semplice testo, però, questa è una soluzione accettabile.
La soluzione teoricamente corretta sarebbe di scrivere, invece:

<?php
  header('Content-Type: text/plain');
  // istruzioni...


Il problema di questa soluzione è che i browser dovrebbero rappresentare il contenuto come testo semplice, ma ce n'è uno, fornito di default con un noto sistema operativo, che non si comporta così, e tenta di rappresentare il testo in altro modo, oppure di aprire il contenuto con altri programmi...

Php - Alcune cose sulle variabili

Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

Ambito di validità delle variabili

Esistono diversi ambiti di validità (scope) di una variabile:
  • locale (la variabile è visibile solo nella funzione in cui è definita)
  • globale (la variabile è definita fuori dalla funzione, ma è specificatamente richiamata)
  • superglobale (la variabile è accessibile ovunque senza bisogno di specificazioni
A differenza di altri linguaggi:
  1. le variabili globali non sono visibili, in assenza di specificazione, all'interno di una funzione (come invece succede, ad esempio, in Pascal);
  2. non esiste uno scope per un blocco (come invece succede, ad esempio, in C).

Si consideri il seguente frammento di codice:

ini_set('error_reporting', E_ALL);
function foo()
{
  echo $k;
}
$k=1;
foo();

Quello che si ottiene è:
Notice:  Undefined variable: k in ... on line ...
Se si deve usare la variabile globale all'interno della funzione (anche se non è una buona pratica), ci sono due possibilità.

La prima è di dichiararla esplicitamente come globale:

function foo()
{
  global $k;
  echo $k;
}
$k=1;
foo();

La seconda è di usare l'array globale $GLOBALS:

function foo()
{
  echo $GLOBALS['k'];
}
$k=1;
foo();

Le variabili superglobali

Alcuni array speciali mettono a disposizione di tutte le funzioni valori specifici collegati all'ambiente di esecuzione ($_ENV), ai valori inviati dal browser ($_GET, $_POST, ecc.). In linea di massima, è bene evitare di accedere direttamente a queste variabili e utilizzare invece delle classi che si occupano di fornire i dati in forma "controllata".

Ad esempio, si consideri di usare un codice simile a questo:

class WebRequest
{
  public function getParameter($name, $default=null)
  {
    if (array_key_exists($name, $_GET))
    {
      return htmlentities($_GET[$name]);
      // eventualmente qui si possono aggiungere altre sostituzioni...
    }
    else
    {
      return $default;
    }
  }
}

$request = new WebRequest();
echo 'con pulizia: ' . $request->getParameter('bar') . "\n";
echo 'senza pulizia: ' . $_GET['bar'] . "\n";

Richiamando il codice con una query string di questo tipo:

?bar=5>3

si otterrà:

con pulizia: 5&gt;3
senza pulizia: 5>3

con evidenti vantaggi in termini di sicurezza (e con il bonus di poter specificare dei valori di default).

Nota storica: in vecchie versioni di PHP (precedenti alla versione 4.2.0), l'impostazione predefinita (register_globals=on) faceva sì che venissero automaticamente create delle variabili con il nome del parametro ($bar nell'esempio). Questa impostazione è deprecata per motivi di sicurezza, ma è bene conoscerla per il caso in cui ci si debba cimentare nella manutenzione/sostituzione di vecchio software.

Variabili statiche

Una funzione può contenere variabili statiche:

function baz()
{
  static $number;
  $number++;
  return 'foo ' . $number . "\n";
}
echo baz();
echo baz();
echo baz();

produce
foo 1
foo 2
foo 3

Variabili di variabili

Una variabile può contenere il nome di un'altra variabile:

$name="Mario";
$var='name';
echo $$var . "\n"; 
produce

Mario

Nota: il meccanismo funziona anche con diversi livelli di indirezione.

La funzione eval()

Con la funzione eval() si possono eseguire istruzioni costruite al volo:

$expression='$a=5+3;';
eval($expression);
echo $a . "\n";

Attenzione: è bene non abusare di queste cose, che minano la sicurezza del codice e ne mettono a rischio la portabilità. «Se eval() è la risposta, vuol dire che quasi certamente hai posto la domanda sbagliata.» (attribuita a Rasmus Lerdorf)

PHP - Appunti sulla progettazione


Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

Fasi di progettazione

Le fasi di progettazione di una base di dati e di una o più applicazioni utente che su di essa si basano dovrebbero essere le seguenti:
  • progettazione logica, che porta ad un diagramma entità/relazioni
  • progettazione delle tabelle, che porta allo schema relazionale
  • implementazione concreta, che porta alle istruzioni DDL (o equivalenti) per la progettazione delle tabelle con i relativi campi

Consigli per la progettazione delle tabelle

Mantenere la coerenza nei nomi

Bisognerà adottare uno schema per i nomi delle tabelle e dei nomi dei campi ed applicarlo in maniera coerente. Ad esempio, non sembrano coerenti questi nomi di tabelle:
  • Clientifornitori (o scegliamo Clienti e Fornitori, oppure clienti e fornitori)
  • ClientiFornitoriFattura (per i nomi delle tabelle usiamo sempre il plurale o sempre il singolare)
  • CustomersFornitoriInvoices (usiamo nomi in italiano o in inglese, non mescolati)
  • customer_typesubjectTypeBookType (underscore, camelCase o tutte le iniziali in maiuscolo)

Non andare in cerca di guai

In generale, è opportuno limitarsi a nomi di tabelle e nomi di campi:
  • senza spazi
  • senza caratteri fuori dall'insieme [A-Za-z0-9], più eventualmente il simbolo di sottolineatura

Usare dati di prova

Per verificare di aver progettato correttamente le tabelle, è opportuno inserire dei dati di prova:
  • significativi (ad esempio, tenendo in considerazione ipotetici casi limite, o valori fuori dal comune)
  • in numero adeguato (se voglio verificare come si presenta l'interfaccia utente quando ci sono tanti clienti, è bene che nei dati di prova ci siano tanti clienti; viene naturale pensare anche ad una generazione automatica, con numeri progressivi )
  • facili da importare (per poter ripristinare una situazione iniziale, nel caso in cui si commettano degli errori).

PHP - PUT e DELETE tramite Javascript


Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

Limiti dei browser

Normalmente i browser implementano solo i metodi GET e POST. Se si prepara un form con l'attributo method che non vale "GET" o "POST" il browser fa una richiesta tramite GET.

Utilizzare Javascript per PUT e DELETE

Se si vuole fare un PUT o un DELETE si può però chiedere al browser di utilizzare Javascript. Questo codice, con un po' di adattamenti, è preso da "Not just Post and Get".

<html>
<title>HTTP Methods example</title>
<head>
<script language="Javascript">
<!--
var xmlhttp;
function execute($method,$url)
{
  xmlhttp=new XMLHttpRequest();
  xmlhttp.open($method,$url,true)
  xmlhttp.send(null);
}

function testmethod($method)
{
  alert('Executing ' + $method + '...');
  execute($method, 'info.php');
}
-->
</script>
</head>
<body>
<?php foreach(array('get', 'post', 'put', 'delete') as $method): ?>
    <input 
        type="button" 
        value="<?php echo $method ?>" 
        onclick="testmethod('<?php echo $method ?>');" 
    />
<?php endforeach ?>
</body>
</html>

Il codice HTML che si ottiene per il body è il seguente:
<body>
 <input 
  type="button" 
  value="get" 
  onclick="testmethod('get');" 
 />
 <input 
  type="button" 
  value="post" 
  onclick="testmethod('post');" 
 />
 <input 
  type="button" 
  value="put" 
  onclick="testmethod('put');" 
 />
 <input 
  type="button" 
  value="delete" 
  onclick="testmethod('delete');" 
 />
</body>
Lo script PHP che riceve i dati può limitarsi, giusto per darci la conferma che i metodi PUT o DELETE sono stati ricevuti, a scrivere una specie di file di log:

<?php
// file info.php
$fp= fopen('log.txt', 'a');
fwrite($fp, $_SERVER['REQUEST_METHOD']. "\n");
fclose($fp);
?>

PHP - XAMPP


Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

XAMPP

Per esercitazioni sullo sviluppo web in ambiente Microsoft Windows può essere utile usare XAMPP. Consiglio di scaricare e usare la versione indicata come "Metodo B: 'Installazione' senza l'installer"
Dopo aver scompattato il file (ad esempio, in C:\), eseguire lo script setup_xampp.bat per effettuare i cambiamenti necessari a seconda del percorso specificato. Al termine, eseguire xampp_control.exe e tentare di avviare il server Apache.

Problemi e soluzioni

Porta 80 occupata

Ce ne possiamo rendere conto eseguendo xampp-portcheck.exe.
Se è in esecuzione Ms Internet Information Server, che occupa la porta 80, non è possibile avviare normalmente Apache.

Soluzione 1: chiudere IIS, con il comando
net stop IISADMIN /y

Soluzione 2: impostare Apache perché ascolti su una porta diversa (ad esempio la porta 8080), modificando il fileapache/conf/httpd.conf (bisogna trovare la riga con scritto Listen 80 e sostituirla con Listen 8080).

Firewall in azione

All'avvio di Apache potrebbe comparire un messaggio che dice che il Firewall di Windows blocca il servizio.

Soluzione 1: disattivare il firewall, oppure consentire un'eccezione.
Soluzione 2: lavorare solo da localhost, che dovrebbe comunque rimanere possibile.

PHP - Come procedere


Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

Alcuni argomenti che meriterebbero di essere trattati

Uno sviluppatore PHP dovrebbe avere una buona idea di come sfruttare alcuni strumenti potenti e flessibili che il linguaggio mette a disposizione. Ne elenco alcuni, senza un particolare ordine di priorità:
Ovviamente, a seconda di interessi e necessità concrete, ci si potrà trovare ad avere bisogno di molte altre cose.
L'idea fondamentale è che uno sviluppatore web non dovrebbe reinventare la ruota, ma controllare se esistono soluzioni che può sfruttare (possibilmente ricambiando con proprio codice e/o documentazione).

Documentazione

Il codice può essere facilmente documentato, anche in assenza di commenti formattati in maniera particolare. Lo strumento di riferimento è phpDocumentor.
Se poi il codice viene commentato adeguatamente, l'utilità è ancora maggiore.

ORM e Framework

Per qualsiasi progetto non banale, vale la pena di sfruttare qualche framework di sviluppo, che spesso è appoggiato a un Object-Relational Mapper.
Vale la pena anche di dare un'occhiata a cosa offre il framework Zend.


PHP - Il controllore


Questo post fa parte di una serie preparata qualche anno fa per delle lezioni su PHP.

Un unico punto di accesso

Una buona pratica è quella di avere un unico punto di accesso all'applicazione, da usare per tutte le azioni che possono essere compiute dall'utente.
Questo punto di accesso sarà in cui verrà invocato il livello controller (nell'ambito del pattern MVC). Ciò comporta una serie di vantaggi:
  1. centralizzazione dei controlli di validità della richiesta, in base a tutti i parametri ritenuti necessari
  2. generazione di una sola istanza di classi per l'accesso alla base di dati, agli "oggetti" che rappresentano la connessione HTTP (es. WebRequest e WebResponse, se li definiamo, ecc.)
  3. possibilità di abilitare/disabilitare agevolmente l'intera applicazione
  4. possibilità di definire URL più significativi e Search-Engine Optimized.

Definizione degli URL

Potremo definire un unico controller index.php che si occupa di "smistare il traffico" a seconda dell'azione richiesta. In prima approssimazione, gli URL saranno simili ai seguenti:

http://www.example.com/myapp/index.php?action=listitems
http://www.example.com/myapp/index.php?action=showitem&id=12

Con il primo invocheremo l'azione listitems, con il secondo l'azione showitem, passando il parametro id=12 da utilizzare per decidere quale elemento mostrare.

Se le azioni listshowedit, ecc. sono le medesime per diversi tipi di oggetti (es. foto, documenti, video, ecc.) potrà essere conveniente avere azioni in qualche modo raggruppate, così:

http://www.example.com/myapp/index.php?module=photos&action=list
http://www.example.com/myapp/index.php?module=photos&action=show&id=12
http://www.example.com/myapp/index.php?module=videos&action=list
http://www.example.com/myapp/index.php?module=videos&action=show&id=32

Se poi volessimo degli URL più significativi e SEO, potremo fare in modo che il nostro controller effettui un'analisi della query string in modo da poter gestire URL fatti in questo modo:

http://www.example.com/myapp/index.php/photos/list
http://www.example.com/myapp/index.php/photos/show/id/12
http://www.example.com/myapp/index.php/videos/list
http://www.example.com/myapp/index.php/videos/show/id/32

Progettazione degli URL

Gli URL sono una parte importante di un'applicazione web, troppo spesso sottovalutata. Essi dovrebbero essere (vedi i suggerimenti riportati su NewMediaJournalism):
  • permanenti
  • leggibili
  • gerarchici
  • brevi e chiari

Slug al posto dell'id

In molti contesti, è preferibile indicare un elemento con un identificativo mnemonico significativo anziché con uno sterile identificativo numerico progressivo. Questo identificativo, nel caso di articoli giornalistici (ma il concetto può essere esteso ai post di un blog, al titolo assegnato ad un'immagine, ecc.) viene chiamato slug.

Il nome slug identifica un proiettile la cui forma è cambiata a causa del passaggio per la canna della pistola; analogamente, un titolo di un pezzo giornalistico come "Nuove idee per la Wikipedia" potrebbe venire trasformato, anche con procedimenti automatici, nello slug "nuove-idee-per-la-wikipedia".

URL rewriting

Tramite opportuna configurazione del server web, e agendo sul file .htaccess, è possibile evitare che nell'URL compaia un riferimento allo script invocato (in pratica viene reso invisibile il nome index.php):

http://www.example.com/myapp/photos/list
http://www.example.com/myapp/photos/show/id/12
http://www.example.com/myapp/videos/list
http://www.example.com/myapp/videos/show/id/32

Ulteriori informazioni in merito si possono trovare nella guida all'URL-rewriting del sito HTML.it.

Esercizio

Mettere insieme i pezzi visti fino a qui, e progettare una piccola applicazione con separazione netta dei livelli MVC, definendo le classi appropriate, progettando gli URL, predisponendo i test necessari, ecc.