Coding per docenti


Tutti possono programmare (cit. Ratatouille)

0.
I programmatori sono professionalmente autoreferenziali.
Nel senso che scrivono per essere letti da una casta ristretta: i computer, loro stessi e i pochi altri in grado di apprezzare le loro finezze. Se qualcun altro non capisce il loro codice sorgente, è un problema suo e non vale la pena di averci a che fare. In alcuni casi i programmatori si divertono a offuscare il loro codice e anzi gareggiano a che scrive il guazzabuglio (funzionante) più illeggibile. Non lo fanno tanto per proteggersi (tanto la proprietà del codice che producono non è loro, ma della società che li stipendia) ma proprio perché è così che affermano la loro autorità intellettuale. Non tanto diversi da chi dice che il latino serve a distinguere il futuro dirigente dal futuro youtuber.
Esagero un po’, ma è vero che la leggibilità del codice è sempre stata un cruccio per i manager. Se si lascia libero il programmatore, quello scrive in modo personale, contorto, incomprensibile. Per questo gli si insegna a dare nomi sensati alle funzioni o alle variabili, lo si invita a rispettare uno standard di fatto, a documentare il tutto possibilmente in una lingua conosciuta a livello planetario e non nel suo dialetto locale.
In sostanza, almeno per ora, i programmatori continuano ad essere una casta: c’è chi conosce i linguaggi e sa leggere il codice sorgente (meno di 30 milioni di persone in tutto il mondo, di cui la metà in Asia) e poi ci sono tutti gli altri miliardi di utenti che usano i programmi ma che non sarebbero mai in grado di capire come sono fatti e men che meno di modificarli per adattarli alle loro esigenze.
Tutto questo alla faccia dell’opensource, nel senso che un sorgente può anche essere rilasciato con una licenza permissiva, ma poi le competenze per modificarlo sono talmente rare che in pratica tutti finiscono per utilizzarlo così com’è. Non aiuta il fatto che il numero dei linguaggi di programmazione è enorme: sono circa 2000, anche se se ne usano una ventina.


La stessa situazione c’è con i software didattici e quelli utilizzati nella formazione. Anche i software aperti (come quelli che compongono So.Di.Linux, https://sodilinux.itd.cnr.it/) possono essere modificati solo da programmatori esperti ma non dagli utenti finali.

Ogni tanto capita che dei docenti si dedichino a progettare e realizzare dei software didattici. Era molto famosa, anni fa, la raccolta della maestra Ivana (https://www.ivana.it), che esiste tuttora. Di software educativi ne abbiamo fatti anche noi di Lynx, parecchi anni fa, anche se i nostri erano “software-autore”, cioè avevano come obiettivo quello di permettere ai ragazzi di creare, salvare, riaprire oggetti digitali complessi come mappe, vocabolari, esposizioni.
Spesso invece si trovano software didattici chiusi, cioè non progettati per essere modificati, ma solo per essere usati in un ambito disciplinare. In sostanza sono pensati usando come modello i software tradizionali, in cui c’è un soggetto esperto che cabla le sue conoscenze e abilità in un prodotto che gli altri – meno esperti – possono usare. E’, in fondo, la stessa idea che sta dietro i manuali scolastici e la formazione tradizionale.

La proposta che facciamo in questo articolo è invece quella di progettare e realizzare software educativi (semplici), modificabili direttamente da chiunque. Letteralmente: software che anche un docente che non abbia competenze informatiche possa adattare – fino ad un certo punto – al contesto del suo ambiente di apprendimento, ai suoi studenti, ai suoi limiti, ai suoi obiettivi.
Non si tratta solo di una questione tecnica: bisogna adottare un approccio diverso rispetto agli artefatti digitali. Approccio non nuovo, ma dimenticato.

1.
Si potebbe dire: ma perché, c’è ancora bisogno di persone che sappiano programmare? Tra gli usi rivoluzionari dei LLM e dei servizi di generazione di testi basati su questi c’è infatti la creazione di codice sorgente a partire da specifiche in linguaggio naturale.
In pratica, uno scrive: “fammi un pezzo di codice sorgente in Python che metta in ordine diecimila nomi”, e il servizio lo produce. Certo, per valutare se il codice è corretto e ben fatto occorre comunque un programmatore esperto.
Ma la programmazione automatica non è proprio una novità: la capacità di completare un codice su base probabilistica esisteva da tempo, anche se molto più limitata. Esistono anche, da qualche anno, dei servizi di Low Coding (https://www.ibm.com/it-it/topics/low-code), cioè degli ambienti in cui anche un utente senza abilità di programmazione può definire la logica di un programma tramite strumenti grafici (frecce, rettangoli) e ottenere un programma funzionante.
Anche i software di cosiddetto “coding” per bambini come Snap!, Scratch eccetera in fondo fanno questo: permettono di specificare il funzionamento voluto senza dover conoscere un linguaggio di programmazione convenzionale (testuale), ma limitandosi a utilizzare blocchetti colorati che hanno dei vincoli per escludere errori di sintassi.
Il principio è sempre lo stesso, dai lontani anni ’50: il processore può essere programmato solo in un linguaggio ultraspecialistico e difficile da imparare; però si possono creare dei mediatori che traducono in quel linguaggio dei testi scritti in un linguaggio più semplice. Questo processo può essere ripetuto a piacere, fino ad arrivare appunto al prompt: “per favore scrivimi un programma che mi fa la lista della spesa”.

2.
Ma ci sono stati momenti in cui qualche visionario illuminato ha pensato di andare in una direzione diversa: creare dei linguaggi facili, utilizzabili da tutti o quasi. Invece di immaginare dei linguaggi potenti, vicini alla maniera di funzionare dei computer, perché non pensarne di semplici, meno efficaci ma vicini alla maniera umana di pensare e affrontare i problemi?
Alla fine degli anni ’50 servivano programmi per gestire le transazioni finanziarie. Certo si sarebbero potuti scrivere in ForTran (Formula Translator), che però come dice il nome stesso era un linguaggio scientifico, adatto ai matematici e agli ingegneri. Si decise invece di inventare un linguaggio che fosse utilizzabile anche da persone che non avevano una preparazione scientifica. Nacque il COBOL: Common Business-Oriented Language. Con il COBOL sono stati scritti i programmi che gestiscono tuttora i bancomat di tutto il mondo.
Pochi anni dopo, alcuni docenti del Dartmouth College fecero un passo ancora più ambizioso: siccome era chiaro già da allora che sarebbero serviti sempre più programmatori, Kemeny e Kurtz decisero di inventare un linguaggio che fosse talmente semplice che chiunque, letteralmente, potesse usarlo: il BASIC (Beginners All-purpose Symbolic Instruction Code). Un linguaggio per tutti gli usi e adatto ai principianti. Anche questo, come il COBOL, prende in prestito parole del vocabolario inglese, ma è ancora più semplice e flessibile.
Ci sono in totale solo 40 “parole” da imparare, tra istruzioni e comandi. Non c’è un ordine definito nella struttura del programma e anzi si può indicare al processore di saltare qua e là nel codice sorgente tramite un’istruzione speciale, (GOTO, https://it.wikipedia.org/wiki/GOTO). Per i curiosi, qui https://alandix.com/wp-content/uploads/2021/07/BASIC_Oct64.pdf c’è il manuale del BASIC originale.

3.
Pensato per usi educativi, il BASIC è uscito dai recinti accademici in poco tempo: si cominciano a vedere all’inizio degli anni ’70 gli home computer, che costano una frazione infima rispetto ai grandi server, e persino rispetto ai mini-computer dell’epoca. Chiunque poteva programmare in BASIC su un Commodore (anche il sottoscritto l’ha fatto) e creare videogiochi o software gestionali personalizzati.
Ma malgrado questi sforzi, come sa chiunque si occupa anche marginalmente di questi temi, l’era dell’informatica fatta in casa è finita presto, grazie anche a un marketing furbo che ha spostato il valore da “sapere come funziona” a “sapere come si usa”. Tutti, in questa parte del mondo, abbiamo in casa un notevole numero di computer, travestiti in tante maniere diverse (tablet, telefoni, televisori, orologi, lavatrici, forni, frigoriferi, …); nessuno di noi però sa come funzionano né sarebbe in grado di modificarli oltre il limite previsto dai progettisti, cioè tramite bottoni e icone. E anche se sapesse farlo, non potrebbe perché il contratto con cui il software viene distribuito non lo permette quasi mai.
Insomma esiste una cultura diffusa del bricolage e del fai-da-te analogico, ma non esiste l’equivalente digitale.

4.
I software sono oggetti complessi. Possono essere molto grandi e ragionevolmente fin dai primi linguaggi si è cercato di costringere il programmatore a organizzare il codice sorgente in modo che non solo il computer, ma anche ogni altro programmatore fosse in grado di capirne la struttura. Così ogni linguaggio ha delle regole che potremmo chiamare “retoriche”, cioè che non riguardano la sintassi delle istruzioni, ma proprio la struttura generale del testo, esattamente come ogni lettera inizia con “Caro amico” e finisce con “Tanti saluti” mentre un Decreto presidenziale inizia con una serie di “Visti..” e finisce con la formula “È fatto obbligo a chiunque spetti di osservarlo e di farlo osservare.”
Non tutti i linguaggi hanno una retorica obbligatoria; alcuni sono piuttosto disinibiti e permettono di giocare liberamente con l’ordine delle parti, mentre altri sono rigidi e non ammettono eccezioni.
Ci sono però delle suddivisioni che non sono né obbligatorie, né specifiche per un certo linguaggio, ma hanno a che fare con una sorta di etichetta, di bon ton della programmazione, e sono trasversali. Una delle più diffuse, legata al paradigma della programmazione orientata agli oggetti, è quella tra Modello, Vista e Controllo. In questa visione, il Modello è la parte del programma che mima il dominio del problema ed è responsabile del funzionamento interno, mentre la Vista e il Controllo costituiscono l’interfaccia tra l’utente il modello.
Da un punto di vista più generale, ogni software può essere visto come composto da tre parti: i dati, l’interfaccia utente e la struttura che connette i primi con la seconda realizzando le funzionalità richieste al programma.
Questa tripartizione può essere più o meno esplicita: più lo è, più è facile modificare il software dopo il suo rilascio, perché si capisce dove bisogna mettere le mani. Inoltre si evitano gli effetti collaterali: se si vuole cambiare la maniera in cui il software comunica con gli utenti, deve essere possibile farlo senza toccare il suo funzionamento. E’ anche uno dei principi della progettazione accessibile: più versioni di un software che fanno le stesse cose ma usando interfacce utente diverse.

5.
Questa divisione era presente già nel primo linguaggio di programmazione che usava termini presi dal linguaggio naturale, l’Assembly. Un codice sorgente Assembly è composto di tre sezioni:

  • data (ovvero i dati iniziali)
  • stack (ovvero le variabili da utilizzare durante l’esecuzione)
  • text (ovvero le istruzioni)

Anche in COBOL ogni programma ha una struttura fissa articolata in divisioni: IDENTIFICATION, ENVIRONMENT, CONFIGURATION etc. I dati sono separati dalle istruzioni (PROCEDURE) e inseriti in una apposita divisione.

IDENTIFICATION DIVISION.
PROGRAM-ID. DIVISION-REPRESENTATION.
AUTHOR. RUPA KUMARI.
INSTALLATION. MF.
DATE-WRITTEN. 18 AUG 2022.
DATE-COMPILED. 18 AUG 2022.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER.
OBJECT-COMPUTER.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-VAR PIC X(50).
PROCEDURE DIVISION.
MAIN-PARA.
DISPLAY ‘ROW 1-6 COMES UNDER IDENTIFICATION DIVISION’.
DISPLAY ‘ROW 7-12 COMES UNDER ENVIRONMENT DIVISION’.
DISPLAY ‘ROW 13-15 COMES UNDER DATA DIVISION’.
DISPLAY ‘ROW AFTER 16 WILL COMES UNDER PROCEDURE DIVISION’.
STOP RUN.

In BASIC, che pure è un linguaggio molto meno rigido del COBOL, era possibile definire esplicitamente i dati da usare con un’apposita istruzione DATA, seguita dai valori.
Questi dati, che dovevano essere posizionati alla fine del codice sorgente, venivano letti sequenzialmente dall’istruzione READ.

10 READ AI, AZ, A3, A4
15 LET D = AI * A4 – A3 * AZ
ZO IF D = 0 THEN 65
30 READ BI, BZ
37 LET XI = (BI * A4 – BZ * AZ )
4Z LET XZ = ( AI * BZ – A3 * BI)
55 PRINT XI, XZ
60 GO TO 30
65 PRINT “NO UNIQUE SOLUTION”
70 DATA 1, 7, 4
80 DATA 7,-7,5
85 DATA 1, 3, 4, -7
90 END

In BASIC, come in COBOL, ci sono apposite istruzioni per comunicare con l’utente: PRINT (come DISPLAY del COBOL) scrive un risultato sullo schermo. Esiste anche INPUT, che fa il contrario, cioè legge un dato dalla tastiera. In questo modo si realizza un’interfaccia utente, per quanto minimalistica.

C’è almeno un terzo linguaggio che è stato inventato negli anni ’70 (in Francia, stavolta) con un approccio in qualche modo simile: non un linguaggio costruito sullo schema della macchina, ma un linguaggio costruito avendo in mente un’attività umana specifica, che è la risoluzione di problemi logici. La stessa divisione tra dati, struttura e interfaccia che abbiamo visto nel COBOL si ritrova in Prolog. Un programma è composto da tre sezioni:

  • i fatti
  • le regole
  • gli obiettivi da dimostrare

Per esempio:
– fatti: Edgar è un corvo
– regole: tutti i corvi sono neri
– obiettivo: si può dimostrare che Edgar è nero?

La particolarità del Prolog è che il motore che è in grado di dimostrare gli obiettivi utilizzando i fatti e le regole fornite è già compreso nell’interprete del linguaggio. In poche parole, in Prolog non si dice come va risolto un problema, ma si descrive il problema in termini di conoscenze note e si chiede all’interprete di dimostrare un fatto nuovo.

Una curiosità storica: in Prolog la maniera normale di interagire con un programma è fargli domande attraverso un prompt testuale. Interfaccia non significa soltanto icone e bottoni.

6.
Al di là dei riferimenti storici, l’idea di fondo questo articolo è immaginare dei Software Educativi Modificabili a partire da questo modello, ispirandosi alla tripartizione di cui abbiamo parlato sopra.
I SEM sono divisi in tre parti, in ordine decrescente di trasparenza e modificabilità:

  • i dati, che devono essere completamente modificabili direttamente dal docente senza nessuna competenza
  • l’interfaccia, che è limitatamente modificabile, con un minimo di competenza
  • la struttura, che non è modificabile dal docente perché troppo complessa.

Queste tre parti possono convivere in un solo file, oppure essere affidate a tre files diversi, per rendere più facile la modifica indipendente e minimizzare i rischi di errore.

Ad esempio, un software per fare sondaggi su web dovrebbe produrre una pagina HTML con le domande e le possibili risposte.
Le risposte dovrebbero essere salvate e al termine dovrebbe essere mostrato un riassunto delle risposte date fino a quel momento.

Di conseguenza, il suo codice sorgente dovrebbe comprendere:

  • le domande, con le possibili risposte alternative: semplici elenchi di frasi o parole
  • la specifica della maniera in cui le domande sono visualizzate (font, colori, dimensioni, posizione)
  • le funzionalità per raccogliere le risposte e scriverle su un file

Per modificare una domanda, o per toglierne e aggiungerne una, deve essere sufficiente intervenire sulla sezione dati.
Si potrebbe definire una collezione di domande (che si chiama “domande” e che si riconosce perché è racchiusa tra parentesi quadre) che al suo interno contiene delle semplici frasi separate da virgola:

Ad esempio:


"domande" : [
     "Hai mai usato un servizio di generazione di testi (es. ChatGPT)?",
     "Hai mai usato un servizio di generazione di immagini (es.Midjourney)?"
]

La stessa cosa per le possibili risposte. Che essendo appunto alternative si chiamano “alternative” e per ognuna presentano una collezione di opzioni (non necessariamente le stesse per ogni domanda):

"alternative" :  [
    ["Sì","No"],
    ["Mai","Qualche volta","Spesso"],
]

Ma è possibile che il docente voglia andare oltre, e invece di un sondaggio voglia realizzare un quiz (sorvoliamo sulle motivazioni e sulle finalità, che non necessariamente sono valutative). Potrebbe aggiungere altre domande:

"domande" : [
    "Quanto fa sette per otto?",
    "Come si chiamava il cavallo di Alessandro Magno?"
]

E altre risposte alternative:

"alternative" :  [
    ["42","48","56"],
    []
]

In questo caso, dovrà inserire le risposte corrette:

"corrette" : [
    ["56"],
    ["bucefalo"]
]

Il passaggio dal sondaggio al quiz non dovrebbe essere traumatico, perché la struttura prevede già questa estensione, che in effetti è ragionevole. In sostanza, i dati stessi dovrebbero pilotare la struttura.
Come si è visto:

"alternative" :  [
    ["42","48","56"],
    []
]

significa che la seconda domanda non ha nessuna risposta tra cui scegliere: bisogna scrivere la risposta in un campo libero. Così:

"corrette" : [
    [],
    [],
]

significa che le domande 1 e 2 non hanno una risposta corretta, ma sono solo una richiesta di opinione.

L’interfaccia in questo esempio è composta fondamentalmente dai campi con le domande e le risposte; questi possono essere posizionati a destra, al centro, a sinistra; possono essere scritti con colori e caratteri diversi.
Siccome il programma viene proposto sul web, la sua interfaccia è necessariamente in HTML, che è un particolare linguaggio di descrizione delle interfacce. Dalla metà degli anni ’90, la descrizione dell’aspetto di una pagina HTML è affidata ad uno o più fogli stile separati (CSS: Cascading Style Sheets). I CSS permettono una gestione molto sofisticata della maniera in cui gli oggetti sono disposti sulla pagina, in termini non solo di posizione ma di piani, di adattamento alle dimensioni dello schermo, animazioni, eccetera.

Se però il docente non è esperto di CSS, può utilizzare lo stesso metalinguaggio che ha usato per i dati, che riduce le possibilità offerte dai Fogli Stile a poche opzioni essenziali:


"domanda" : {
    "colore" : "blue" ,
    "carattere" : "Arial" ,
    "dimensione" : "large" ,
    "stile" : "normal"
},
"risposta" : {
    "colore" : "red" ,
    "carattere" : "Arial" ,
    "dimensione" : "large" ,
    "stile" : "italic"
},

La grammatica che abbiamo utilizzato per specificare dati e interfaccia non è una nostra invenzione: è quella di JSON (JavaScript Object Notation), che è un formato standard definito ufficialmente nel 2013 anche se era giù utilizzato da anni per poter scambiare dati tra programmi diversi.
Si potrebbero usare altri linguaggi di marcatura universali, come l’XML o il più recente YAML che è ancora più semplice e si usa per definire le configurazioni dei software.
Un esempio del software che abbiamo appena descritto (con dati diversi) potete vederlo all’opera qui: https://www.stefanopenge.it/public/survey

Nota: grazie a Paolo Mauri ho scoperto i lavori di Cedric Eyssette, professore di filosofia con passione per il software. Tra questi, Text2quiz permette di creare un questionario con vari tipi di domande a partire da una specifica affidata ad un file in formato Markdown. I dati assomigliano a questo:

Etiquettes || Le génie | Le contraire du génie || {{ inventer | la créativité de l'imagination | produire originellement son monde | l'originalité | servir de modèles }}{{ imiter | le mécanisme de l'instruction | reproduire ce que d'autres ont fait | la conformité aux règles | se servir de modèles}} || 

Ovviamente per questo caso specifico (un sondaggio o un quiz) esistono addirittura dei linguaggi appositi per definire domande e risposte, come Aiken o GIFT.
Ma noi qui stiamo parlando di un approccio da utilizzare per qualsiasi tipo di software, in cui i dati possono essere qualunque cosa.
Un software che voglia rappresentare graficamente la densità della popolazione italiana diveisa in regioni, ad esempio, potrebbe specificare i suoi dati così:


{
"regioni" : {
    "lazio" : {
        "superficie" : 17242,
        "popolazione" : 5712518
},
    "campania" : {… }

Cosa faccia esattamente questo software, come interagisca con gli studenti, non è definito. Ma possiamo aspettarci come minimo che sia in grado di creare una tabella esplorabile, o ricercabile. Oppure una mappa colorata dell’Italia.
Questo stesso software potrebbe costruire altre mappe, colorate diversamente, a seconda dei dati che gli si passano: piovosità, numero di biblioteche per abitante, affollamento degli ospedali, eccetera.
Da un altro punto di vista, si potrebbe partire da questi dati demografici per immaginare un nuovo software. E’ un po’ quello che succede con gli OpenData, che però di solito sono considerati “cose da specialisti” e non sono mai riusciti ad entrare veramente negli ambienti di apprendimento.

7.
In conclusione, potremmo provare a definire in maniera astratta alcun principi dei software educativi modificabili:

I principi dei SEM:

I. nessuno programma da solo
Programmare è un’attività complessa ed è normale che occorrano più competenze per portarla avanti..
Ma è anche normale che si intervenga su un programma esistente (fatto da qualcun altro), e poi si rilasci per modifiche e usi futuri.
Più persone, nel tempo, possono mettere le mani sullo stesso codice.
Questa dovrebbe essere la maniera normale di concepire la vita di un programma.

II. i dati sono “parlanti”
I dati dovrebbero avere dei nomi comprensibili, che dicono quello che contengono, e un’organizzazione interna che punta più alla naturalezza che all’efficacia. Questo aiuta nel caso in cui qualcun altro voglia intervenire in futuro. In generale, l’efficenza non dovrebbe essere prioritaria sulla comprensione

III. i dati pilotano la struttura
Non dovrebbe essere necessario andare a modificare la struttura per ottenere risultati diversi, ma dovrebbe essere sufficiente (fino ad un certo punto) modificare i dati.

IV. l’interfaccia si perfeziona per specifiche successive
Dovrebbe esserci un’interfaccia minimalista, di partenza, da arricchire. In altre parole, le specifiche dell’interfaccia non sono obbligatorie (come lo sono quelli dei dati) ma aggiungono valore.

V. interfacce diverse per persone diverse
Invece di cercare di definire l’interfaccia che va bene per tutti, dall’inizio si dovrebbero prevedere versioni alternative in funzione delle possibilità dello studente. Dimensioni, contrasti, colori, font ma anche densità delle informazioni, lunghezza delle frasi eccetera.

VI. una specifica, molti utilizzi
La maniera di specificare i dati (e anche, più limitatamente, l’interfaccia) dovrebbe essere indipendente dal linguaggio di programmazione usato per la struttura. In altre parole, la divisione DATI dovrebbe essere agnostica, al punto che si potrebbe riscrivere la struttura in un altro linguaggio di programmazione senza dover modificare i dati. Oppure trasportare dei dati da un programma all’altro. Lo stesso dovrebbe valere per l’interfaccia.


Pubblicato

in

, , , , , ,

da