Il bello del golang

Parlo poco di programmazione non essendo (piu’) uno sviluppatore , ma dal momento che ho deciso di studiare un pochino Go Lang, e che sul lavoro devo gestire gruppi di sviluppatori, (nonche’ il parto delle loro menti) , questo tuffo in un lunguaggio di recente concezione mi permette di trarre alcune conclusioni, o perlomeno alcune sensazioni.

Per prima cosa: sono un seguace di Wirth. Significa che qualsiasi problema della programmazione e’ prima di tutto un problema di cattivi programmatori. Poi, semmai, si va a cercare il difetto nel linguaggio, nel paradigma, eccetera.

In ultima analisi si parla sempre di sistemi che sono Turing-Completi, quindi alla fine si parla di roba che non ha senso definire piu’ o meno potente. Li si puo’ definire piu’ comodi, piu’ adatti allo sviluppo di gruppo, piu’ vicini al linguaggio umano, ma parlare della “potenza” di un linguaggio e’ la tassa per non sapere cosa significhi “Turing-Completo”.

Andiamo al Go Lang. Innanzitutto, perche’ un nuovo linguaggio di programmazione? La risposta e’: perche’ migliorare i programmatori, o assumerne di migliori, costa molto piu’ che costruire un nuovo linguaggio di programmazione. Sebbene sia chiaro che la stragrande mancanza dei problemi siano legati ad una cattiva programmazione, si pensa di risolvere la cosa migliorando il linguaggio.

In particolare, il problema che ossessiona il mondo della programmazione e’ la complessita’ del progetto. La complessita’ del progetto e’ semplicemente il fatto che se occorrono un milione di righe di codice per spiegare alla macchina come comportarsi, allora:

  1. Nessuno puo’ averle in mente tutte => serve una squadra.
  2. Nessuno puo’ capire tutte le interazioni => serve un modello di astrazione
  3. Nessuno puo’ prevedere davvero tutti i possibili problemi => serve un modello sintetico

Il guaio di queste tre cose e’ che alla fine tutte queste cose le si implementa sul linguaggio, tenendosi i programmatori che ci sono. Poiche’ migliorare i programmatori costa, mentre inventare un linguaggio costa meno, il mondo sta saltando da un linguaggio all’altro nel tentativo di colmare le lacune dei programmatori. Allora chi disegna i linguaggi di programmazione cosa fa?

  1. Concepisce sistemi per il lavoro di squadra, cioe’ inclusione, preprocessori, sistemi di sviluppo distribuito, build systems centralizzati, etc.
  2. concepisce sistemi per la modellazione e la rappresentazione del codice, tipo UML &co.
  3. Concepisce sistemi di sintesi: librerie, programmazione ad oggetti, eccetera.

Sembrerebbe una strategia vincente, ma non funzione. La quantita’ di software si e’ moltiplicata quasi esponenzialmente negli ultimi anni, la qualita’ rimane scadente, quando non peggiora. Tutto questo lavoro nel creare il nuovo linguaggio del giorno fallisce regolarmente. Dal almeno 20 anni. Abbiamo ancora sistemi operativi coi virus. Abbiamo ancora eccezioni di null-pointer.

Ma la prova piu’ grande del fallimento e’ la quantita’ immensa di nuovissimissimissimi paradigmi della programmazione, paradigmi del project management, paradigmi dello sviluppo, che si sono sviluppati negli ultimi anni. E che regolarmente vengono rimpiazzati, dopo aver fallito miseramente.

Quello che succede sul mercato del lavoro e’ che molti vogliono fare i programmatori. Si gettano sulla programmazione cercando il linguaggio piu’ semplice da usare. Abbassano il reddito agli altri. Le aziende ci marciano molto (es: Java) sino a quando la gente si rompe di guadagnare poco e si getta sul linguaggio che ricicla il passato ma consente di guadagnare di piu’ (es: da java a scala).

Il guaio e’ che dopo un anno siamo punto a capo. Framework giganteschi, librerie che da sole costituiscono una competenza verticale, complessita’ malgestita e di conseguenza livelli di sicurezza infimi. Cosa e’ successo?

Riprendiamo le tre assunzioni di prima e vediamo , anziche’ applicarle ai linguaggi, come si applicano ai programmatori. Quando un progetto contiene milioni o anche solo migliaia di righe di codice:

  1. Nessuno puo’ averle in mente tutte => serve una squadra.
  2. Nessuno puo’ capire tutte le interazioni => serve un modello di astrazione
  3. Nessuno puo’ prevedere davvero tutti i possibili problemi => serve un modello sintetico

Allora, che abilita’ specifiche devono avere i programmatori perche’ sia gestibile la complessita’?

  1. Per lavorare in squadra, devono documentare le cose che fanno.
  2. Per usare un modello di astrazione condivisibile, devono stare vicini al linguaggio naturale.
  3. Per poter usare un modello sintetico, devono scrivere meno codice.

Ed e’ qui che si fallisce miseramente.

Andiamo sui punti, per ordine: la documentazione.

Supponiamo che qualcuno sviluppi dentro una squadra e NON documenti quel che scrive. Anzi, oggigiorno diamolo pure per scontato. Ovviamente gli altri dovranno capire come riutilizzare il suo codice. Ma lui risponde che “il codice e’ documentazione”, e vi risponde che chi e’ un buon programmatore puo’ leggere il codice (o il javadoc, o il godoc, o qualsiasi cosa) e capirlo.

La cosa sembra sensata, ma se la estendiamo ad una squadra non lo e’.

Supponiamo che per capire come utilizzare il tuo codice di oggi e fare un paio di test occorra un’ora. E che siamo in una squadra di 8 persone. Abbiamo 8 persone che spendono un’ora per capire ed usare il tuo codice. Il problema non viene nel fatto che hai gettato una giornata uomo. Anche se lo avessi documentato, qualcuno avrebbe dovuto leggere tale documentazione.

Il problema e’ un altro:

  • Hai impattato sui tempi di sviluppo altrui. Non sappiamo di preciso quanto tempo ci mettera’ il tuo collega a capire il tuo codice. Hai inserito una variabile aleatoria nella pianificazione.
  • Hai impattato sulla qualita’. Se documenti il codice e ci metti gli esempi di uso standard, l’uso del codice sara’ sano. Se ci fidiamo della corretta comprensione che una persona diversa ha del tuo codice, ci esponiamo al rischio che lui capisca male. Hai introdotto l’errore umano dove poteva non esserci.
  • Analogamente, hai impattato sulla sicurezza. Il collega che legge il codice andra’ a vedere come usarlo. Non andra’ ad esaminarlo nel dettaglio. Quindi, ci esponiamo al rischio che il collega ne faccia un uso insicuro.

E tutto questo, solo perche’ non hai scritto documentazione che mostri l’uso STANDARD della tua libreria. Se non standard, almeno quello che avevi in mente.

Secondo punto, stare vicini al linguaggio naturale.

A me le “interfacce{}” del golang piacciono un sacco. Vengono subito dopo le emorroidi. Esse sono concepite per rappresentare un processo di astrazione che non esiste in natura. O meglio. Se vostra moglie di dice “prendi il coso che c’e’ dentro il robo, nell’altra stanza”, senza indicare la stanza, il coso e il robo, ha semplicemente fatto quello che in golang si fa con un’interfaccia.

Ma se voi fate quello che si fa in golang con un’interfaccia, deducete che in questo momento vorreste un calzascarpe, andate in corridoio , lo prendete dalla scarpiera, infilate la scarpa e lo portate a vostra moglie. Dal punto di vista del golang avete usato alla perfezione il concetto di interfaccia.

Il guaio e’ che vostra moglie aveva in mente il battibistecche.

Qual’e’ il problema dell’interfaccia di golang?

Il problema e’ che parte dall’idea che:

  1. Programmatore A , che ha l’ idea iA , scriva l’interfaccia.
  2. Programmatore B, che ha l’idea iB , popoli l’interfaccia.
  3. Per un qualche magico motivo, programmatore B sappia che diavolo avesse in mente programmatore A, facendo un uso opportuno dell’interfaccia.

Quanto e’ probabile questa cosa? E’ probabile quanto e’ probabile che vostra moglie vi chieda “prendi il coso che c’e’ nel robo dell’altra stanza” e voi gli portate la cosa giusta.

E’ vero, succede.

Ne deduciamo quindi che le interfacce del golang siano concepite per programmatori sposati tra loro.

Ne prendo atto: il golang ha i valori della Famiglia. Ok.

L’errore di questa cosa consiste nel disegnare un concetto che e’ troppo lontano dal modo di pensare della mente umana, disegnarlo in modo che non solo venga capito, ma debba anche essere condiviso, e poi ci si aspetti che tutto funzioni. Se anche il singolo individuo puo’ percepire l’astrazione – che non esiste nel linguaggio naturale – , la probabilita’ che l’uso corretto di quell’interfaccia passi da una mente all’altra e’ microscopica.

Non esiste niente di simile alle interfacce nel linguaggio naturale, e quando esiste funziona solo tra coppie sposate. A meno che golang non sia un linguaggio concepito coi valori della famiglia in mente, onestamente se ne faceva anche a meno. Le interfacce andavano bene in ADA95, perche’ restringevano la quantita’ di cose che si potevano fare con un dato. Qui nel golang, esse aumentano enormemente la possibilita’ di fare. E quindi, diminuiscono la probabilita’ che voi facciate la cosa giusta.

Andiamo all’ultimo punto: scrivere meno codice.

Scrivere meno codice e’ essenziale per la buona programmazione.

E’ vero: per avere il certificato A , nella vita normale, devo avere il certificato B, l’attestato C, e poi portarle all’ufficio Z. In Germania ci mettete 5 minuti, ma dovete sapere quale sia l’ufficio esatto ove andare. E’ scritto nel “Manuale della Germania”, che pero’ non e’ in vendita. (La gente crede sia una catena montuosa, viste le dimensioni.).

Allo stesso modo, nei linguaggi di programmazione moderni, per non parlare dei framework moderni, c’e’ il disprezzo totale, inesorabile ed assoluto verso le variabili globali, che riducono enormemente la quantita’ di codice da scrivere. (contemporaneamente i programmatori fanno gara a passare variabili e funzioni usando un puntatore, per mostrare quanto lo hanno grosso. Il fatto che qualsiasi argomento contro una variabile globale possa venire usato contro un puntatore , cioe’ una variabile assoluta, evidentemente non li coglie). Questo si risolve mettendo le variabili dentro dei contenitori locali, e poi scrivendo altro codice per recuperarne il valore ed assegnarlo ad una variabile locale.

Risultato: in fase di troubleshooting, la gente deve fare come l’ispettore Derrick e mettersi ad investigare sul movente del programmatore: come mai qui c’e’ questa roba? Serve solo per recuperare sta cosa da un altro posto? E da quale posto? E quale cosa? Cui prodest? Cave canem?

Queste tre grandi cattive abitudini, che sono

  1. Non documentare librerie e classi.
  2. Non stare vicini al linguaggio naturale.
  3. Scrivere troppo codice.

resistono a tutti i tentativi di produrre un ““mondo del software”” migliore, per una ragione: qualsiasi linguaggio di programmazione puo’ essere abusato. MA specialmente, qualsiasi linguaggio verra’ abusato. Il problema non sta nel linguaggio. Stai nei programmatori.

Sia chiaro, non parlo di vizi dei programmatori moderni. Anzi, quel viziaccio e’ nato spesso dagli accademici, che non pagando i programmatori disegnavano protocolli e software mettendoci dentro unghie incarnite come se piovessero. In questi giorni, per divertimento, sto facendo una specie di server che risponde al protocollo NNTP su localhost e poi usa un altro protocollo per trovare gli altri server e distribuire i messaggi ed i newsgroup. I server si trovano da soli e si scambiano i messaggi. Una specie di usenet senza server dell’ ISP, peer to peer.

Ora, io non sono nemmeno un programmatore full-time, e sto buttando giu’ idee, sinora il mio server crea un cluster DHT/Pastry , e risponde ad alcuni comandi NNTP. Cioe’ non fa ancora nulla. Ma persino costruendo un giocattolo per me stesso, vedo ancora esempi di come, anche in passato, si sia ragionato male.

Il primo esempio e’ la stessa definizione del protocollo NNTP nell’ RFC977. Osservate la definizione di “NEWNEWS” e di “NEXT”. Ora, chi facesse un protocollo nell’anno di grazia 1986 – non sto scherzando: 1986 – poteva permettersi tutto tranne che sprecare memoria e codice. Nel senso che erano immensamente costosi. Allocare un puntatore (su cui fare NEXT, che e’ stateful) per ogni utente connesso era costoso. A quell’epoca i KILOBYTE di memoria costavano. E anche i programmatori, nel privato costavano molto.

Stessa cosa con NEWNEWS. Potremmo nominare il fatto che i client avessero ancora meno memoria dei mainframe o dei server, ma rimane il fatto che quel design sembra sensato SOLO SE NON PAGHI I PROGRAMMATORI. Nel 1986, solo l’espansione di quell’ asterisco COSTAVA.Rendere stateful una sessione, che poi oggi e’ banale, all’epoca era pensabile solo su grandi macchine. Che loro, evidentemente, non pagavano.

Quel mindset, cioe’, e’ rimasto sin dal 1986. Immagino che chi ha disegnato quella roba sia passato dal C al C++, poi quando non riusciva piu’ a gestire il codice abbia deciso che Java fosse una ficata, poi quando e’ impazzito di librerie non documentate sia passato a C#, e alla fine sia finito su Python, per divertirsi con l’indentazione, oppure su Scala.

Ma per quanti linguaggi cambino, questi personaggi non potranno mai pensare a roba decente. Non potranno perche’ pensano malissimo.

Il golang me lo dimostra. E’ un linguaggio fantastico, sia chiaro. Ha tolto dalle palle quasi tutti gli elementi fastidiosi della programmazione. Ha tolto moltissime delle cose che seccavano. Cross compilazione in pochi secondi.
Sintassi chiara. Compilazione semplice. Eseguibili senza dipendenze.

Ma nella ricerca di librerie che ho fatto per scrivere il mio programma, mi sono sentito dire che:

  • Vuoi la documentazione? Basta leggere il codice. Il codice e’ documentazione.
  • Se il codice non e’ chiaro, non e’ perche’ ho scritto array di liste di FIFO di interfacce a puntatori di ring. Sei tu che non pensi come Spock sotto LSD.
  • Il fatto che si possa fare la stessa cosa con un terzo del codice testimonia quanto sono fico: posso scrivere tre volte il codice che serve per puro divertimento.

La mia sensazione, cioe’, e’ che su golang stiano cercando di riciclarsi quelli che:

  • hanno fallito in Java.
  • Hanno fallito in Php.
  • Hanno fallito in Python.
  • Hanno fallito in C#/.net
  • Hanno fallito con Javascript/CSS/Jquery

sento odore delle stesse minchiate. Girando per librerie di protocolli, e cercando la documentazione, vedo chiaramente il mindset di tutto cio’ che e’ andato storto nel passato. Roba mal documentata o non documentata e venduta come “libreria”, un modo di programmare lontanissimo dal linguaggio naturale, codice inutile ovunque, scritto solo per dimostrare “mamma, guarda, so usare un’interfaccia{}!”.

Vedo poi arrivare i primi “framework”. La pestilenza del software. Fuori dal mondo enterprise, i framework sono la cosa piu’ stupida ed inutile che esista, e servono solo a creare la persona che sul CV scrive che conosce il tale framework. “Conosce” significa che siccome la documentazione manca e il codice e’ brutto e ridondante, allora lui ci ha sbattuto la testa e per questo tempo speso in trial&errors vuole essere pagato.

Certo, ci sono casi nei quali i framework servono. Ma si tratta di casi che capitano con grandi progetti, nella media basterebbero delle normalissime librerie. Insomma, vedo nubi nere all’orizzonte.

Il motivo per il quale temo per il golang pero’ e’ diverso: si presta troppo bene a programmare da soli. E quando programmi da solo, non ti serve documentare. Hai tutto in mente. Non ti serve usare codice chiaro: tu leggi benissimo la tua calligrafia assirobabilonese. E neanche scrivere poco codice: anzi, sofistichiamo un pochino, che quando torna la mamma glielo faccio vedere prima di aiutarla a portare in casa la spesa.

Golang e’ bellissimo, ma aiuta troppo il programmatore solitario. Ha il merito di essere il piu’ meraviglioso oggetto per hobbysti dopo il Borland Turbo Pascal, ma dall’altro lato, aiuta troppo il programmatore solitario.

Il mio timore e’ di veder piombare nel mondo del lavoro gente che non ha capito una cosa: nell’ IT, devi lavorare con-gli-altri. Il tuo codice verra’ fatto girare da un gruppo di operations. Il tuo codice verra’ osservato dalla security IT. Dovrai implementare sul codice di altri. Gli altri implementeranno sul tuo.

In definitiva, cioe’, il peggior difetto dei programmatori e’ quello di saper lavorare solo sul proprio pc e da soli. Se gia’ il programmatore ha la tendenza a diventare solitario, questa tendenza era attenuata da build tool come maven e altri sistemi che di fatto spingevano gli sviluppatori sulla strada del lavorare con gli altri.

Adesso arriva golang, e vedo che e’ fantasticamente disegnato per consentire ad un programmatore di lavorare da solo. Certo, ha una serie di strumenti magnifici per lo sviluppo di squadra, ma rimane troppo buono per divertirsi da soli.

In pratica, ho paura di sentirmi dire daccapo “ma sul computer dove l’ho provato funziona benissimo”.

Dal mio punto di vista, mi ci sto solo divertendo nel poco tempo libero, ma cercare di immaginare un mondo nel quale si concentreranno tutti quelli che non sanno lavorare con gli altri e hanno tutte le cattive abitudini degli ultimi 20 anni un pochino, onestamente, mi preoccupa.

Spero di sbagliare.

Tags | golang inutile linguaggio |