Geek Publishing

Spesso scherzo sul fatto che se dovessi sostenere l’esame della
patente europea del computer verrei sicuramente bocciato. Il fatto
è che dopo più di vent’anni che uso il computer per me è ancora un
dramma usare Word o Excel. A volte me ne vergogno, ma la maggior parte del tempo
ne sono orgoglioso, mi viene da pensare a quanto sia ridicolo
l’ECDL,
e vedo la mia incapacità come un segno distintivo
di geekness.

Ci sono essenzialmente due motivi per cui sono così
scarso con Word ed Excel (ma anche con OpenOffice). Il primo è che non utilizzo
mai o quasi questi strumenti. Quello che uso di più è il foglio di
calcolo di OpenOffice, per cinque minuti al mese quando devo
aggiornare il foglio delle presenze in ufficio, ed ogni volta devo
combattere con l’autocompletamento.
Chi mi conosce sa che non sto esagerando, anzi
sto sottostimando le mie difficoltà. Il fatto è che oltre alla mancanza
di familiarità ho proprio un problema di usabilità. Quando vedo una
finestra a tutto schermo con duecento bottoni mi perdo e non so più
che pesci pigliare. In effetti ho sempre pensato che la mia memoria
visiva fosse subnormale, per cui non riesco a ricordarmi dove si
trovano i bottoncini e ogni volta li devo cercare per lo schermo.
D’altra parte anche il mio senso dell’orientamento è notoriamente
disastroso (tipo quella volta che mi sono perso tornando
a casa mia, motivo per cui i miei compagni di liceo mi sfottono ancora).
Fortunatamente, invece, non ho particolari difficoltà a ricordarmi
le combinazioni dei tasti, per cui so che per aprire un nuova finestra
in Emacs devo dare un C-x52, anche se non ho idea di dove si trovi
la voce del menu corrispondente (ammesso che esista). Un aneddoto
divertente è che quando è uscita la versione di Emacs release 21
in cui se non erro è stata introdotta una toolbar, la prima cosa
che ho chiesto su comp.emacs è stato come rimuovere la toolbar
che mi dava fastidio ;)

Pubblicare articoli tecnici the geeky way

Fatta questa premessa, d’obbligo per un articolo che
deve apparire nella rubrica "Siamo tutti geek", lasciatemi introdurre
adesso l’argomento di cui voglio parlare,
ovvero come scrivere articoli tecnici. Si tratta di un argomento che
mi sta a cuore perché scrivo articoli da anni e mi interessa
avere un processo di pubblicazione il più veloce ed efficiente
possibile. Avrete già capito dalla premessa che io non scrivo gli
articoli con Word. Ma allora cosa uso? La
risposta è che ho provato vari strumenti ed adesso ho trovato una
combinazione ottimale che voglio pubblicizzare e propagandare.

Andiamo con ordine. Storicamente, il primo tool che ho utilizzato è
stato LaTeX.
Il motivo è chiaro: facevo il Fisico e nell’ambiente
LaTeX si usava per tutto, dagli articoli alle lettere commerciali.
Ho continuato ad usare LaTeX con successo per circa dieci anni: se
state scrivendo articoli di Fisica non è che ci siano alternative, è
l’unico tool con tutte le formule matematiche che possiate
immaginarvi. D’altra parte, quando ho cominciato a occuparmi di
programmazione mi sono accorto subito che LaTeX non era lo
strumento giusto: se non avete formule matematiche LaTeX è
eccessivo (overkill). Per fortuna già a quei tempi la comunità di
Python aveva ideato uno strumento ottimo per scrivere articoli, il
ReStructuredText
o ReST per gli amici; io mi vanto di essere un early
adopter
di ReST ed ho cominciato ad usarlo fin dal mio primo articolo
su Python. Il ReST è molto più semplice e molto più produttivo di
LaTeX, ma è convertibile in LaTeX all’occorrenza (quindi posso
generare articoli con un’ottima qualità di stampa) e di default genera
HTML, che è perfetto per la pubblicazione in Internet. Il ReST ha
un’infinità di pregi e potrei scrivere un intero articolo su di esso,
ma non voglio dilungarmi adesso, motivo per cui
rimando chi volesse saperne di più al
sito del progetto docutils:
in una mezz’oretta o meno dovreste
essere in grado di scrivere il vostro primo articolo in ReST. Notate
che originariamente il ReST è stato pensato come formato ufficiale per
scrivere la documentazione di applicazioni Python e che è buona norma
scrivere le docstring in formato ReST; ciò nonostante ReST è
un tool di uso generale ed io lo uso per scrivere qualunque tipo di
documento, compresi articoli che non hanno nulla a che fare con
Python. Insomma, ReST è un grosso passo avanti rispetto a LaTeX ed è
uno step essenziale nel processo di pubblicazione dei miei articoli.

Pubblicare la cosa giusta

Quando un autore pubblica un articolo di programmazione, quasi sicuramente
includerà degli snippet di codice, dei piccoli esempi. È chiaramente
importante che il codice sia corretto e consistente con l’articolo.
Come si fa a garantirlo e ad essere sicuri che a ogni revisione
gli esempi continuino a funzionare? È chiaro che il metodo ingenuo di
scrivere il codice a parte, testarlo a mano, e inserirlo poi
nell’articolo con un copy & paste non funziona. Questo
significa che ad ogni revisione dell’articolo tutto il codice va
testato di nuovo manualmente ed io sono di gran lunga
troppo pigro per imbarcarmi in un’impresa del genere.
Tenete poi conto che io spesso scrivo delle note a mio uso e consumo;
a volte pubblico l’articolo fatto e finito dopo anni.
Nel frattempo la versione di
Python può essere cambiata, il copy & paste di una sessione
interattiva di Python 2.2 può essere diverso di quello di Python 2.5,
insomma è indispensabile
un metodo automatico per testare la correttezza della documentazione.

Per fortuna non c’è da faticare molto perché Python fornisce lo
strumento perfetto nella sua libreria standard, il modulo doctest.
Io sono un grande estimatore di doctest e non
mi stancherò mai di decantarne le lodi. Ho anche tenuto dei
seminari
sui vantaggi di doctest: ogni programmatore Python che si rispetti
dovrebbe conoscerlo anzi, a mio parere, ogni linguaggio di programmazione
dovrebbe copiare l’idea ;)

Ciò detto, resta da spiegare qualche trucco per usare doctest
nella maniera più conveniente. Di default doctest testa le
docstring di un programma Python per cui viene
naturale mettere tutta la documentazione in un’unica mega-docstring
Questo può essere fastidioso. Versioni recenti
di doctest permettono di testare file di
testo senza problemi, ma ai tempi in cui scrivevo i miei primi
articoli questa funzionalità ancora
non c’era e l’avevo aggiunta io stesso con un piccolo hack.
In pratica avevo messo in piedi un
sistema che sfruttava doctest, ma in maniera opposta al suo
uso tipico: scrivevo tutto l’articolo in un file .txt con
degli inserti di codice Python, dopodiché facevo girare uno
script scritto appositamente per estrarre il codice, generare vari
programmini Python ed un main.py contenente l’articolo come
docstring. Quindi lo script faceva girare doctest, tutto in maniera
automatica. Se siete curiosi, trovate la ricetta sul Python
Cookbook
,
datata Aprile 2005. C’è anche una piccola funzione elisp che vi
permette di doctestare il vostro articolo da Emacs semplicemente
premendo un tasto. Spettacolare!

Giusto per pagare i miei debiti, dirò che il sistema appena descritto
è stato molto influenzato dalla lettura di
Bruce Eckel. In Thinking
in C++
or in Thinking in Java, adesso non ricordo, Eckel
spiegava di aver messo in piedi un sistema (credo in Python) che estraeva il codice
sorgente dai suoi libri e lo compilava, per essere sicuro di non
distribuire esempi troppo bacati. Essendo Python un linguaggio
molto migliore di Java e C++ nel mio sistema io non mi accontentavo
soltanto di compilare il codice di esempio, ma lo facevo
anche eseguire da doctest.

Il segreto del geek publishing

Ho usato il sistema appena descritto per vari anni con soddisfazione,
ma recentemente ho trovato un trucco ancora più astuto, che adesso vi
illustrerò. Lo svantaggio di avere il codice immerso in un file di
testo è che si perde la colorazione (il syntax highlighting) insieme
agli altri vantaggi del Python mode di Emacs, quindi il codice non è
molto editabile. Se avete molto testo e poco codice la cosa può
essere accettabile, ma fastidiosa. Un’alternativa sarebbe scrivere il
codice in piccoli file .py separati e comporli tutti insieme in un
secondo passo, visto che ReST ha una funzionalità di inclusione di
blocchi di codice. Questo però ha lo svantaggio che l’articolo non
sta tutto in un singolo file mentre a me interessa semplificare la
distribuzione (tanto per fare un esempio,
un file singolo è molto meglio se voglio spedire il
sorgente via email). C’è da dire poi che il mio sistema
di lavoro è sinergico: io edito codice e documentazione
contemporaneamente, non è che prima scrivo tutto il codice e poi
tutta la documentazione. Anzi spesso arrivato a metà di un articolo
trovo una soluzione migliore e quindi riscrivo sia un pezzo di testo
che un pezzo di codice allo stesso tempo. Per me quindi è importante
poter vedere codice e testo nello stesso file. Siccome con Emacs è
senz’altro più semplice scrivere testo dentro un file Python che
scrivere codice dentro un file di testo, sono tornato al sistema
suggerito in origine da doctest, ovvero scrivere tutto l’articolo
nella docstring. Tuttavia, va notato che un programma Python ha la capacità
di manipolare la propria docstring, quindi è possibile inserire il
codice sorgente del programma stesso dentro la sua docstring usando
opportunamente inspect.getsource. Avendo capito questo, l’idea
è sorta spontanea (in realtà dopo cinque anni passati senza
accorgermene quindi non è che io sia stato proprio un’aquila): scrivere
i miei articoli come programmi Python che quando vengono invocati
generano un documento ReST manipolando opportunamente la propria
docstring e automaticamente la doctestano.
Il codice che effettua la magia è il seguente:

def create_rst(pyfile):
      """
      Given a file .py, create a file .txt with the $$-expressions
      in the docstring replaced by the corresponding code blocks.
      """
      pyname, ext = os.path.splitext(os.path.basename(pyfile))
      mod = __import__(pyname)
      fname = pyfile.replace('.py', '.txt')

      def repl(mo):
          if mo.group(2) is None: # escaped $$$
              return mo.group(1)[1:]
          obj = getattr(mod, mo.group(2))
          if isinstance(obj, str):
                return obj
          lines = inspect.getsourcelines(obj)[0]
          return '.. code-block:: python\n\n%s\n' \
                 % '\n'.join(' ' + ln.rstrip() for ln in lines)
      txt = re.sub(r'(\$\$\$[\w_\d]+)|\$\$([\w_\d]+)', repl, mod.__doc__)
      open(fname, 'w').write(txt)

mentre il codice chiamante è il seguente:

if __name__ == '__main__':
   import doctest; doctest.testmod()
   import sys; create_rst(sys.argv[0])

Questo stesso articolo è stato scritto in questo modo. Per capire
come funziona il trucco in pratica dovete scaricarvi il sorgente
Python, geek_publishing.py.

Due avvertenze: 1) ricordatevi di specificare l’encoding del programma
Python; è buona norma farlo sempre, non farlo quando avete
caratteri accentati nelle docstring è andarsi a cercare grossi problemi di encoding;
2) ricordatevi di usare una raw string, ovvero
prefissate la docstring con una "r" onde
evitare problemi con i caratteri di escape (tipo "\n").

Noterete che la docstring di geek_publishing.py contiene una riga
$$create_rst che viene automaticamente rimpiazzata con
il codice sorgente della funzione corrispondente, cosicché
ogni volta che modifico la funzione sono sicuro per costruzione
che l’articolo mostri il codice corretto: non rischio un disallineamento
tra codice e documentazione. Notate anche che è possibile escapare
(che termine orribile!) espressioni del tipo $$xxx che non vanno
interpolate usando tre dollari: $$$xxx.

La colorazione del codice sorgente usa pygments, una comodissima
libreria Python che può essere integrata con docutils seguendo
la ricetta che trovate sul sito di pygments.

Se non volete installare pygments, sostituite
la stringa '.. code-block:: python\n\n' con '::\n\n' nel
codice sorgente; non avrete i colori nell’HTML, ma il
risultato sarà usualmente leggibile. Con versioni recenti
di ReST la direttiva code:: dovrebbe implementare la
colorazione anche senza pygments,
ma io sto ancora usando docutils 0.4.

Literate programmming?

Scommetto che molti di voi si saranno chiesti quale sia stata
l’influenza del
literate programming
sul mio sistema di
pubblicazione. Dopotutto l’idea alla base è molto simile: come dice
John Max Skaller:
the idea is that you do not document programs
(after the fact), but write documents that contain the programs
.

La realtà è che io ho sentito per la prima volta il
termine literate programming quando ho postato l’idea su comp.lang.python,
cinque anni fa: è stato solo a quel punto che ho scoperto che
Donald Knuth, l’inventore del concetto originale, mi
aveva preceduto di vent’anni! Essere anticipati da Knuth lo vedo
come un complimento, significa che sono sulla buona strada ;)

A parte gli scherzi il mio sistema di pubblicazione non si pone
come un sistema di literate programming: a me non interessa
commentare un programma nella sua interezza come se fosse un lavoro
di letteratura, mi interessa invece produrre della documentazione
testabile per le parti del programma che deve essere utilizzate
dall’utente finale.
Se vi serve un sistema di literate programming per Python vi consiglio
PyLit (segnalatomi dal nostro redattore Carlo C8E Miron) che è anch’esso
basato su reStructuredText.

Partendo da LaTeX, passando per ReST, sfruttando doctest e con un
pizzico di codice sono riuscito a mettere insieme un sistema di
pubblicazione per articoli tecnici che mi soddisfa. L’unico problema è
che l’HTML generato è un pò troppo ricco per essere accettato per la
pubblicazione in Stacktrace. Così sono stato costretto a scrivere un
parser che ripulisce l’HTML generato da docutils. Per fortuna la
libreria standard di Python contiene un ottimo HTMLParser che mi ha
permesso di risolvere il problema in poco tempo e adesso abbiamo un
convertitore rst2st.py che converte da ReST al formato di
Stacktrace. Dunque, se il mio sistema vi piace, usatelo, scrivete
molti articoli per Stacktrace e mandateceli! Vi aspettiamo numerosi!

Comments

  1. Ottimo articolo Michele. Pensa che io l’ECDL (e l’ICDL) l’ho dovuto prendere alcuni anni fa (in Irlanda, pagato dall’azienda per cui lavoravo). Quasi me ne vergogno ma ho sempre avuto una certa abilità con Office (Microsoft e non). Vado però fiero del fatto che ora posso guidare i server nelle autostrade di tutta Europa. :-P

  2. Il problema non sta nell’ECDL in sè ma nel fatto che questa dovrebbe esaurire la gamma di competenze necessarie a livello professionale: sarebbe come dare ad un metalmeccanico il manuale di istruzioni della macchina che deve usare ed esaminarlo solo sulle procedure di avviamento e produzione di un pezzo trascurando procedure di sicurezza, fault tolerance ecc…

    Comunque nemmeno io sono mai venuto a patti con i fogli di calcolo :P Poi c’è da dire che il fare il grafico per lavoro mi ha aiutato sul versante desktop publishing che comunque è da preferirsi a LaTeX e compagni quando si deve stampare fuori dal mondo dell’accademia o delle scienze.

  3. Ottimo articolo!
    Per quanto riguarda le difficoltà con Word o altre cose del genere, credo sia normale. Se si lavora nel campo dello sviluppo per applicativi desktop che verranno poi utilizzati da non-geek, scontrarsi con questi problemi è all’ordine del giorno!

    IMHO il problema è in una diversa concezione della usabilità del prodotto tra chi il software lo usa e chi lo scrive…

  4. asdrubale says:

    Visto che usi Emacs, non hai mai provato Muse?

    http://mwolson.org/projects/EmacsMuse.html

  5. Che articolo stupendo!!

    Conoscevo solamente l’idea di Eckel, che lessi qualche anno fa in Thinking in Java. Devo dire che il literate programming mi intriga parecchio e sto iniziando a valutare l’idea di comporre una porzione della mia tesi proprio così….

    Grazie!

Policy per i commenti: Apprezzo moltissimo i vostri commenti, critiche incluse. Per evitare spam e troll, e far rimanere il discorso civile, i commenti sono moderati e prontamente approvati poco dopo il loro invio.