I Critical Code Studies sono un insieme di discipline che si propongono di studiare il codice sorgente dei programmi come artefatto culturale, cioè non come macchina ma come opera pienamente umana, nata in contesti determinati e frutto del momento, del luogo, delle persone. Per fare questo non si limitano a ricostruire la genesi del codice, ma lo leggono come un testo, ne indagano i riferimenti espliciti e impliciti. Non hanno come destinatari gli esperti di informatica, i programmatori, ma tutti quelli che sono interessati a capire come e perché i computer hanno cambiato le nostre vite non solo in quanto utenti passivi ma anche in quanto autori. E’ uno studio che vuole, esplicitamente, incrociare domande linguistiche, letterarie, sociologiche, storiche, economiche. Capire, ad esempio, perché il numero di donne programmatrici oggi è così ridotto mentre negli anni ’40 del secolo scorso praticamente quello di “coder” era un mestiere solo femminile. Studiare come è cambiato il modo di scrivere codice non solo con l’evolversi della potenza espressiva dei linguaggi di programmazione, ma anche con il parallelo evolversi dei modelli di romanzo. Il libro di Mark Marino (Critical Code Studies, MIT, 2020) offre ottimi esempi di questo tipo di analisi.
Questa breve lezione parla di opensource, di archeologia, di omonimi e di differenze tra lingue naturali e linguaggi di programmazione. Parte da uno strano frammento di codice sorgente del 2009, apparentemente incomprensibile, e ne rintraccia alcuni riferimenti diretti e indiretti fino agli anni ’60. E’ una lezione introduttiva, che non ha uno scopo preciso se non quello di far vedere cosa si ottiene se si smette di pensare ai programmi come mantra fatti di 1 e 0 e si prova a leggerli davvero.
Penso di poter dire che si tratta del primo saggio di CCS apparso in italiano.
1.
Moodle è un’applicazione web per l’e-learning, creata in Australia ma molto conosciuta anche in Italia. E’ per fortuna un software opensource; il che significa non solo che lo si può scaricare gratis, ma che è possibile leggere e studiare il suo codice sorgente. Per il tipo di analisi che intendiamo fare, e per qualsiasi altro tipo di analisi, è un elemento cruciale che non andrebbe mai dimenticato. Il codice aperto non è solo questione tecnica o legale, ma pienamente culturale.
Moodle è stato iniziato da Martin Dougiamas, un informatico australiano, oltre venti anni fa; nel tempo hanno collaborato al suo sviluppo centinaia di altri programmatori. Oggi è composto da circa trentamila file scritti nel linguaggio PHP, più altri in Javascript, (S)CSS etc.
Trentamila è un numero grande ma non enorme. Calcolando una media di 100 righe per file, significa che l’intera applicazione è composta da tre milioni di righe. “Alla ricerca del tempo perduto”, per dire, è composto da “sole” 100.000 righe. Questo delle dimensioni è un aspetto forse banale ma va tenuto almeno sullo sfondo di ogni riflessione. Nessuno, nemmeno Dougiamas, può dire di conoscere bene Moodle, se non nel senso di avere un’idea di massima della struttura. La memoria umana non è fatta per gestire questo tipo di oggetti.
Il codice sorgente di navigationlib.php (che è una delle librerie di Moodle e si trova nella cartella /lib) è stato scritto originariamente nel 2009 da Sam Hemelryk. Questa è una bella caratteristica del codice opensource: è quasi sempre firmato. Il copyright è suo, ma siccome il codice è rilasciato con una licenza GPL 3 chiunque lo può modificare.
Chi è Hemelryk? Ha lavorato per cinque anni in Moodle, prima come programmatore junior e poi senior e dal 2014 è il direttore dello sviluppo in Totara, una società nata a Wellington, in Nuova Zelanda, che propone una versione di Moodle “irrobustita”, cioè epurata da ogni codice dubbio, rischioso, ridondante. Questa versione non è opensource, il che introduce qualche dubbio sull’intero processo, ma così è.
/**
* This file contains classes used to manage the navigation structures within Moodle.
*
* @since Moodle 2.0
* @package core
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
All’interno del file c’è una classe che ha tra i suoi metodi una breve funzione che si chiama load_user_settings(), la quale contiene questo frammento che è il punto di partenza per il nostro viaggio:
foreach ($navusers as $user) {
if ($user->id == $USER->id) {
continue;
}
…
Si tratta di un ciclo (foreach) che “attraversa” una collezione di oggetti ($navuser); per ognuno di questi viene fatto un controllo ( if (….) ) e in caso di successo vien eseguita un’azione ( {…} ).
Il controllo ha questo significato: se il valore della proprietà ‘id’ dell’oggetto $user è uguale al valore della proprietà ‘id’ dell’oggetto $USER allora… non fare niente.
A parte il fatto che “allora non fare niente” non sembra una grande idea (che razza di controllo è?), quello che pare evidente, anche a chi non conosca in dettaglio il linguaggio di programmazione PHP, è che qui viene fatto un controllo di uguaglianza; solo che viene fatto sullo stesso oggetto e sulla stessa proprietà, il che è piuttosto strano. E’ chiaro che il valore di una proprietà di un oggetto è uguale al valore di quella stessa proprietà per quello stesso oggetto. Lo diceva Aristotele: A è A.
Siccome questo frammento però è perfettamente corretto e funzionante, o almeno sta lì da quasi quindici anni, ne possiamo dedurre solo una cosa: che $USER e $user non sono la stessa cosa.
Infatti in PHP, come in molti altri linguaggi di programmazione (C, Java, Javascript, Ruby, …), i nomi delle variabili sono “case-sensitive”. I casi qui sono due: maiuscolo e minuscolo, il che vuol dire appunto che $a e $A sono due variabili diverse.
Da un certo punto di vista questo è normale: le lettere dell’alfabeto, maiuscole e minuscole, sono codificate tramite una tabella (American Standard Code for Information Interchange) che va da 65 di A fino a 122 di z. Quindi in effetti la stringa AAA è codificata in maniera completamente diversa da aaa.
Quello che non è normale è che invece i nomi delle funzioni in PHP non sono case sensitive, cioè load_user_settings() è identica a LOAD_USER_SETTINGS(). Ma questa è una della particolarità di PHP che non lo rende particolarmente amato dai programmatori più radicali.
Non è particolarmente standard nemmeno il fatto che una variabile – anche se globale, cioè visibile in qualsiasi punto del programma – sia scritta tutta in lettere maiuscole. D’altra parte le variabili globali sono il male e secondo molti non dovrebbero proprio esistere perché sono la porta attraverso cui può entrare qualsiasi cosa.
2.
D’altra parte, anche nelle lingue naturali non sempre MARIO e mario sono la stessa cosa.
Le lettere maiuscole esistono da sempre, almeno nella nostra parte del mondo. Siamo talmente abituati a vedere epigrafi latine in maiuscolo da non farci più caso. Pare che i primi usi del minuscolo come default e del maiuscolo solo per evidenziare l’inizio di un periodo o un nome proprio risalgano al VII secolo d.C.; solo mille anni dopo si è cominciato a regolamentarne l’uso.
Oggi una parola scritta tutta in maiuscole è, in generale, un acronimo; ma ci sono alcuni esempi ben noti di come le maiuscole possano portare un significato preciso: re è una nota, Re è un capo di stato (il cosiddetto “maiuscolo reverenziale”). Italia si scrive sempre con la lettera maiuscola iniziale, mentre italiano no. Queste regole non sono sempre tassative ma sono grosso modo rispettate da tutti. Invece altre regole sono obbligatorie: Bari è una città, mentre bari è un verbo. Per un riassunto di queste regole si può vedere la Treccani (con la maiuscola): https://www.treccani.it/enciclopedia/maiuscola_(Enciclopedia-dell’Italiano)-(Enciclopedia-Italiana)/ . Curioso il fatto che invece il protocollo HTTP non prevede le maiuscole e le tratta esattamente come le minuscole. Quindi la URL di sopra è piuttosto bislacca…
I linguaggi di programmazione, malgrado quello che si può pensare, sono molto flessibili e aperti all’innovazione. Il vocabolario di ogni linguaggio è in generale molto piccolo, ma è facilissimo introdurre nuove parole. Ogni linguaggio ha due tipi di “parole”: quelle stabilite una volta per tutte dal creatore del linguaggio e quelle inventate dal programmatore ogni volta che scrive un programma. Ci sono però delle regole che dicono come si possono creare parole.
Per esempio, in PHP i nomi delle variabili (che sono dei cassetti destinati a contenere cose che serviranno in futuro, tipo i calzini o le mutande) possono iniziare con una lettera dell’alfabeto o con _ ma non con un numero; possono contenere numeri, ma non spazi.
Oltre a queste regole ferree, ce ne sono alcune che sono semplicemente parte di una specie di Galateo condiviso dai bravi programmatori, ma non sono veramente obbligatorie. Per esempio, i nomi delle costanti andrebbero scritti tutti in maiuscolo (es. const NODETYPE_LEAF); i nomi delle funzioni andrebbero scritti in minuscolo con le parti separate da trattini bassi (es. load_user_settings). Ci sono infiniti galatei di questo tipo, per ogni linguaggio, per ogni epoca, per ogni contesto. C’è ad esempio un galateo per Linux, scritto da Linus Torvalds in persona, che specifica quanto spazio deve essere lasciato a sinistra, quanto tra gli operatori e le variabili, quanto devono essere lunghi i nomi, eccetera.
In ogni caso, la lettera maiuscola è un segnale di importanza. Tant’è che nei primi sistemi di comunicazione digitali in cui non era possibile aggiungere colori e formattazione al testo, scrivere una frase in maiuscolo equivaleva a GRIDARE. Così USER è sicuramente più importante di user.
Cos’è quel simbolo di $ all’inizio del nome? Vuol dire che la variabile USER contiene una valuta? No, è una traccia antica che si può andare a seguire e che ci porta indietro di sessant’anni.
3.
Il linguaggio PHP è stato creato nel 1995 da Rasmus Lerdorf, un programmatore danese nato in Groenlandia e vissuto in Canada. L’aveva fatto per suoi scopi personali (l’aveva chiamato Personal Homepage Tools) ma PHP è finito per diventare uno dei linguaggi più usati al mondo per la programmazione dei siti web, anche per la sua facilità di apprendimento.
Non sappiamo quale fosse il primo computer con cui Lerdorf ha avuto a che fare, ma è probabile che lì sopra ci fosse il linguaggio BASIC. Il BASIC era stato creato trenta anni prima, nel 1964 da John Kemeny al Dartmouth College per facilitare l’apprendimento della programmazione anche per i non-ingegneri. Perché BASIC diventasse davvero il linguaggio che tutti potevano usare bisognò aspettare dieci anni e l’arrivo degli Home computer: computer che si potevano assemblare in casa, come l’Altair, e che avevano l’interprete del linguaggio BASIC già installato in ROM. Ancora dieci anni, e il BASIC diventa il linguaggio di accesso alla programmazione anche per chi acquista i Personal Computer IBM con sopra il sistema operativo MS DOS.
GW-BASIC era una delle versioni di BASIC dedicata a queste macchine. L’origine del nome non è mai stata chiara: forse significava”Graphics and Windows”, oppure “Gee-Whiz Basic” (O che roba! Basic) oppure Greg-Whitten (dal nome dello sviluppatore).
Comunque, a differenza del BASIC originale, in GW-BASIC c’erano due tipi di variabili: quelle che contenevano i numeri interi, su cui si potevano fare calcoli, e quelle che contenevano stringhe, cioè sequenze di lettere. Per dire all’interprete BASIC come trattare le une e le altre, i nomi delle variabili di tipo intero dovevano terminare con % mentre i nomi delle variabili di tipo stringa dovevano terminare con $.
10 LET A$="CIAO" 20 LET A%=1
Probabilmente, $ stava mnemonicamente per $tring. Lo stesso simbolo aveva significati completamente diversi in COBOL o in FORTRAN. In diversi casi, però, aveva a che fare con l’interpolazione, cioè la sostituzione di una variabile con il suo valore all’interno di una stringa. L’uso del simbolo $ nella storia dei linguaggi di programmazione è talmente vario che c’è un lungo paragrafo nella pagina di Wikipedia relativa che ne parla.
In PHP il simbolo $ in realtà non fa parte del nome della variabile, ma serve a indicare appunto che si tratta di una variabile. In altri linguaggi di programmazione non ci sono simboli particolari per differenziare le variabili, e meno che mai per indicarne il tipo. La creazione di una variabile va fatta esplicitamente con un’istruzione apposita, dichiarandone in anticipo il tipo:
string utente = "Mario" // C val utente : String = "Mario"; // Scala
In PHP non esiste un’istruzione specifica per creare una variabile: viene creata nel momento in cui ci si mette qualcosa dentro. Peraltro, il tipo della variabile viene inferito dall’interprete sulla base di quello che ci si mette dentro, e si può cambiare in qualsiasi momento. Se ci sono dentro dei calzini, allora è il cassetto dei calzini.
Anche se non è definito in questi termini nel manuale ufficiale, potremmo dire che $ è un po’ più di un indicatore: è un operatore che restituisce il valore della variabile.
Se creo una variabile e la chiamo ‘utente’, con l’espressione:
$utente
mi sto riferendo il suo valore.
Potrei creare un’altra variabile e chiamarla studente. Visto che PHP non è particolarmente esigente sui tipi di variabili, il valore di questa variabile potrebbe essere 1 (un numero intero) in un certo momento e in seguito diventare ‘mario’ (una sequenza di caratteri alfanumerici):
$studente = 1; //... $studente = 'mario';
In altri linguaggi questo sarebbe stato un errore: nel cassetto dei calzini non posso mettere le mutande. Ma PHP è piuttosto liberale a questo proposito. In effetti ci sono linguaggi rigidissimi, rigidi, meno rigidi e completamente lassisti. PHP è pericolosamente vicino a questi ultimi.
Niente mi impedisce di assegnare come contenuto di una variabile un’altra variabile:
$utente = $studente
Allora avrei che il valore di ‘utente’ è la variabile studente, il cui valore è ‘mario’.
L’operatore $ mi permette di ottenere direttamente il valore del valore di user. Quindi se
$user
vale $studente, allora
$$user
vale ‘mario’. Se pensate che sia un gioco, sappiate che nel codice sorgente di Moodle questa possibilità è sfruttata diverse volte.
In LOGO, linguaggio educativo nato negli anni ’60, un po’ prima di Scratch, e derivato dal LISP, questa doppia applicazione si sarebbe scritta così:
MAKE 'studente mario MAKE 'utente :studente
MAKE è la funzione che crea una variabile; l’apice indicava il nome della variabile e i due punti ne indicavano il contenuto. A volte le cose per bambini sono fatte meglio di quelle per i grandi.
4.
Tornando a PHP e a Moodle, nel caso specifico, $USER è l’oggetto che contiene l’utente che sta eseguendo lo script, mentre $user è uno degli utenti su cui si sta eseguendo l’operazione (cioè caricare le preferenze degli utenti).
Con le parole di Hemelryk:
/** * Loads the user settings block of the settings nav * * This function is simply works out the userid and whether we need to load * just the current users profile settings, or the current user and the user the * current user is viewing. * * This function has some very ugly code to work out the user, if anyone has * any bright ideas please feel free to intervene. * * @param int $courseid The course id of the current course * @return navigation_node|false */
Da un lato il programmatore – futuro direttore della produzione di Totara ma probabilmente molto giovane all’epoca – sapeva bene di non aver scritto il miglior codice del mondo (“Questa funziona ha del codice veramente brutto per elaborare l’utente, se qualcuno ha qualche idea brillante per favore si senta libero di intervenire”); dall’altro sembrava non avere le idee chiarissime o comunque non si era molto dato da fare per chiarirle (“Questa funzione è semplicemente elabora lo userid e se dobbiamo caricare solo le preferenze degli utenti correnti o l’utente corrente e l’utente che l’utente corrente sta guardando”).
Però questa cosa bislacca di avere due variabili identiche (a meno del maiuscolo/minuscolo) non è un’idea sua: è uno “standard” del codice sorgente di Moodle. In pratica $USER è una variabile globale, che contiene SEMPRE l’utente soggetto, quello che sta eseguendo lo script; $user invece può contenere qualsiasi cosa (purché di tipo utente): per esempio gli utenti registrati , quelli iscritti ad un corso o gli utenti che hanno accesso ad una certa risorsa.
In un altro frammento della classe Api, nella funzione update_policyagreed() si legge:
if (!$user || (is_numeric($user) && $user == $USER->id)) { $user = $USER;
Va ricordato che in generale nei linguaggi di programmazione == è un confronto, mentre = è un’assegnazione, tra l’altro da sinistra a destra. Quindi:
$user = $USER;
non è una verifica di identità, ma un’azione che cambia lo stato del sistema, costituisce un’identità. Non che questi due oggetti ora siano proprio lo stesso oggetto (cosa fattibile, ma che avrebbe richiesto un’altra forma: $user = &$USER) ma contengono lo stesso valore.
Leggiamo ora la prima riga, quella che inizia con if. Il punto esclamativo in PHP nega il valore di ciò che segue; quindi !$user è vero se $user non è stato definito oppure è falso.
Le due barre verticali significano “OPPURE” mentre i due ampersand significano “E”; is_numeric($user) è una funzione che abbastanza intuitivamente restituisce VERO se $user è un numero intero. Da questa riga si vede che $user potrebbe – in teoria – contenere qualsiasi cosa (niente oppure un numero); se è un numero, e se questo numero poi è uguale ad una certa proprietà di $USER, beh in questo caso… si butta tutto e si copia dentro $user il valore di $USER. Chiaro, no?
Verrebbe da dire: ma perché diavolo non chiamare $user e $USER in modo diverso? Perché lasciare in piedi questa ambiguità, anche se ogni Vero Programmatore di Moodle non ci casca? Perché non chiamarlo $student o al limite $someUser in modo che chiunque possa aprire un file e capire cosa sta succedendo?
Mistero. Certe volte si ha l’impressione che i programmatori non vogliano davvero essere capiti.
Lascia un commento
Devi essere connesso per inviare un commento.