Home
Strumenti di base del pragmatic programmer: il testo puro e la shell

20 Febbraio 2020

Strumenti di base del pragmatic programmer: il testo puro e la shell

di

Ogni artigiano inizia il proprio percorso con un insieme di base di strumenti di buona qualità.

Chi lavora il legno avrà bisogno di righelli, calibri, un paio di seghe, qualche buona pialla, buoni ceselli, trapani e punte, mazzuoli e morsetti. Questi strumenti saranno scelti con amore, saranno fatti per durare, serviranno a scopi specifici con poca sovrapposizione con altri strumenti e, forse la cosa più importante, il nostro ebanista in erba se li sentirà bene in mano.

Poi inizia un processo di apprendimento e di adattamento. Ogni strumento avrà la sua personalità e le sue peculiarità e dovrà essere trattato in un suo modo speciale. Ciascuno dovrà essere appuntito o affilato in un modo specifico, o tenuto in un certo modo. Con il tempo, ciascuno si logorerà a seconda dell’uso, fino a che l’impugnatura non sembrerà un calco delle mani dell’artigiano e la superficie di taglio non si allineerà perfettamente con l’angolo a cui lo strumento viene tenuto. A quel punto, gli strumenti porteranno direttamente dal cervello dell’artigiano al prodotto finito, saranno diventati estensioni delle sue mani. Con il tempo, aggiungerà nuovi strumenti, forme, seghe circolari a guida laser, maschere a coda di rondine – tutti ottimi prodotti tecnologici, ma potete scommetterci che sarà davvero felice solo quando avrà in mano quegli strumenti originali, quando sentirà la pialla cantare mentre scorre sul legno.

Gli strumenti amplificano il talento: quanto migliori sono, tanto meglio li sappiamo usare, tanto più produttivi potremo essere. Iniziamo con un insieme di base di strumenti di applicazione generale. Con l’esperienza, e quando incontreremo richieste speciali, amplieremo con regolarità il parco attrezzi. Stiamo sempre all’erta per individuare modi migliori di fare le cose. Lasciamo che sia il bisogno a guidare i nostri acquisti.

Molti programmatori alle prime armi commettono l’errore di adottare un unico strumento di grande potenza, per esempio un particolare ambiente di sviluppo integrato (IDE, Integrated Development Environment) e non abbandonano mai la sua comoda interfaccia. È un errore: dobbiamo sentirci a nostro agio oltre i limiti imposti da un IDE, e l’unico modo è avere a portata di mano lo strumentario di base, affilato e pronto per l’uso.

In questo articolo parleremo di investire nello strumentario di base e partiremo da due elementi: la materia prima, quella a cui dovremo dare forma, e il banco da lavoro, nel nostro caso il computer.

Il potere del puro testo

Da programmatori pragmatici, il nostro materiale di base non è il legno o il ferro, ma la conoscenza. Raccogliamo requisiti come conoscenza, poi esprimiamo quella conoscenza nei nostri progetti, nelle implementazioni, nei test e nei documenti. Siamo convinti che il formato migliore per conservare a lungo la conoscenza sia il puro testo. Con il puro testo, abbiamo la possibilità di manipolare la conoscenza, manualmente o da programma, utilizzando praticamente tutti gli strumenti a nostra disposizione.

Il problema con la maggior parte dei formati binari è che il contesto necessario per comprendere i dati è separato dai dati stessi: si dissociano artificialmente i dati dal loro significato. I dati potrebbero anche essere cifrati: sono assolutamente privi di significato senza la logica dell’applicazione in grado di analizzarli. Con il puro testo, invece, si può ottenere un flusso di dati che descrive se stesso ed è indipendente dall’applicazione che lo ha creato.

Che cos’è il puro testo?

Il puro testo (plain text) è costituito da caratteri stampabili, in una forma che veicola informazione. Può trattarsi di qualcosa di molto semplice, come una lista della spesa:

* latte
* insalata
* caffè

o di qualcosa di complesso come il sorgente di questo libro (sì, è stato scritto in puro testo, con grande disappunto dell’editore, che avrebbe voluto si usasse un word processor).

La parte relativa all’informazione è importante. Questo non è puro testo utile:

hlj;uijn bfjxrrctvh jkni'pio6p7gu;vh bjxrdi5rgvhj

né lo è questo:

Field19=467abe

Il lettore non ha idea di quale possa essere il significato di 467abe. Vogliamo che il nostro puro testo sia comprensibile agli esseri umani.

Testo puro non significa testo non strutturato: HTML, JSON, YAML e così via sono tutti puro testo, e lo stesso vale per la maggior parte dei protocolli fondamentali della rete, come HTTP, SMTP, IMAP e via elencando, e per buoni motivi:

  • garanzia contro l’obsolescenza;
  • possibilità di fare leva su strumenti già esistenti;
  • maggiore facilità di test.

Garanzia contro l’obsolescenza

Dati in forma leggibile dagli esseri umani e dati che si autodescrivono sopravvivranno a ogni altra forma di dati e alle applicazioni che li hanno creati. Punto. Se i dati sopravvivono, avremo la possibilità di usarli, potenzialmente, anche molto dopo la definitiva scomparsa dell’applicazione originale che li ha scritti.

Possiamo analizzare sintatticamente un file simile con una conoscenza solo parziale del suo formato; nel caso dei file binari, dobbiamo conoscere tutti i particolari dell’intero formato per poterne effettuare correttamente l’analisi sintattica.

Prendiamo un file di dati di qualche sistema legacy (e tutto il software diventa legacy non appena è stato scritto). Non sappiamo un granché dell’applicazione originale; tutto quello che importa è che manteneva una lista dei numeri di Sicurezza sociale dei clienti, che dobbiamo trovare ed estrarre. Fra i dati, vediamo

<FIELD10>123-45-6789</FIELD10>
...
<FIELD10>567-89-0123</FIELD10>
...
<FIELD10>901-23-4567</FIELD10>

Riconoscendo il formato di un numero di Sicurezza sociale, possiamo rapidamente scrivere un programmino per estrarre quei dati, anche se non abbiamo alcuna informazione su tutto il resto che si trova nel file.

Immaginiamoci invece che cosa sarebbe successo se il file fosse stato formattato in questo modo:

AC27123456789B11P
...
XY43567890123QTYL
...
6T2190123456788AM

Non avremmo riconosciuto con altrettanta facilità il significato dei numeri. Questa è la differenza fra leggibile da un essere umano e comprensibile a un essere umano.

Intanto che ci siamo, anche FIELD10 non è di grande aiuto. Qualcosa come

<SSNO>123-45-6789</SSNO>

renderebbe l’esercizio banale, e garantirebbe che i dati sopravvivano a qualsiasi progetto li abbia creati.

Fare leva su strumenti già esistenti

Praticamente ogni strumento nell’universo informatico, dai sistemi di controllo delle versioni agli editor e agli strumenti da riga di comando, può operare con il puro testo. Mica per niente è basato su puro testo un intero sistema operativo: Unix, famoso per essere stato progettato secondo la filosofia degli strumenti piccoli e affilati, ciascuno mirato a fare una cosa sola molto bene. Questa filosofia è resa possibile dall’uso di un formato di fondo comune, il file di puro testo orientato alla riga.

Per esempio, supponiamo di dover mettere in esercizio un’applicazione di grandi dimensioni con un file di configurazione complesso, specifico per il sito. Se il file è in puro testo, possiamo sottoporlo a un sistema di controllo delle versioni, in modo che venga generata automaticamente una cronologia di tutti i cambiamenti. Strumenti di confronto fra file come diff e fc consentono di vedere a colpo d’occhio quali cambiamenti siano stati apportati, mentre sum consente di generare una somma di controllo (cxhecksum) per verificare che il file non abbia subito modifiche accidentali (o malintenzionate).

Maggiore facilità di test

Se usiamo il puro testo per creare dati sintetici che guidino i test di sistema, è semplice aggiungere, aggiornare o modificare i dati di test senza dover creare strumenti speciali a questo scopo. Analogamente, output in puro testo da test di regressione può essere analizzato banalmente con comandi di shell o con un semplice script.

Il minimo comun denominatore

Anche nel futuro di agenti intelligenti basati su blockchain che navigano autonomamente nelle acque selvagge e pericolose di Internet, negoziando fra loro scambi di dati, l’onnipresente file di testo sarà ancora lì. In effetti, in ambienti eterogenei i vantaggi del puro testo compensano abbondantemente tutti i suoi svantaggi. Dobbiamo essere sicuri che tutte le parti possano comunicare utilizzando uno standard comune, e il puro testo è quello standard.

Giochi di shell

Chiunque lavori il legno ha bisogno di un bel banco da lavoro, robusto e affidabile, un posto in cui tenere i pezzi a un’altezza comoda mentre li lavora. Il banco è il centro del laboratorio e l’artigiano continua a ritornarvi mentre il pezzo prende forma.

Per un programmatore che manipola file di testo, il banco da lavoro è la shell di comando. Dal prompt della shell si può richiamare qualunque strumento, usando i pipe per combinarli in modi che gli sviluppatori originali mai si sarebbero sognati. Dalla shell possiamo lanciare applicazioni, debugger, browser, editor e utility. Possiamo cercare file, interrogare lo stato del sistema e filtrare l’output. Programmando la shell, poi, possiamo costruire macro-comandi complessi per attività da svolgere spesso.

Ai programmatori cresciuti fra interfacce GUI e ambienti di sviluppo integrati (IDE) potrebbe sembrare una posizione estrema: in fin dei conti, non si può fare tutto altrettanto bene puntando e facendo clic con il mouse?

La semplice risposta è no. Le interfacce GUI sono meravigliose e per certe operazioni semplici possono essere più veloci e più comode. Spostare file, leggere e scrivere email, costruire e mettere in esercizio un progetto sono tutte cose che si fanno benissimo in un ambiente grafico ma, se svolgiamo tutto il lavoro con le GUI, non possiamo attingere a tutte le potenzialità dell’ambiente. Non potremo automatizzare attività comuni, né usare tutta la potenza degli strumenti disponibili. E non saremo in grado di combinare quegli strumenti per creare macrostrumenti personalizzati. Un vantaggio delle GUI è il WYSIWYG, what you see is what you get, quello che vedi è quello che ottieni. Lo svantaggio è WYSIAYG, what you see is all you get, quello che vedi è tutto quello che ottieni.

Gli ambienti GUI normalmente sono limitati alle capacità previste dai loro progettisti. Se dobbiamo andare oltre il modello fornito dal progettista, di solito siamo sfortunati — e ci succederà spesso. I programmatori pragmatici non si limitano a scrivere codice, o a sviluppare modelli a oggetti, o a scrivere documentazione, o ad automatizzare il processo di build: fanno tutte queste cose. La portata di qualsiasi strumento di solito è limitata alle attività che si prevede quello strumento debba svolgere. Per esempio, supponiamo di dover integrare nel nostro IDE un preprocessore di codice (per implementare la progettazione per contratto, o pragma di multielaborazione, o qualcosa di simile). A meno che chi ha progettato l’IDE non abbia fornito esplicitamente gli agganci giusti, l’integrazione non sarà possibile.

Se invece usiamo la potenza della shell di comando e acquisiamo familiarità con essa, la nostra produttività avrà un’impennata. Serve un elenco di tutti i nomi di package unici importati esplicitamente dal nostro codice Java? Quanto segue lo memorizza in un file chiamato lista.

grep '^import ' *.java |
sed -e's/.*import *//' -e's/;.*$//' |
sort -u >lista

Chi non abbia dedicato molto tempo a esplorare le possibilità della shell di comando del sistema che usa non ha idea di quanto potrebbe diventare più produttivo.

Una shell tutta per me

Come un falegname personalizza il proprio spazio di lavoro, uno sviluppatore personalizzerà la propria shell. La personalizzazione in genere comporta modificare la configurazione del programma terminale che si usa. Fra i cambiamenti più comuni ci sono i seguenti.

  • Impostare i temi di colore. Si possono passare moltissime ore a provare ogni singolo tema disponibile online per una particolare shell.
  • Configurare un prompt. Il prompt che dice che la shell è pronta a ricevere un comando può essere configurato in modo da presentare quasi qualsiasi informazione si possa volere (e anche una gran quantità di cose che non si vorrebbero vedere). Qui comandano le preferenze personali: noi tendenzialmente preferiamo prompt semplici, con il nome della directory corrente in forma abbreviata e uno stato del controllo di versione, insieme all’indicazione dell’ora.
  • Alias e funzioni di shell. Semplificate il flusso di lavoro trasformando i comandi di uso più frequente in semplici alias. Magari aggiorniamo regolarmente il nostro sistema Linux, ma non riusciamo a ricordare se aggiorniamo e poi facciamo l’upgrade, o viceversa. Creiamo un alias:
alias apt-up'sudo apt-get update && sudo apt-get upgrade'

Magari abbiamo cancellato accidentalmente dei file con il comando rm una volta di troppo. Scriviamo un alias in modo che in futuro ci avverta sempre:

alias rm = 'rm-iv'
  • Completamento dei comandi. La maggior parte delle shell completerà automaticamente i nomi dei comandi e dei file: scriviamo i primi caratteri, premiamo il tasto di tabulazione e la shell completerà come può. Si può estendere molto questo comportamento, però, configurando la shell in modo che riconosca il comando che stiamo inserendo e offra un completamento specifico per il contesto. Qualcuno addirittura personalizza il completamento in funzione della directory corrente.

Passeremo una gran quantità di tempo in una di queste shell. Facciamo come il granchio eremita e sistemiamocela come fosse casa nostra.

Questo articolo richiama contenuti dal capitolo 3 di Pragmatic Programmer – Edizione del 20° anniversario.

unsplash-logoImmagine di apertura di Michael Dziedzic

L'autore

  • David Thomas
    David Thomas è tra i massimi esperti mondiali del linguaggio di programmazione Ruby. Applica con successo il metodo di sviluppo agile e cerca sempre di trovare soluzioni semplici a problemi complessi.
  • Andrew Hunt
    Andrew Hunt è un consulente informatico apprezzato a livello internazionale e autore di circa mezza dozzina di manuali dedicati all'apprendimento della buona programmazione.

Iscriviti alla newsletter

Novità, promozioni e approfondimenti per imparare sempre qualcosa di nuovo

Gli argomenti che mi interessano:
Iscrivendomi dichiaro di aver preso visione dell’Informativa fornita ai sensi dell'art. 13 e 14 del Regolamento Europeo EU 679/2016.

Corsi che potrebbero interessarti

Tutti i corsi
Big-data-analytics-iniziare-bene-cover Corso Online

Big Data Analytics - Iniziare Bene

con Andrea De Mauro

Credi che i Big Data siano una grande opportunità ma che spesso se ne parli a sproposito? Excel ti sta stretto e vorresti fare di più? Andrea De Mauro ti aiuta a fare chiarezza e ti insegna a muovere i primi passi nell'analisi dei Big Data.

corso-data-governance Simone Aliprandi Corso Online

Data governance: diritti, licenze e privacy

con Simone Aliprandi

I dati sono ovunque intorno a noi ma per poterli utilizzare in sicurezza bisogna confrontarsi con temi complessi che riguardano licenze, proprietà intellettuale e privacy. Se non ti senti sicuro o hai paura di prendere la decisione sbagliata, il corso di Simone Aliprandi fa per te.

language_design_progettare_con_le_parole-home Corso In aula

Language design: progettare con le parole

con Yvonne Bindi

Nell'interfaccia che hai messo a punto le parole perdono di significato e il messaggio non è chiaro? Forse non stai considerando che le parole possono essere interfacce. Yvonne Bindi ti insegna ad affrontare il design con le parole.


Libri che potrebbero interessarti

Tutti i libri

Pragmatic Programmer - Edizione del 20° anniversario

Guida per artigiani del software che vogliono diventare maestri

34,90

49,89€ -30%

28,41

29,90€ -5%

19,99

di David Thomas, Andrew Hunt

Clean Code

Guida per diventare bravi artigiani nello sviluppo agile di software

46,15

64,89€ -29%

37,91

39,90€ -5%

24,99

di Robert C. Martin

Clean Architecture

Guida per diventare abili progettisti di architetture software

46,15

64,89€ -29%

37,91

39,90€ -5%

24,99

di Robert C. Martin


Articoli che potrebbero interessarti

Tutti gli articoli