Sei sulla pagina 1di 85

ESAME INFORMATICA (6 CFU)

CAPITOLO UNO

1. Che cos’è un computer?

Il termine computer (calcolatore, in italiano) è in uso, oggi, per indicare una “macchina per
l'elaborazione di dati rappresentati da caratteri alfanumerici variamente codificati, che vengono
sottoposti a procedimenti aritmetici e logici, memorizzati in archivi e resi reperibili e trasmissibili” –
dal dizionario di Repubblica.it. Tuttavia, la definizione originale dello stesso termine, in uso dal
diciassettesimo secolo, è leggermente differente, visto che si riferisce a qualcuno che “esegue calcoli
matematici” – da Wikipedia. In questo capitolo, quando useremo il termine “computer”,
considereremo sempre la sua accezione più generica, ovvero: qualsiasi agente (ovvero, quell’entità in
grado di agire se istruita appropriatamente, come una persona o una macchina) che è in grado di
fare calcoli e produrre una risposta (detta output) a partire da qualche informazione iniziale (detta
input).

Computer umani, ovvero gruppi di persone che hanno eseguito lunghi calcoli per determinati
esperimenti, sono stati impiegati molte volte nel passato. Per esempio, in astronomia, computer
umani sono stati impiegati per calcolare le coordinate astronomiche di oggetti extraterrestri – come
i calcoli effettuati da Alexis Claude Clairaut e colleghi per comprendere i vari passaggi della cometa
di Halley. Come ulteriore esempio, computer umani sono stati usati anche da Napoleone Bonaparte
quanto questo ha imposto la creazione di tabelle matematiche per convertire i valori descritti con il
vecchio sistema di misura imperiale verso il nuovo sistema metrico (tutt’ora in uso) [Campbell-Kelly,
2009] [Roegel, 2010].

Nel 1822, Charles Babbage, capendo la complessità di eseguire tutti questi calcoli a mano evitando
l’introduzione di errori, iniziò lo sviluppo di una nuova, incredibile, macchina, chiamata Macchina
Differenziale, mostrata in Figura 1. L’idea era quella di avere a disposizione una macchina che
potesse gestire operazioni simili a quelle effettuate dai computer umani, ma in modo che fossero
eseguite automaticamente, velocemente, e senza errori. Babbage fu in grado di costruire solo un
prototipo parziale della macchina e, dopo l’entusiasmo iniziale, fu demoralizzato dalla limitata
flessibilità che offriva. Infatti, la Macchina Differenziale non era programmabile e, di conseguenza,
era in grado di utilizzare solo un numero limitato di operazioni sull’input ricevuto – specificato,
fisicamente, cambiando specifiche configurazioni della macchina.

In modo da sopperire a queste limitazioni, nel 1837, Babbage iniziò a progettare una nuova
macchina, la Macchina Analitica, mostrata in Figura 2. Seppur nessun prototipo di questa macchina
sia stato effettivamente costruito da Babbage, in linea di principio avrebbe dovuto permettere la
creazione di qualunque calcolo procedurale, rendendola il primo computer meccanico e general-
purpose della storia. Contrariamente al suo predecessore, la Macchina Analitica era in grado di
ricevere in input istruzioni e dati mediante l’uso di schede perforate, senza obbligare l'utilizzatore,
quindi, a compiere manipolazioni fisiche della macchina stessa per farla funzionare.

C’è voluto più di un secolo per vedere sviluppate in una macchina fisica le idee presentate nella
Macchina Analitica. Infatti, l’evoluzione della tecnologia computazionale ha avuto una brusca
accelerata soltanto a seguito della Seconda Guerra Mondiale. In quei tempi, molti calcolatori furono
costruiti per ragioni militari, come, ad esempio, la Bomba (1940) (Figura 3), sviluppata da Alan
Turing, che è stata il principale strumento che ha permesso a un gruppo di persone, rinchiuse nella
base militare segreta britannica di Bletchley Park, di decifrare (grazie anche al lavoro pregresso fatto
da crittologi polacchi come Marian Rejewski) le comunicazioni tedesche che erano state cifrate dalla
macchina Enigma.

Mentre la Bomba era una macchina estremamente efficace ed efficiente, era altresì parzialmente
basata su componenti prettamente meccanici, e permetteva lo svolgimento di una sola operazione,
anche se estremamente cruciale da un punto di vista squisitamente storico. Il primo computer
interamente digitale, come pensato da Babbage con la sua Macchina Analitica, è stato sviluppato
negli Stati Uniti d’America soltanto qualche anno dopo, nel 1946: l’Electronic Numerical Integrator
and Computer (ENIAC), mostrato in Figura 4, che era completamente programmabile attraverso
l’uso di cavi e interruttori. Questa invenzione è stata una delle più cruciali pietre miliari della storia
dei computer elettronici, rappresentando una sorta di “punto fisso” nel tempo da cui tutti i moderni
computer sono poi stati creati.

2. Pensiero computazionale
Spesso diciamo di programmare un computer – dove la parola “computer”, in questo caso, si
riferisce a un computer elettronico. Tuttavia, come anticipato nella definizione che abbiamo fornito
in questo capitolo, un computer può essere sia una macchina sia un essere umano. Tuttavia, il verbo
programmare non si presta particolarmente bene ad essere usato con computer umani – visto che
non possiamo letteralmente programmare una persona (anche se qualche pseudoscienza, come la
programmazione neuro-linguistica, sostiene di poterlo fare). Casomai diciamo che parliamo con una
persona per istruirla sull’esecuzione di specifiche azioni attraverso l’uso di un particolare linguaggio
(in questo caso naturale) che viene usato come canale di comunicazione. Di conseguenza, in questo
contesto, si dovrebbero usare gli stessi verbi, ovvero parlare e istruire, anche quando ci si riferisce ad
un computer elettronico perché, di fatto, è quello che succede. In pratica, scrivere un programma è
esattamente questo: comunicare ad un computer elettronico utilizzando un linguaggio (in questo
caso formale) che sia l’istruttore umano sia il computer stesso possano comprendere [Papert, 1980].

Una volta d’accordo su quale linguaggio usare per la comunicazione tra l’istruttore e il computer (a
prescindere dal fatto che questo sia un umano o una macchina), dovremmo iniziare a pensare una
sequenza di possibili istruzioni da comunicare che, se seguite sistematicamente, possono restituire un
risultato atteso per risolvere un certo problema. In modo da raggiungere questo obiettivo,
solitamente (e inconsapevolmente) proviamo a ricercare possibili soluzioni per il problema in
questione confrontandolo con possibili situazioni che si sono già presentate in passato – e che,
plausibilmente, abbiamo già risolto. L’idea è quella di trovare un pattern (schema ricorrente) che
fornisca una possibile soluzione a un insieme di situazioni che, a livello astratto, sono del tutto
omogenee, in modo da poter riusare la stessa strategia per raggiungere il nostro obiettivo, se questa
è stata soddisfacente nel passato. Per esempio, alcune delle azioni che eseguiamo in un ufficio postale
sono abbastanza simili a quelle che eravamo abituati a svolgere quando, da piccoli, aspettavamo il
nostro turno per giocare con lo scivolo in un parco.

Considerando le situazioni e contesti appena riportati, possiamo definire il pensiero computazionale


come un approccio per risolvere problemi, sviluppare sistemi e capire il comportamento umano che
riprende i concetti fondamentali della computazione [Wing, 2008] – dove con la parola
computazione si intende calcolo. Il pensiero computazionale definisce i processi mentali che
coinvolgiamo quando formuliamo un certo problema ed esprimiamo le relative soluzioni usando un
linguaggio che un computer (sia esso umano o macchina) può comprendere e, conseguentemente,
eseguire.

Jeannette Wing fornisce una definizione aggiuntiva, per chiarire ancor meglio cosa si intenda per
pensiero computazionale [Wing, 2008]:

[Traduzione libera in italiano: “Il pensiero computazionale è un tipo di pensiero analitico. Condivide, con il
pensiero matematico, il modo in cui possiamo approcciare un problema per trovarne la soluzione. Condivide,
con il pensiero ingegneristico, il modo in cui possiamo affrontare la progettazione e la valutazione di grandi
sistemi complessi che operano all’interno dei limiti del mondo reale. Infine, condivide, con il pensiero
scientifico, il modo in cui possiamo trattare la comprensione della calcolabilità, l’intelligenza, la mente e il
comportamento umano.”]

La nozione principale dietro al pensiero computazionale è l’astrazione, ovvero l’abilità di esercitare


pensiero astratto e di esibire abilità di astrazione – che comporta il processo di rimozione dei
dettagli trascurabili di una situazione in modo da semplificarla, per così focalizzare l’attenzione sulle
sue caratteristiche principali [Kremer, 2007]. Come già anticipato nell’esempio descritto in Figura 5,
l’abilità di astrarre situazioni e nozioni è cruciale per automatizzare l’esecuzione di determinate
operazioni attraverso l’uso di un computer che è responsabile dell’interpretazione di queste
astrazioni. Di solito, noi usiamo queste astrazioni in modo intenzionale o inconscio nella vita
quotidiana, come quando usiamo un contenitore sia per metterci degli oggetti (per esempio un
carrello della spesa), sia quando lo immaginiamo per metterci delle azioni da svolgere (per esempio
una lista scritta o mentale delle cose da fare prima di pranzo), o addirittura quando vediamo cose
dove non ci sono, come nel caso della pareidolia (Figura 6), perché alcune caratteristiche percettive
hanno una forma simile a ciò che crediamo di, o vogliamo, vedere.

Uno degli obiettivi del pensiero computazionale è quello di dare nuovamente forma alle astrazioni
che abbiamo già immagazzinato in passato come conseguenza della nostra esperienza personale – e
che, spesso, riusiamo inconsciamente. Quindi, per essere nuovamente e interamente coscienti di
queste astrazioni, dobbiamo ridefinirle usando un linguaggio appropriato per renderle comprensibili
a un computer.

Questo richiede a volte una notevole capacità di introspezione e di riflessione sulle caratteristiche
più importanti di un oggetto, di un discorso o di una situazione, non troppo diversamente da ciò che
avviene nel pensiero filosofico o semiotico, ma sempre garantendo precisione e adeguatezza alla
risoluzione di problemi e alla rappresentazione del loro contenuto. Questo indipendentemente dal
fatto che vogliamo risolvere il problema di come elaborare un testo digitale, di come organizzare i
dati relativi a un’indagine archeologica, o di come trovare il modo migliore per raccomandare un
prodotto o un servizio. A livello generale, l’obiettivo principale (dell’insegnamento) del pensiero
computazionale è quello di permettere alle persone di pensare come se fossero computer scientist,
anche quando bisogna affrontare attività del quotidiano. In futuro, il pensiero computazionale sarà
parte integrante dell’educazione primaria delle persone [Wing, 2008], come la matematica e la fisica,
e plasmerà il modo in cui le persone pensano e imparano [Papert, 1980] e di conseguenza, vivono.
In modo indiretto, questo sta già avvenendo attraverso la trasformazione dei sistemi di produzione e
comunicazione: il Web e i social media, gli “orchestratori di reti” (come AirBnB e Uber), etc.
Categorie fondamentali dell’esistenza umana: spazio, tempo, identità, immagine pubblica, collettività,
pianificazione, relazioni interpersonali, etc. sono tutte influenzate dalla trasformazione sociotecnica
in maniera più veloce e profonda di quanto sia avvenuto negli ultimi secoli.

3. Strutture dati

Uno dei processi di base dell’attività di astrazione è quella di descrivere l’informazione presente in
una certa situazione secondo un’organizzazione generica e riutilizzabile in più contesti. Per fare ciò,
si usano quelle che comunemente sono chiamate strutture dati. Le strutture dati sono i modi in cui
possiamo organizzare l’informazione e i dati da essere processati (input) e restituiti (output) da un
computer, in modo da potervi accedere in modo efficiente ed efficace a livello computazionale. In
pratica, una struttura dati è una sorta di contenitore dove possiamo posizionare alcune informazioni,
e che fornisce dei metodi specifici per aggiungere e richiedere pezzi di questa informazione.

Tra le più semplici strutture dati abbiamo: le liste, le code, le pile, gli insiemi, i dizionari, gli alberi e i
grafi. Tutte queste strutture verranno analizzate nelle sottosezioni che seguono, fornendo esempi
delle loro applicazioni in scenari quotidiani.

LISTA → è una sequenza di elementi ordinati e ripetibili che si possono contare, perché si può
sapere quanti elementi essa contiene in un dato momento. I suoi elementi sono ordinati perché sono
posizionati in uno specifico ordine di precedenza tra loro, che è preservato anche quando
aggiungiamo e rimuoviamo determinati elementi. Inoltre, gli elementi in una lista sono ripetibili,
visto che possono comparire più di una volta in una lista – ad esempio, se proviamo a creare una
lista di caratteri della parola “pensiero”, la lettera “e” comparirà due volte, una in seconda posizione,
e un’altra in sesta posizione. Esistono diversi esempi tratti da situazioni reali di queste liste astratte.
Per esempio, in Figura 7, sono mostrati un indice di un libro e una lista di riferimenti bibliografici
in un articolo scientifico. Entrambi sono due oggetti concreti costruiti partendo dalla nozione
astratta di lista.

PILA → una pila è una specie di lista vista da un particolare punto di vista, ovvero dal basso verso
l’alto, e con uno specifico insieme di operazioni che si possono effettuare sugli elementi della pila.
Figura 8 mostra due esempi di pile in oggetti di tutti i giorni. In particolare, abbiamo una pila di
sedie (a sinistra) e una pila di libri (a destra). La caratteristica principale degli elementi di questa
struttura riguarda le operazioni di aggiunta e rimozione, che seguono una strategia last in first out
strategy (LIFO) – ovvero, l’ultimo elemento che viene inserito è il primo ad essere rimosso. Infatti,
l’ultimo elemento inserito nella struttura è posizionato in cima alla pila e, quindi, è anche il primo
che verrà rimosso se richiesto. Inoltre, se si vuole rimuovere un elemento in mezzo alla pila, è prima
necessario rimuovere tutti gli elementi

che sono stati posizionati dopo questo, dal più recente al più vecchio.

CODA → Una coda è una specie di lista vista da un’altra prospettiva, ovvero da sinistra verso
destra, e con uno specifico insieme di operazioni che possono essere effettuate sugli elementi che
contiene. Figura 9 mostra due differenti esempi di code in situazioni del quotidiano: una coda di
bambini (sinistra) e una linea di attesa di taxi (destra). La caratteristica principale degli elementi di
questa struttura riguarda le operazioni di aggiunta e rimozione degli elementi, che seguono una
strategia first in first out strategy (FIFO) – ovvero, il primo elemento che viene aggiunto è anche il
primo che viene rimosso a seguito di una richiesta. In pratica, il primo elemento inserito nella
struttura è posizionato nella parte libera più a sinistra della coda e, di conseguenza, è anche il primo
che verrà rimosso quando richiesto. In modo del tutto simile alle pile, anche nelle code, se si vuole
rimuovere un certo elemento in mezzo, è necessario prima rimuovere tutti gli elementi che sono
stati aggiunti prima di esso.

INSIEME → è una collezione di elementi non ordinati e non ripetibili che si possono contare. I
suoi elementi non sono ordinati perché l’ordine di inserimento di questi non prescrive nessuna
relazione di cardinalità tra loro. Inoltre, sono non ripetibili perché lo stesso valore non può essere
incluso due o più volte. Ovviamente, esistono diversi esempi di questa struttura dati in oggetti e
situazioni di vita quotidiana. Per esempio, Figura 10 mostra una classe di studenti e una collezione
di colori. Entrambe sono oggetti concreti costruiti a partire dalla nozione astratta di insieme.

DIZIONARIO → un dizionario (o array associativo) è una collezione non ordinata di elementi


definiti da coppie chiave-valore che si possono contare, dove la chiave non è ripetibile. I suoi
elementi sono non ordinati perché l’ordine di inserimento non prescrive nessuna relazione di
cardinalità tra gli elementi, in modo del tutto simile agli insiemi. Inoltre le chiavi di ogni coppia non
sono ripetibili perché la stessa chiave non può essere usata due o più volte nel dizionario.
Ovviamente, esistono diversi esempi di questi dizionari astratti in oggetti di uso quotidiano. Per
esempio, in Figura 11, sono mostrate una collezione di definizioni e una tabella di conversione di
valuta. Entrambe sono oggetti concreti che sono stati costruiti partendo dalla stessa nozione astratta
di dizionario.

ALBERO → l’attività di marcatura di un testo – ovvero, l’annotazione che vi si può fare,


riconoscendo i vari ruoli strutturali e semantici delle varie parti che lo compongono, come
l’identificazione delle sezioni, capoversi, dialoghi, etc. – è un’attività che si compie sistematicamente,
e in modo inconsapevole, ogni qual volta si prende un documento da analizzare o, molto più
generalmente, da leggere. Per esempio, consideriamo il seguente estratto dal primo capitolo di Alice’s
Adventure in Wonderland di Lewis Carroll [Carroll, 1866]:

<<Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do:
once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in
it, “and what is the use of a book,” thought Alice, “without pictures or conversations?” So she was considering
in her own mind, (as well as she could, for the hot day made her feel very sleepy and stupid,) whether the
pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when
suddenly a white rabbit with pink eyes ran close by her.>>

Seppur sia totalmente implicito per chi legge, ogni parte del testo è in realtà organizzato in modo
molto preciso. Per esempio, specifichi blocchi testuali del testo citato sono descritti in capoversi, che
sono a loro volta organizzati in capitoli, che a loro volta compongono il libro. Inoltre, ogni
capoverso può contenere altre strutture, come un dialogo di un certo personaggio. Tutte queste
strutture sono mostrate in Figura 12, dove la struttura principale, chiamata book, è descritta da una
sorta di scatola che contiene diverse scatole più piccole chiamate chapter, una per ogni capitolo.
Ognuna di queste, a sua volta, contiene altre scatole chiamate paragraph, una per ogni capoverso, e
così via. Questo approccio di racchiudere una parte del testo in una scatola etichettata definisce
esattamente l’attività di marcatura, che è possibile definire esplicitamente mediante l’utilizzo di
opportuni linguaggi di markup – alcuni dei quali verranno discussi in seguito. Anche se potrebbe
non sembrare estremamente chiaro ad una prima scorsa, l’organizzazione a scatole appena
presentata descrive una precisa gerarchia tra loro, dove la più grande (ovvero book) ne contiene di
più piccole (ovvero i vari chapter), queste a loro volta ne contengono di più piccole ancora (i
paragraph), e così via. Quando siamo in presenza di queste organizzazioni gerarchiche che non si
sovrappongono, possiamo usare una specifica struttura dati per descriverle in modo astratto: un
albero – come mostrato in Figura 13. Un albero è una struttura dati composta da un insieme di nodi
collegati tra loro da una relazione gerarchica genitore-figlio. Come mostrato in Figura 14, i nodi di
questa struttura dati vengono disposti dall’alto verso il basso, contrariamente all’organizzazione
dell’albero che siamo abituati ad osservare in natura.

Il nodo di origine, ovvero quello più in alto, è chiamato nodo radice (root node). Invece, i nodi che
terminano l’albero, chiamati nodi foglia (leaf nodes), sono posizionati in basso nell’albero, rispetto al
nodo radice. Prendendo in considerazione uno specifico nodo dell’albero, come quello evidenziato in
giallo in Figura 14, possiamo definire tutti i restanti nodi come segue:

 il nodo genitore (parent node) è quello direttamente connesso quando ci si muove verso il
nodo radice;
 un nodo figlio (child node) è uno di quelli direttamente connessi quando ci si muove lontano
dal nodo radice;
 un nodo fratello (sibling node) è uno di quelli che condivide lo stesso nodo genitore;
 un nodo antenato (ancestor node) è uno di quelli raggiungibili seguendo ripetutamente le
relazioni genitore-figlio andando verso il nodo radice;
 un nodo discendente (descendant node) è uno di quelli raggiungibili seguendo
ripetutamente le relazioni genitore-figlio spostandosi lontano dal nodo radice.

Anche se abbiamo usato un esempio di contenimento a “scatole”, le strutture ad albero possono


rappresentare informazioni molto diverse, per esempio la prima frase dell’incipit di Alice in
Wonderland può essere analizzato sintatticamente come in Figura 15, ma le relazioni non sono di
contenimento, come avviene anche nel caso degli “alberi delle decisioni” (immaginate le istruzioni
per usare un bancomat) o nel caso degli organigrammi gerarchici di un’azienda.

GRAFO → L’origine della struttura a grafo deriva da un piccolo gioco, conosciuto ai tempi come un
vero e proprio problema matematico, che riguarda sette ponti di una specifica città, Königsberg,
illustrata in Figura 16. Il problema può essere enunciato come segue: è possibile fare una passeggiata
in città attraversando ogni ponte una ed una sola volta? Molte persone hanno provato a proporre
una soluzione a questo enigma, dimostrato (negativamente) da Eulero nel 1736 mediante una
dimostrazione matematica formale [Euler, 1741].

Per questa dimostrazione, Eulero ha descritto, in modo astratto, le quattro terre che formavano
Königsberg come nodi di una rete collegati da archi, dove ogni arco tra due nodi rappresentava un
ponte tra due lembi di terra. Un’illustrazione di questa astrazione è mostrata in Figura 17. Usando
questa rappresentazione astratta, poi conosciuta col nome di grafo, è stato in grado di dimostrare
che non esiste alcuna soluzione al problema dei sette ponti di Königsberg.

La soluzione del problema era interamente basata sulla seguente intuizione. L’idea era che ogni
nodo, ad eccetto del nodo di partenza e quello di arrivo, dovrebbero avere un numero pari di archi
per essere raggiunti e poi abbandonati. Questa è un’implicazione pratica, derivata dagli spostamenti
che una persona deve fare per arrivare in un lembo di terra e poi passare oltre. Infatti, ogni volta che
si entra in un nodo bisogna percorrere un arco, e un altro arco è comunque necessario per uscire da
quel nodo. Quindi, per poter essere attraversati, ogni nodo che non sia quello di partenza o quello di
arrivo deve avere necessariamente un numero pari di archi, in modo da essere transitato una o più
volte. Tuttavia, tutti i nodi in Figura 17 hanno un numero dispari di archi, il che contraddice il
precedente requisito. Di conseguenza, con questa configurazione, il problema dei sette ponti non può
essere risolto. I grafi sono una delle principali strutture dati in informatica e, in generale, del
pensiero computazionale. Sono usati per descrivere, in termini astratti, molte situazioni del mondo
reale come tragitti tra città, relazioni tra persone nei social network, l’organizzazione dei
collegamenti ipertestuali tra pagine Web [Albert and Barabasi, 2002] e le relazioni concettuali nelle
basi di dati o nei knowledge graph usati per esempio da Google (Figura 18), Amazon e Facebook per
i loro servizi. Questa struttura dati è interamente derivata dall’omonimo strumento matematico
inventato da Eulero, e possono essere distinti in due macro-categorie: grafi non orientati (come
quello usato da Eulero per risolvere il problema dei sette ponti di Königsberg, mostrato in Figura
17), dove un arco può essere attraversato in una direzione o nell’altra a piacere, ed i grafi orientati,
dove ogni arco specifica esplicitamente la direzione di percorrenza, come mostrato in Figura 19. Un
esempio di grafo orientato, in cui gli archi specificano la direzione di percorrenza attraverso una
freccia – ad esempio, tra il nodo “1” e il nodo “2” ci sono due archi che possono essere percorsi solo
dal primo nodo al secondo, ma non viceversa.

CAPITOLO DUE

1. Usi possibili della Macchina Analitica

Ada Lovelace (Figura 1) era la figlia del poeta Lord Byron. Matematica di formazione, è diventata
famosa per il suo lavoro sulla Macchina Analitica di Babbage. La madre, Anne Isabella Milbanke, In
contrasto con le abitudini del padre, che mal sopportava il suo interesse per la cultura scientifica,
aveva invece da sempre supportato l’interesse che Ada aveva nella logica e nella matematica. Uno
degli obiettivi della madre, infatti, era quello di evitare che la figlia incorresse nella stessa
sregolatezza emozionale ed esistenziale che aveva caratterizzato la vita del padre. Tuttavia, in qualche
modo la creatività insita nella famiglia venne poi manifestata in modi assolutamente imprevedibili.
Nel 1833, Ada partecipò ad una festa organizzata da Charles Babbage per presentare la Macchina
Differenziale. Fu talmente colpita dall’invenzione di Babbage che iniziò una corrispondenza
epistolare con lui che durò 27 anni [Morais, 2013]. Ada fu la traduttrice in inglese del primissimo
articolo sulla Macchina Analitica, scritto da Luigi Federico Menabrea, e che lei stessa arricchì con un
grande numero di annotazioni personali e riflessioni. Tra queste, c’era anche una descrizione di
come usare la Macchina Analitica per calcolare i numeri di Bernoulli [Menabrea, 1842].
Tecnicamente, questo fu il primo programma – nonché il primo algoritmo – per un computer
digitale mai scritto, e fu creato da Ada senza avere neppure a disposizione la macchina reale, visto
che la Macchina Analitica era soltanto una macchina teorica che Babbage non costruì mai.

Tuttavia, la sua visione sui possibili usi della Macchina Analitica andava anche oltre [Morais, 2013]:
[Traduzione libera in italiano: “Il meccanismo può anche essere messo al lavoro indipendentemente dalla
presenza effettiva di oggetti su cui operare (benché ovviamente in questo caso non arrivi necessariamente a
un risultato). Inoltre, potrebbe operare su altre cose oltre ai numeri, se si trovassero oggetti le cui relazioni
fondamentali possano essere espresse da quelle della scienza astratta delle operazioni, e che dovrebbero essere
adattate all’azione della notazione delle operazioni e ai meccanismi della macchina. Supponendo, per esempio,
che le relazioni fondamentali tra i suoni di varia altezza, nella scienza dell’armonia e della composizione
musicale, siano suscettibili di tali espressioni e adattamenti, la macchina potrebbe comporre scientificamente
brani di musica elaborati di qualunque durata o grado di complessità.”]

Quel “science of operations” indicato nel testo è un riferimento ad uno specifico campo scientifico
che fu chiaramente identificato soltanto molti anni dopo. In pratica, Ada Lovelace stava parlando
dell’Informatica ben cent’anni prima della sua introduzione formale. Per il suo lavoro nel campo,
Ada Lovelace è spesso riconosciuta come il primo programmatore della storia.

2. Cos’è un algoritmo?

Gli algoritmi accompagnano sistematicamente le nostre attività della vita quotidiana. Per esempio, in
Figura 2 sono mostrati due esempi di procedure passo passo che dobbiamo seguire, rispettivamente,
per preparare salatini e per assemblare una specifica lampada. Mentre l’obiettivo dei due esempi è
estremamente diverso, in quanto nel primo è una ricetta e nel secondo è un insieme di istruzioni per
assemblare un utensile, essi sono descritti nei termini della stessa nozione astratta: istruzione per
produrre qualcosa partendo da un qualche materiale iniziale a disposizione – che, di fatto, rispecchia
pienamente la definizione di algoritmo. La parola algoritmo è una combinazione della parola latina
algorismus (che, a sua volta, è la latinizzazione del nome Al-Khwarizmi, che era un grande
matematico persiano dell’ottavo secolo) e della parola greca arithmos, che significa numero. A livello
generale, possiamo definire un algoritmo come l’astrazione di una procedura passo passo che prende
qualcosa come input e produce un certo output [Wing, 2008]. Ogni algoritmo è scritto in un
linguaggio specifico in modo che le istruzioni che definisce possano essere comunicate e comprese
da un computer (sia esso umano o macchina) in modo da ottenere qualcosa come conseguenza
dell’elaborazione di qualche materiale di input. Un programmatore è una persona che crea algoritmi
e li specifica in programmi usando uno specifico linguaggio comprensibile dal computer – ove, in
questo caso, il termine computer si riferisce ai computer elettronici. Tuttavia, se ci si astrae dalla
nozione di programma, un programmatore è chiunque sia in grado di creare algoritmi che possono
essere interpretati da un qualunque computer (sia esso umano o macchina).

3. Diagrammi di flusso

Non esiste un linguaggio standard per descrivere un algoritmo in modo che possa essere
immediatamente comprensibile da un qualunque computer. Tuttavia, spesso gli informatici si basano
su uno pseudocodice quando vogliono descrivere un particolare algoritmo. Uno pseudocodice è un
linguaggio informale che può essere facilmente interpretato da un qualunque computer, anche se è
solitamente usato per comunicare i passi principali di un algoritmo ad un umano. Mentre un
algoritmo descritto mediante l’uso di pseudocodice non è eseguibile da un computer elettronico, i
suoi costrutti sono strettamente connessi con quelli tipicamente definiti nei linguaggi di
programmazione. In particolare, ogni algoritmo può essere espresso in pseudocodice e, in principio,
questo può essere a sua volta tradotto, abbastanza facilmente, in diversi linguaggi di
programmazione. La vera differenza è che, di solito, alcuni passaggi dello pseudocodice possono
essere semplificati usando delle espressioni in linguaggio naturale, mentre, in un linguaggio di
programmazione, bisogna necessariamente definire in modo chiaro tutti i passaggi. In questo
capitolo, useremo una particolare alternativa grafica al comune pseudocodice che è facilmente
comprensibile dagli umani: i diagrammi di flusso. Un diagramma di flusso è uno specifico tipo di
diagramma che può essere usato per scrivere algoritmi, e che si basa su un limitato insieme di
oggetti grafici.
4. Il nostro primo algoritmo

In questo capitolo svilupperemo il nostro primo algoritmo, che può essere descritto informalmente
come segue: prendere in input tre stringhe, ovvero due parole e un riferimento bibliografico di un
articolo pubblicato, e restituire 2 se entrambe le parole sono contenute nel riferimento bibliografico,
1 se solo una delle parole è contenuta nel riferimento bibliografico, o 0 altrimenti. Mediante i
diagrammi di flusso, un qualunque algoritmo è definito usando due oggetti terminali, che
identificano l’inizio e la fine dell’algoritmo. Il terminale di inizio ha una freccia che parte da esso e
va verso l’istruzione successiva (la prima dell’algoritmo), mentre il terminale di fine può essere
raggiunto da differenti punti dell’algoritmo, e quindi è collegato da almeno una freccia.

La prima versione incompleta dell’algoritmo, mostrata di seguito, semplifica un poco le istruzioni in


linguaggio naturale precedentemente introdotte, in modo da mostrare come possiamo usare alcuni
iniziale oggetti per creare un algoritmo, senza aggiungere ulteriore complessità, almeno per il
momento. In particolare, la versione semplificata prende in input solo due stringhe, una parola e un
riferimento bibliografico, e restituisce 1 se la parola è contenuta nel riferimento bibliografico, 0
altrimenti. Questa versione parziale è mostrata nel diagramma di flusso in Figura 3.

Questa versione parziale usa già molti degli oggetti grafici propri ai diagrammi di flusso. In
particolare, oltre ai terminali di inizio e fine, abbiamo usato tre oggetti di input / output per
acquisire i valori specificati come input e per restituire 0 o 1 dipendentemente da questo input. La
decisione su quale output restituire è stata codificata grazie all’oggetto decisionale dei diagrammi di
flusso, in cui l’input è analizzato e, a seconda della situazione, uno specifico ramo del flusso
dell’algoritmo viene percorso.

L’algoritmo completo

Mentre nella sezione precedente è stata introdotta una prima implementazione della versione
parziale dell’algoritmo, l’implementazione dell’algoritmo completo attraverso lo sviluppo di un
diagramma di flusso è mostrata in Figura 4. In questo caso, sono stati utilizzati tutti gli oggetti
grafici introdotti in Tabella 1. Tuttavia, è importante sottolineare come il diagramma di flusso
presentato è soltanto un possibile modo per implementare l’algoritmo originale. Infatti, è possibile
creare anche un diagramma di flusso diverso che, però, risolve il problema descritto dall’algoritmo in
linguaggio naturale correttamente. Nel diagramma in Figura 4, viene utilizzato il primo oggetto di
processo in cui viene inizializzato a 0, associandolo implicitamente a una variabile (ovvero, “result
value” in figura), il risultato che verrà restituito alla fine dell’esecuzione dell’algoritmo. Questo
risultato è quello che l’algoritmo deve ritornare se entrambe le parole in input non sono contenute
nel riferimento bibliografico specificato. Questo oggetto di processo è seguito da due oggetti
decisionali messi in sequenza, che controllano le due condizioni – ovvero se la prima parola è
contenuta nel riferimento bibliografico, e se la seconda parola è contenuta nello stesso riferimento –
e, nel caso queste siano vere, eseguono un incremento di 1 al risultato finale da restituire, mediante
l’uso di altri oggetti di processo. Alla fine, qualunque sia il valore che è stato associato al risultato
finale viene restituito da un unico oggetto di output, che conclude l’esecuzione dell’algoritmo.

5. Ci sono limiti alla computazione?

Una delle domande tradizionali che le persone, che si avvicinano al pensiero computazionale e agli
algoritmo, di solito si pongono è: possiamo usare gli algoritmi per computare qualsiasi cosa
vogliamo? In altre parole: esiste un limite a quello che possiamo computare? O ancora: è possibile
definire un problema computazionale – ovvero un problema che può essere risolto algoritmicamente
da un computer – che non può essere risolto da nessun algoritmo?

Nel caso dell’informatica, ma anche di tutte le scienze matematiche, uno degli approcci più usati per
dimostrare che qualcosa non esiste è quello di costruire una situazione in apparenza plausibile che,
poi, si rivela paradossale e auto-contraddittoria – in cui, per esempio, l’esistenza di un algoritmo
contraddice se stessa. Questo approccio dimostrativo porta il nome di reductio ad absurdum
(dimostrazione per assurdo). L’argomentazione che ne sta alla base è quella di stabilire che una
situazione è contraddittoria cercando di derivare un’assurdità dalla sua negazione, in modo da
dimostrare che una tesi deve essere accettata perché la sua negazione non può essere difesa [Rescher,
2017] e, alla fine, genera un paradosso.
I paradossi sono stati usati molte volte in logica nel passato. Mentre, da un punto di vista, possono
essere considerate storie divertenti da usare per insegnare, da un altro punto di vista sono strumenti
potenti che mostrano i limiti di particolari aspetti formali di una situazione. Per esempio, uno dei
più famosi paradossi in matematica è il paradosso di Russell, scoperto da Bertrand Russel nel 1901.
È stata una delle più grandi scoperte dell’inizio del ventesimo secolo, poiché ha provato che l’allora
teoria degli insiemi proposta da Georg Cantor, e usata come base fondazionale per tutto il lavoro
che Gottlob Frege stava facendo per definire le leggi di base dell’aritmetica, portava ad una
contraddizione. Di conseguenza, il paradosso di Russell invalidava l’intera teoria degli insiemi e il
lavoro fatto da Frege stesso – che era in stampa quando Russell gli comunicò la sua scoperta. Una
variazione del paradosso può essere formulata come segue.

Paradosso del bibliotecario: Nella Biblioteca di Babele, tutte le persone sono di una delle due
seguenti tipologie. La prima tipologia di persone, le indipendenti (no-needed in Figura 5), sono
quelle che, quando devono cercare un libro per loro stesse, lo fanno da sole senza chiedere aiuto a
nessuno. L’altro tipo di persone, ovvero le bisognose (help-needed), sono quelle che non sono in grado
di cercare un libro da sole, e che necessitano dell’aiuto del bibliotecario per trovarlo. Ora, una delle
persone nella biblioteca è il bibliotecario, che cerca un libro per tutte e sole le persone bisognose,
ovvero quelle che non sono in grado di cercare quel libro da sole. Considerando questa situazione, la
domanda è: chi cerca i libri al bibliotecario?

Risoluzione: Se il bibliotecario fosse indipendente, ovvero si cercasse i libri da solo, verrebbe meno
la premessa che lo vuole cercare i libri solo per le persone bisognose – quindi, se fosse indipendente
allora sarebbe bisognoso. Se invece non fosse in grado di cercarsi i libri da solo, e quindi fosse
bisognoso, allora dovrebbe farsi aiutare dal bibliotecario, che però è lui stesso – quindi, se fosse
bisognoso allora sarebbe indipendente. Uno dei più importanti problemi studiati in informatica anni
fa, che faceva parte dei 23 problemi aperti della matematica che David Hilbert propose nel 1900, è
noto col nome di problema della terminazione. Questo problema riguardava il capire se fosse
possibile sviluppare un algoritmo che fosse in grado di rispondere se un altro algoritmo, specificato
come input, terminasse la sua esecuzione o no. L’algoritmo proposto in Figura 4 è un esempio di
uno di quelli che termina, ma è possibile anche sviluppare un algoritmo che non termina mai, ad
esempio come mostrato in quello definito in Figura 6. Avere un modo per scoprire sistematicamente
se un algoritmo termina la sua esecuzione o no sarebbe di importanza cruciale, perché
permetterebbe immediatamente di identificare quegli algoritmi che non lavorano in modo
appropriato.

Uno degli scienziati che di più a lavorato alla risoluzione di questo quesito è stato Alan Mathison
Turing (mostrato in Figura 7). Alan Turing è stato un informatico, nonché padre dell’informatica
teorica e dell’intelligenza artificiale, anche se i suoi lavori hanno interessato diverse discipline tra cui
la matematica (si vedano gli studi per decodificare la macchina Enigma), la logica (con l’introduzione
della macchina di Turing [Turing, 1937]), la filosofia (si veda lo studio sulla relazione tra i calcolatori
elettronici e il concetto di intelligenza [Turing, 1950]) e la biologia (si veda lo studio che identifica i
processi spontanei di creazione di pattern in natura [Turing, 1952]).

Nel 1936, Turing sviluppò la sua macchina proprio per cercare di rispondere al problema della
terminazione di Hilbert. La macchina proposta da Turing era prettamente teorica, nel senso che non
l’aveva costruita fisicamente, anche se recentemente molte persone hanno provato a costruire
prototipi fisici dell’idea di Turing.

La macchina, che è in grado di simulare l’esecuzione di qualunque algoritmo realmente


implementabile, è composta da un nastro di memoria infinito composto da celle. Ogni cella può
contenere un simbolo (o 0 o 1, dove 0 è usato come default per inizializzare le celle di tutto il
nastro) che può essere letto e scritto dalla testina della macchina. Lo stato in cui la macchina si trova
in un certo momento è altresì annotato. Le operazioni che può fare la macchina in un certo stato
sono definite in una tabella (finita) di istruzioni, dove ogni istruzione dice cosa fare (scrivere un
nuovo simbolo, muovere la testina a sinistra o a destra, spostarsi in un nuovo stato) in base allo stato
in cui la macchina si trova e al simbolo presente nella cella sotto la testina. Infine, sono forniti anche
uno stato iniziale e zero o più stati finali, in modo da sapere dove iniziare e finire il processo. La
macchina è stata usata da Turing per mostrare una soluzione per il problema della terminazione. In
questo capitolo presentiamo un’approssimazione alla soluzione che Turing ha fornito, basata
interamente sulla reductio ad absurdum, già usata per risolvere il paradosso del bibliotecario, e sui
diagrammi di flusso come un’astrazione grafica di una specifica macchina di Turing.

Supponiamo sia possibile sviluppare l’algoritmo “termina?”, che prende in input un certo algoritmo e
restituisce “vero” nel caso in cui l’algoritmo specificato come input termina, mentre restituisce
“falso” in caso contrario. Ovviamente, questo è soltanto un algoritmo ipotetico: stiamo supponendo
che possiamo svilupparlo in qualche modo, senza mostrare come farlo davvero.
Ora, usiamo l’algoritmo “termina?” per sviluppare un nuovo algoritmo, introdotto nel diagramma
di flusso in Figura 9. Questo nuovo algoritmo prende in input un algoritmo e restituisce 0 se
l’algoritmo in input non termina, mentre non termina in caso contrario. Notate che siamo in grado
di implementare davvero ogni passo di questo nuovo algoritmo, siccome scoprire se l’algoritmo in
input termina è restituito dal nostro algoritmo (ipotetico) “termina?”, mentre la non terminazione è
un processo chiaramente implementabile, visto che ne abbiamo introdotto un esempio in Figura 6.

Ora la domanda è: cosa succede se cerchiamo di eseguire l’algoritmo descritto in Figura 9 usando se
stesso come input? Abbiamo due situazioni possibili:

 l’algoritmo “termina?” afferma che il nostro algoritmo in Figura 9 termina, e


conseguentemente (per come è definito) non termina l’esecuzione;
 l’algoritmo “termina?” afferma che il nostro algoritmo in Figura 9 non termina, e
conseguentemente (per come è definito) restituisce 0 e termina l’esecuzione.

Quindi, qualunque sia il comportamento del nostro algoritmo in Figura 9, la sua esecuzione
passando se stesso come input genera sempre una contraddizione. L’unica spiegazione possibile,
quindi, è che l’algoritmo ipotetico “termina?” che usiamo per decidere se un algoritmo termina o
meno non può essere sviluppato. Di conseguenza, la risposta al problema della terminazione è che
l’algoritmo che verifica se un altro termina non può esistere.

Questo risultato ha avuto un effetto dirompente sulla percezione delle abilità computazionali che un
computer può avere. In pratica, la macchina di Turing e le relative analisi effettuate su di essa hanno
imposto dei limiti chiarissimi a quello che possiamo calcolare, e hanno permesso di dimostrare che
determinati problemi computazionali interessanti, come quello della terminazione, non possono
essere risolti da nessun approccio algoritmico.
CAPITOLO TRE

1. Che cos’è un linguaggio?

Una linguaggio “naturale” è un linguaggio comune, come l’italiano, che può essere scritto o orale, e
che si è evoluto in maniera naturale all’interno di una comunità. Da come li conosciamo, i linguaggi
naturali hanno il vantaggio (e, contemporaneamente, lo svantaggio) di essere così tanto espressivi che
specifiche istruzioni comunicate attraverso il loro uso possono sembrare ambigue. Consideriamo, per
esempio, la frase “la vecchia porta la sbarra”. Questa frase significa che c’è una vecchia porta che
blocca qualcuno o che c’è una signora anziana che trasporta una sbarra? Tuttavia, spesso, noi
riusciamo a disambiguare il significato di una frase mediante l’uso di convenzioni sociali o
analizzando il contesto in cui l’azione avviene, in modo da restringere il possibile significato di un
pezzo di informazione. Mentre i linguaggi naturali non sono formali per definizione, molti studi in
linguistica cercano di fornirne una formalizzazione mediante l’uso di strumenti matematici
[Bernardi, 2002].
Una delle figure più importanti dietro alla formalizzazione del linguaggio naturale è Noam Chomsky
(mostrato in Figura 1). Chomsky è uno dei più importanti accademici degli ultimi cento anni e uno
dei padri della linguistica moderna, insieme a Ferdinand de Saussure, Lucien Tesnière, Luis
Hjelmslev, Zellig Harris, Charles Fillmore, etc. Le sue ipotesi di ricerca principali sul linguaggio
umano sono: (1) la sua struttura sintattica di base è rappresentabile mediante una teoria matematica
e (2) tale struttura è determinata biologicamente in tutti gli umani – ovvero, è già presente in noi sin
dalla nascita – e, come tale, è una caratteristica unica che si è evoluta nel tempo e che è condivisa
soltanto dagli umani e non da altri animali.

Questa sua visione del linguaggio umano è molto dibattuta, ma ha avuto il merito di fondare su basi
rigorose la ricerca sulle relazioni tra competenza e produzione linguistica, sulle dinamiche e le
interazioni tra capacità “innate” e sviluppo cognitivo e sociale delle abilità linguistiche. Ha anche
permesso di chiarire in parte distinzioni come sintassi vs. semantica, lessico vs. discorso, tra
rappresentazione logica e rappresentazioni mentali, etc.

Tra la sua produzione accademica troviamo la classificazione delle grammatiche formali in una
gerarchia di crescente potere espressivo, che rappresenta uno dei suoi più importanti contributi,
considerando il suo impatto anche al di fuori della linguistica tradizionale – per esempio nel
dominio dell’informatica teorica e nei linguaggi di programmazione, come vedremo in seguito. Una
grammatica formale è uno strumento matematico usato per definire la sintassi di un linguaggio (sia
lingue naturali come l’italiano, sia linguaggi artificiali) attraverso l’uso di un insieme finito di regole
di produzione, che permettono di costruire una qualunque frase valida in quello specifico linguaggio.

Una grammatica formale è composta da un insieme di regole di produzione di forma premessa ::=
espressione (in notazione Backus–Naur, or BNF), dove la premessa e l’espressione possono
contenere uno o più simboli delle seguenti tipologie: simbolo terminale (specificato tra virgolette in
BNF), che identifica tutti i simboli elementari del linguaggio in considerazione (come nomi, verbi,
etc.);

 simbolo terminale (specificato tra virgolette in BNF), che identifica tutti i simboli
elementari del linguaggio in considerazione (come nomi, verbi, etc.);
 simbolo non terminale (specificato tra parentesi angolari in BNF), che identifica tutti i
simboli di una grammatica formale che possono essere sostituiti da una combinazione di
simboli terminali e non terminali.

In linea di principio, l’applicazione di una regola di produzione riguarda la sostituzione dei simboli
nella premessa con quelli specificati nell’espressione finché non si raggiunge una sequenza che
include soltanto simboli terminali. Per esempio, le regole di produzione <frase> ::= "Io" <verbo>,
<verbo> ::= "scrivo" e <verbo> ::= "leggo" permette la creazione di tutte le frasi di due parole che
hanno il pronome di prima persona singolare accompagnato da uno dei verbi possibili (ad esempio
“Io scrivo”). In più, ogni grammatica formale deve specificare un simbolo di inizio, che deve essere
non terminale.

La gerarchia proposta da Chomsky mette a disposizione un modo per descrivere formalmente le


relazioni che possono esistere tra diverse grammatiche in termini delle loro possibili strutture
sintattiche che sono in grado di generare. In pratica, queste tipologie sono caratterizzate dal tipo di
simboli che possono essere usati nella premessa e nell’espressione delle regole di produzione. Queste
tipologie di grammatica sono elencate di seguito, dalla meno espressiva alla più espressiva [vengono
usate le lettere dell’alfabeto greco per indicare una qualsivoglia possibile combinazione di simboli
terminali e non terminali, incluso il simbolo terminale vuoto, solitamente rappresentato con ε]:

 grammatiche regolari – forma delle regole di produzione:

<non-terminale> ::= "terminale>

<non-terminale> ::= "terminale" <non-terminale>

Esempio:

<frase> ::= "Io" <verbo>

<verbo> ::= "scrivo"

<verbo> ::= "leggo"

 grammatiche libere dal contesto – forma delle regole di produzione:

<non-terminale> ::= γ

Esempio:
<frase> ::= <pronome> <frase-verbale>

<pronome> ::= "Io"

<nome> ::= "libro"

<nome> ::= "documento"

<frase-verbale> ::= <verbo>

<frase-verbale> ::= <verbo> "un" <nome>

<verbo> ::= "scrivo"

<verbo> ::= "leggo"

 grammatiche dipendenti dal contesto – forma delle regole di produzione:


α <non-terminale> β ::= α γ β

Esempio:

<frase> ::= <pronome-soggetto> <frase-verbale>

"Io" <pronome-oggetto> <verbo> ::= "Io" <pronome-oggetto> "amo"

"Io" <verbo> <nome> ::= "Io" "leggo" "un" <nome>

<frase-verbale> ::= <verbo> <nome>

<frase-verbale> ::= <pronome-oggetto> <verbo>

<pronome-soggetto> ::= "Io"

<pronome-oggetto> ::= "ti"

<pronome-oggetto> ::= "vi"

<nome> ::= "libro"

<nome> ::= "documento"


 grammatiche ricorsivamente enumerabili – forma delle regole di produzione:
α ::= β (nessuna restrizione)

Esempio:

<frase> ::= <pronome-soggetto> <frase-verbale>

"Io" <pronome-oggetto> <verbo> ::= "Io" "ci" "vedo"

"Io" <verbo> <nome> ::= "Io" "leggo" "un" "libro"

<frase-verbale> ::= <verbo> <nome>

<frase-verbale> ::= <pronome-oggetto> <verbo>

<pronome-soggetto> ::= "Io"

<pronome-oggetto> ::= "mi"

<pronome-oggetto> ::= "ti"

<verbo> ::= "amo"

<verbo> ::= "odio"

2. I linguaggi di programmazione

C’è un particolare aspetto di ogni computer (sia esso umano o macchina) che non è stato ancora
affrontato direttamente, ovvero: quale meccanismo possiamo usare per chiedere a un computer di
eseguire una particolare attività? La modalità per affrontare questo problema è estremamente
connessa con il particolare canale comunicativo che vogliamo adottare. Se consideriamo un
computer umano, possiamo usare un linguaggio naturale (ad esempio l’italiano) o i diagrammi di
flusso per istruirlo sui passi algoritmici che deve compiere. Invece, per comunicare efficacemente con
un computer elettronico si usano i linguaggi di programmazione.

Un linguaggio di programmazione è un linguaggio formale che obbliga l’uso di specifiche regole


sintattiche sviluppate in modo tale da evitare possibili istruzioni ambigue – solitamente restringendo
l’espressività del linguaggio – cosicché tutte le “frasi” componibili possano trasmettere un solo
possibile significato. I linguaggi di programmazione sono solitamente basati su grammatiche libere
dal contesto, in conformità con la classificazione Chomskiana fornita nella sezione precedente – e
possono distinguersi per un basso o elevato livello di astrazione dal linguaggio propriamente in uso
da un elaboratore elettronico per eseguire le operazioni. In particolare, possiamo raggruppare i
linguaggi di programmazione in tre macro-insiemi:

 il linguaggio macchina è un insieme di istruzioni che possono essere eseguite direttamente


dalla CPU (central processing unit, o processore) di un computer elettronico. Per esempio, il
codice seguente è un codice binario eseguibile (composto da una sequenza di 0 e 1) che
definisce una funzione (ovvero, uno strumento che prende qualche input e produce un
qualche output, e che di fatto implementa un algoritmo in un certo linguaggio di
programmazione) per calcolare l’n-esimo numero di Fibonacci:

100010110101010000100100000010001000001111111010000000000111011100000110101
110000000000000000000000000000000000011000011100000111111101000000010011101
110000011010111000000000010000000000000000000000001100001101010011101110110
000000100000000000000000000000010111001000000010000000000000000000000001000
110100000100000110011000001111111010000000110111011000000111100010111101100
110001001110000010100101011101011111100010101101111000011

 i linguaggi di programmazione a basso livello sono linguaggi che forniscono un livello di


astrazione sopra il linguaggio macchina, e che permettono di scrivere programmi in modo
che siano un pochino più intellegibili dagli umani. Il più famoso linguaggio di questo tipo è
l’Assembly. Anche se introduce simboli più comprensibili, di solito una linea di codice in
Assembly rappresenta una specifica istruzione in linguaggio macchina. Per esempio, la
funzione per calcolare l’n-esimo numero di Fibonacci introdotta precedentemente può essere
definita in Assembly come segue:

fib:

mov edx, [esp+8]

cmp edx, 0
ja @f

mov eax, 0

ret

@@:

cmp edx, 2

ja @f

mov eax, 1

ret

@@:

push ebx

mov ebx, 1

mov ecx, 1

@@:

lea eax, [ebx+ecx]

cmp edx, 3

jbe @f

mov ebx, ecx

mov ecx, eax

dec edx

jmp @b
@@:

pop ebx

ret

 i linguaggi di programmazione ad alto livello sono quei linguaggi caratterizzati da un


forte livello di astrazione dal linguaggio macchina. In particolare, possono usare parole
proprie del linguaggio naturale per definire costrutti specifici, così da essere di più facile
comprensione per un umano. A livello generale, più astrazione da un linguaggio di
programmazione a basso livello è fornita, più comprensibile è il linguaggio. Per esempio,
nell’estratto che segue mostriamo come usare il linguaggio di programmazione Python per
implementare la stessa funzione introdotta in precedenza:

def fib( n ):

if n <= 0:

return 0

elif n <= 2:

return 1

else:

a=1

b=1

while True:

c=a+b

if n <= 3:

return c

a=b

b=c
n=n-1

Grace Brewster Murray Hopper (mostrata in Figura 2) è tra i più grandi pionieri dei linguaggi di
programmazione. È stata un’informatica e il primo programmatore dell’Harvard Mark I, che era un
computer elettromeccanico general-purpose usato durante la seconda guerra mondiale e interamente
ispirato alla macchina analitica di Babbage. Grace Hopper era fermamente convinta della necessità di
avere linguaggi di programmazioni che fossero indipendenti dalle macchine su cui erano utilizzati,
che l’ha portata allo sviluppo del COBOL, uno dei primi linguaggi di programmazione ad alto livello
che è tuttora usato per alcune applicazioni industriali.

COBOL (common business-oriented language) è un linguaggio di programmazione sviluppato per


uso industriale che utilizza largamente termini propri alla lingua inglese per descrivere le varie
istruzioni dei programmi. L’idea di adottare, per la prima volta, comandi in lingua inglese ha reso il
linguaggio un po’ più verboso ma anche molto più leggibile e chiaro. Per fare un esempio, nei
linguaggi di programmazione odierni se vogliamo definire la condizione di un costrutto condizionale
(ovvero, l’equivalente di un un oggetto grafico decisionale nei diagrammi di flusso), ad esempio
controllare se il valore assegnato ad una certa variabile x è maggiore di quello assegnato alla
variabile y, si usano i simboli matematici per le uguaglianze, come x > y. In COBOL, la stessa
condizione è esprimibile dall’istruzione x IS GREATER THAN y.

Dopo la Seconda guerra mondiale, sono stati creati diversi linguaggi di programmazione, con
caratteristiche specifiche a seconda dei principi di sviluppo e dell’uso che se ne doveva fare – ad
esempio, dipendentemente dai problemi computazionali per cui venivano usati. Mentre tutti questi
linguaggi, in principio, permettono lo sviluppo di soluzioni per un qualsiasi problema
computazionale, alcuni di questi sono più appropriati per determinati domini rispetto ad altri. Per
esempio, il COBOL, come già anticipato, è stato sviluppato per la creazione di applicazioni
industriali, mentre il FORTRAN è stato sviluppato per gestire al meglio la computazione di dati
scientifici.

Mentre un’analisi accurata di tutti i linguaggi di programmazione è fuori degli obiettivi del corso, in
Figura 3 sono mostrati i principali linguaggi di programmazione dal 1954 al 2017.
3. Linguaggi visuali

In modo da facilitare l’avvicinamento all’uso dei linguaggi di programmazione tradizionali, negli


ultimi anni sono stati sviluppati diversi linguaggi di programmazione visuali che permettono lo
sviluppo di piccoli programmi per risolvere problemi computazionali specifici. Alcuni di questi,
proposti sotto forma di gioco, permettono l’introduzione dei costrutti principali propri dei linguaggi
di programmazione mediante l’utilizzo di oggetti grafici.

Uno delle proposte più interessanti degli ultimi anni è stata avanzata da Google in occasione del
cinquantennale dell’introduzione dei primi linguaggi di programmazione per bambini. Il 4 dicembre
2017, Google ha messo a disposizione un doodle in cui si deve istruire un coniglio in modo che
riesca a mangiare tutte le carote posizionate su un determinato percorso. Le azioni che si possono
far compiere al coniglio riguardano attività di movimento, ad esempio “vai avanti” o “gira a destra”,
e devono essere disposte in una specifica sequenza in modo che il problema computazionale
mangiare tutte le carote presenti sul percorso venga risolto efficacemente. Ad esempio, in Figura 4,
viene mostrata una delle schermate iniziali del gioco proposto. Seppur possa sembrare semplice ad
una prima analisi, il quantitativo di nozioni che il gioco veicola e permette di apprendere è
estremamente allineato con quelle che tipicamente contraddistinguono i linguaggi di
programmazione. Per cui, giocando a questo gioco, si imparano implicitamente e, da un certo punto
di vista, in modo completamente inconsapevole, dei concetti chiave propri alla programmazione e al
pensiero computazionale.

La sequenza di istruzioni specificate per risolvere il problema computazionale proposto di fatto


implementa uno specifico algoritmo. Utilizzando i diagrammi di flusso, introdotti nel capitolo
precedente, è possibile specificare lo stesso insieme di istruzioni usando un linguaggio più formale,
come mostrato in Figura 5.

In modo da semplificare la specificazione di queste lunghe sequenze di azioni, il gioco propone


costrutti addizionali mano a mano che si va avanti nei vari livelli di difficoltà. In particolare, in
Figura 7, viene mostrata come eseguire una sequenza di azioni, per risolvere il problema
computazionale, mediante l’utilizzo di un nuovo oggetto grafico (o costrutto) che permette di
raggruppare sequenze ripetitive di azioni e di eseguirle un numero definito di volte, ovviando al
problema di indicarle tutte per esteso come fatto in Figura 6.
Anche questo algoritmo prettamente grafico può essere rappresentato mediante l’utilizzo di un
diagramma di flusso, come mostrato in Figura 8. In questo caso, la ripetizione è realizzata attraverso
l’utilizzo di un oggetto grafico decisionale che controlla se la sequenza di azioni “fai due passi
avanti” e “gira a destra” è stata eseguita il numero necessario di volte (4) per risolvere il problema
computazionale, e così concludere l’algoritmo.

Il linguaggio di programmazione visuale proposto finora è stato sviluppato specificamente per


risolvere un particolare problema computazionale, far mangiare tutte le carote presenti su un
percorso ad un coniglio. Ovviamente, esistono anche altri linguaggi di programmazione visuale che
sono più general-purpose, ovvero che permettono di sviluppare algoritmi per risolvere problemi
computazionali di vario genere. Uno di questi è Blocky, creato da Google. Questo linguaggio mette a
disposizione diversi costrutti propri dei linguaggi di programmazione tradizionali, ma li propone
sotto forma di blocchetti che si possono incastrare uno sull’altro o uno dentro l’altro per definire le
sequenze di operazioni di un algoritmo.

In Figura 9 è introdotto un algoritmo in Blocky che costruisce la sequenza di azioni descritte in


Figura 4, inserendole dentro una lista nell’ordine in cui vanno fatte eseguire al coniglio. In questo
caso, viene inizializzata una variabile istruzioni con una lista vuota che, nelle operazioni successive,
viene riempita con le operazioni che devono essere eseguite dal coniglio. In modo da mantenere il
giusto ordine delle azioni della sequenza, ogni nuova istruzione viene inserita alla fine della lista.

In modo del tutto simile all’algoritmo introdotto nel diagramma di flusso in Figura 8, che a sua volta
implementa la sequenza di azioni presentate in Figura 7, è possibile utilizzare specifici costrutti di
Blocky per permettere ripetizioni sistematiche di un gruppo di istruzioni. Per esempio, in Figura 10
viene mostrato l’utilizzo del costrutto repeat while <condition> do, che permette l’esecuzione di una
sequenza di operazioni in esso contenute fintanto che la condizione del costrutto è vera.

Oltre alla possibilità di creare graficamente un algoritmo, Blocky mette anche a disposizione una
sorta di traduttore che permette di descrivere i vari passi dell’algoritmo implementato in uno tra
cinque diversi linguaggi di programmazione. Per esempio, il Listato 1 mostra la traduzione in
Python delle istruzioni presentate in Figura 10.
istruzioni = list()

iterazione = 0

while iterazione < 4:

iterazione = iterazione + 1

istruzioni.append("avanti")

istruzioni.append("avanti")

istruzioni.append("gira a destra")

Python è un linguaggio di programmazione ad alto livello general-purpose, ed è correntemente uno


dei linguaggi più usati per il Web e per attività di analisi automatiche di dati e del linguaggio
naturale. Tra i vari vantaggi, Python è uno dei linguaggi più semplici con cui iniziare a studiare
come programmare e creare applicazioni. Seppur in questo corso non verranno approfonditi i
principi della programmazione in Python, sul Web ci sono a disposizione tantissime risorse gratuite
(principalmente in inglese) che permettono uno studio approfondito del linguaggio, in particolare:

 Il libro introduttivo Dive into Python 3 [Pilgrim, 2009];


 La documentazione ufficiale del linguaggio;
 Una piattaforma online per giocare con Python 3 senza installare alcun software sul proprio
computer;
 Un corso interattivo per imparare Python da zero;
 Un altro libro interamente dedicato alla risoluzione di problemi e algoritmi sviluppati in
Python [Miller and Ranum, 2011];
 Un libro digitale che contiene un’introduzione a Python per le Scienze Umane.
CAPITOLO QUATTRO

1. Introduzione

In questo capitolo e nei successivi affronteremo tutte le tecnologie alla base di Internet e del World
Wide Web. Tuttavia, invece di affrontare questi temi in modo tradizionale, ovvero partendo dalla
descrizione architetturale di Internet per poi presentare il Web, abbiamo voluto introdurre questi
argomenti seguendo la traccia fornita da Tim-Berners Lee (l’inventore del Web) in un noto
documento esplicativo a disposizione sul suo sito Web.

In particolare, questo capitolo ed i successivi quattro, nella loro interezza, permettono di rispondere
ad una semplice, seppur significativa, domanda:

Cosa succede quando si clicca su un collegamento ipertestuale (o link) di una pagina Web?

Per rispondere pienamente a questa domanda, è necessario avere delle conoscenze di base relative sia
sul come l’informazione viene trasmessa digitalmente, sia sulle componenti che compongono
Internet e il Web. In particolare, la narrazione qui presentata segue sistematicamente i vari passi che
vengono eseguiti da tutti gli attori coinvolti non appena viene eseguito un “click” su un collegamento
ipertestuale di una pagina web.

2. La nascita degli ipertesti

Tuttavia, prima di concentrarci sulla descrizione della sequenza di azioni che viene scatenata a
seguito di un “click”, è bene chiarire cosa sia un ipertesto e, conseguentemente, cosa sia un
collegamento ipertestuale.

Un ipertesto è un corpo di materiale scritto interconnesso in modo così tanto complesso che non è
conveniente presentare su carta [Nelson, 1965]. Seppur, al giorno d’oggi, siamo abituati ad utilizzare
questo tipo di strumento, essendo il Web di fatto un gigantesco ipertesto, una settantina di anni fa
quest’idea era praticamente non convenzionale e non realizzabile.

L’idea embrionale dell’ipertesto sembra sia stata affrontata ben prima della sua proposta formale,
essendovi diversi riferimenti già in letteratura a possibili costruzioni prettamente ipertestuali – ad
esempio, si veda il racconto “Il giardino dei sentieri che si biforcano” di Jorge Luis Borges. Tuttavia,
l’idea di una esemplificazione tecnologica si ha soltanto nel 1945, a seguito delle riflessioni
contenute nel famoso articolo “As We May Think” di Vannevar Bush [Bush, 1945].

Vannevar Bush, mostrato in Figura 1, è stato un famoso ingegnere ed inventore statunitense, e fu a


capo dell’Agenzia Federale per la Ricerca e lo Sviluppo durante la seconda guerra mondiale. Nel suo
famoso articolo pubblicato in The Atlantic Monthly, Bush affronta il problema della crescita
esponenziale delle pubblicazioni, a carattere accademico e non, conseguenza delle nuove scoperte
scientifiche, che necessitano di essere divulgate, e ai meccanismi di produzione sempre più
industrializzati. Facendo continui riferimenti alla divulgazione accademica come principale dominio
di discussione, Bush metteva in evidenza come i meccanismi, che all’epoca venivano ancora usati per
trasmettere e/o revisionare i risultati di una ricerca, erano molto vecchi e per niente adatti a
facilitarne la divulgazione. Se non si fosse intervenuti per tempo, ci sarebbe stato il rischio di
perdere importanti pietre miliari della ricerca all’interno di una massa sempre più corposa di
materiale irrilevante. In aggiunta, quel che emergeva dalla sua trattazione era che l’attuale tecnologia,
o almeno quella in fase di sperimentazione, poteva già dare largo supporto alla creazione di
piattaforme elettro-meccaniche che semplificassero notevolmente il salvataggio, la ricerca, e la
consultazione di materiale rilevante.

Mentre il problema dello spazio su cui salvare tutte le informazioni poteva essere affrontato
mediante l’uso di tecnologie di frontiera, come i microfilm (grazie ai quali, secondo Bush, era
possibile salvare un’intera copia dell’Enciclopedia Britannica all’interno di un supporto grosso
quanto una scatola di fiammiferi), uno dei problemi, se non il problema maggiore, era avere un
meccanismo di facile accesso alle informazioni e, in particolare, ad altri dati ad esse correlati. Infatti,
secondo Bush, uno dei problemi principali alla consultazione di un qualsiasi materiale, era la sua
organizzazione sequenziale e l’artificialità del meccanismo di indicizzazione dei contenuti.

Quando una qualsivoglia informazione viene raccolta in un dispositivo di memorizzazione, questa


informazione viene in qualche modo indicizzata alfabeticamente (si pensi, ad esempio, ad un indice
dei nomi alla fine di un manuale) o numericamente (si pensi, ad esempio, all’indice dei capitoli e
sezioni di un libro). Inoltre, un’informazione può essere contenuta soltanto in un posto specifico, a
meno che non venga in qualche modo duplicata. Per recuperare una certa informazione a partire
dagli indici a disposizione, una persona deve seguire determinate regole in modo da identificare la
posizione in cui tale informazione si trova (si pensi, ad esempio, ai libri in una biblioteca). Questo
processo si ripete nuovamente, e sistematicamente, ogni qual volta si debba, o si voglia, cercare una
nuova informazione.

Come anticipato, Bush ha definito questo meccanismo di indicizzazione prettamente artificiale


perché non è il modo in cui la mente umana solitamente opera. Infatti, partendo da una specifica
informazione, la mente si sposta istantaneamente alla successiva mediante un processo associativo,
ove un’informazione in qualche modo ne richiama un’altra, conformemente a una complicata rete di
pensieri veicolata dalle cellule che compongono il nostro cervello. L’idea di Bush è che questa
selezione di informazioni mediante meccanismi prettamente associativi può essere meccanizzata e
conseguentemente esplicitata in una macchina. Ovviamente, seppur Bush pensasse che non fosse
possibile raggiungere la stessa velocità e flessibilità della mente umana (anche se le attuali ricerche
sui big data sembrano oggi suggerire il contrario), sarebbe quantomeno stato possibile battere la
mente umana relativamente alla permanenza e al recupero nel tempo delle informazioni se queste
fossero state memorizzate su dispositivi appropriati, ad esempio i microfilm.
Nel suo articolo, Bush presentava, in linea totalmente teorica, una macchina chiamata memex
(mostrata in Figura 2) che avrebbe permesso di salvare tutti i libri, record di dati, e comunicazioni di
vario genere su dispositivi appropriati, così da accedervi in modo completamente meccanico,
flessibile, e veloce. In particolare, il memex era composto da una scrivania con due schermi al centro
per facilitare la lettura dei documenti memorizzati, accompagnati da una tastiera, un insieme di
bottoni e leve (a destra), e, sulla sinistra, una plancia su cui posizionare qualunque documento così
da essere fotografato e memorizzato nei microfilm utilizzati dalla macchina.

Tutte le informazioni memorizzate (ad esempio, un libro) potevano, ovviamente, essere recuperate
mediante il classico meccanismo a indici descritto sopra, e consultate attraverso l’uso delle leve
messe a disposizione dalla macchina, che permettevano di sfogliare sequenzialmente documenti.
Inoltre, la macchina metteva a disposizione anche un meccanismo per annotare i documenti
visualizzati, così da aggiungere note a margine, commenti, e quant’altro.

In aggiunta a questo, il più grande vantaggio che il memex avrebbe introdotto era la possibilità di
creare percorsi tra le informazioni, ovvero dei collegamenti associativi tra le varie porzioni di
informazioni memorizzate nel memex. In particolare, un utente avrebbe potuto creare uno specifico
percorso associativo e memorizzarlo nella macchina con un nome, così da poterlo richiamare ed
estendere in futuro. In questo caso, il memex avrebbe permesso non solo di spostarsi
sequenzialmente sul documento visualizzato, ma anche trasversalmente su diversi documenti
seguendo tutti i percorsi associativi che un utente avrebbe potuto creare. Infine, avrebbe anche
potuto salvare il percorso in uno specifico microfilm così da poterlo condividere con un collega, che
avrebbe potuto visualizzarlo nel suo memex.

Le idee contenute nell’articolo di Vannevar Bush erano visionarie e d’avanguardia per l’epoca, e
alcune di queste rappresentano ancora dei possibili desiderata dello sviluppo degli ipertesti e, più in
generale, del Web. Molti ingegneri e inventori sono stati ispirati da quest’articolo nel corso degli
anni successivi. Tra questi è bene ricordare Theodor (Ted) Holm Nelson (mostrato in Figura 3), colui
che ha coniato la parola ipertesto.

Nel 1960, Ted Nelson aveva iniziato a lavorare ad un nuovo progetto, chiamato Xanadu – un
esplicito riferimento alla città capitale del regno di Kublai Khan. L’obiettivo del progetto era quello
di creare una rete di computer che potesse essere depositaria dell’intera conoscenza umana e che
potesse essere estesa mediante dei collegamenti ipertestuali bidirezionali che permettessero di
collegare tra loro idee contenute in diversi documenti (come mostrato in Figura 4), riprendendo il
concetto di percorsi associativi postulato da Vannevar Bush [Nelson, 1965]. Inoltre, in questo lavoro,
Nelson ha introdotto una serie di concetti chiave – ad esempio: trasclusione e intertwingularity, che
non ha corrispettivi in italiano, ma richiama esplicitamente il concetto di processo associativo della
conoscenza tipico degli esseri umani enunciato da Vannevar Bush – che sono stati fondamenti
pregnanti di tutti gli ipertesti sviluppati successivamente.

Nello stesso periodo in cui Nelson divulgava le sue idee e il suo progetto, un altro scienziato,
Douglas Engelbart (mostrato in Figura 5), aveva iniziato l’implementazione di un sistema
rivoluzionario per l’epoca, che di fatto permetteva per la prima volta la creazione di ipertesti su un
computer. Questo sistema, chiamato oN-Line System (NLS) ebbe un impatto dirompente sullo stato
corrente e futuro delle tecnologie informatiche che erano a disposizione all’epoca. Basti pensare le
innovazioni software (le applicazioni e i programmi a disposizione di un computer) e hardware
(ovvero la parte fisica e tangibile di un computer, come il processore, il disco fisso, la memoria RAM,
etc.) che lo sviluppo dell’NLS aveva portato: il concetto di finestre come meccanismo visuale per
l’organizzazione di contenuti e applicazioni di un sistema operativo, l’ipertesto, un sistema di
videoconferenza, il mouse (mostrato in Figura 6), un sistema di videoscrittura (o word processor in
inglese, tipo Microsoft Word), un meccanismo (chiamato dynamic linking) per richiedere solo
quando necessario opportune librerie e applicazioni a disposizione sul computer, meccanismi per il
controllo delle versioni dei documenti, e un editor collaborativo in tempo reale (tipo Google Docs).
Tutte queste cose non esistevano prima di NLS, e sono da lì in avanti state il fondamento per lo
sviluppo dei moderni computer e sistemi operativi.

L’intero sistema, implementato realmente da Engelbart e soci, era stato per la prima volta mostrato
in una famosa sessione dimostrativa nella Fall Joint Computer Conference del 1968, organizzata
dalla Association for Computing Machinery e dall’Institute of Electrical and Electronics Engineers
(le due principali associazioni internazionali accademiche di informatica), suscitando commenti
entusiastici da parte di tutta la comunità, tanto da aver poi etichettato quella sessione come la madre
di tutti i demo (The Mother Of All Demos, in inglese).

3. L'invenzione del World Wide Web


Sono dovuti passare diversi anni dalla madre di tutti i demo, poco più di trenta, prima di poter
assistere ad un’implementazione su scala mondiale di un ipertesto, il World Wide Web o, più
semplicemente, il Web [Berners-Lee et al., 1994]. L’idea venne ad un giovane scienziato del CERN di
Ginevra nel 1989, Tim Berners-Lee (mostrato in Figura 7). Il progetto, inizialmente respinto da
parte dei suoi superiori con il famoso commento “vago ma eccitante”, ritrovato qualche anno più
tardi da Berners-Lee stesso su una copia a disposizione del suo capo di allora, venne poi accettato
come progetto collaterale per testare le potenzialità di un nuovo computer (il NeXT, realizzato
dall’omonima azienda di proprietà di Steve Jobs negli anni di separazione da Apple) che era stato
appena comprato dal CERN.

Nell’idea originale di Berners-Lee, il Web avrebbe dovuto essere un ipertesto che potesse descrivere
una varietà di risorse eterogenee, tra cui documenti, persone, gruppi di persone, organizzazioni,
concetti astratti, e quant’altro. Inoltre, sarebbe dovuto anche essere possibile collegare tra loro queste
risorse mediante l’uso di collegamenti ipertestuali etichettati, in modo da poter specificare la
semantica del collegamento come parte esplicita del link. Questa visione è riassunta nel diagramma
in Figura 8, estratto da una copia del documento originale che Berners-Lee aveva scritto per
convincere il CERN a finanziare il progetto. Seppur ispirato alle idee di Ted Nelson, l’infrastruttura
ideata da Berners-Lee proponeva alcune semplificazioni, prima tra tutte il fatto che tutti i
collegamenti ipertestuali del Web dovessero essere percorribili in un’unica direzione, contrariamente
all’organizzazione postulata originariamente da Ted Nelson, ove tutti i collegamenti ipertestuali Il
primo prototipo del Web realizzato da Tim Berners-Lee, tuttavia, aveva ulteriormente semplificato lo
scenario, riducendo ad una soltanto, il documento o pagina Web, la tipologia di risorse descrivibili e
permettendo una sola tipologia di collegamento ipertestuale, ovvero il semplice riferimento (il
documento A fa riferimento al documento B). In modo da realizzare questa visione, Berners-Lee
sviluppò una serie di tecnologie, basate su altre già esistenti e messe a disposizione negli anni
precedenti, che permettessero agli utenti la creazione di documenti ipertestuali (l’Hypertext Markup
Language, o HTML), di mettere a disposizione i suddetti documenti ipertestuali sul Web (attraverso
la creazione di server web), di poterli richiedere mediante l’utilizzo di un opportuno identificativo
(chiamato Uniform Resource Locator, o URL) e di uno specifico protocollo di comunicazione
(l’Hypertext Transfer Protocol, o HTTP), e infine di visualizzarli su un computer (attraverso l’uso di
un browser). Tutte queste tecnologie sono tutt’ora in uso e rappresentano le fondamenta del Web,
seppur questo si sia evoluto molto negli ultimi anni e si sia sempre più conformato all’idea iniziale
che aveva Tim Berners-Lee, anticipata in Figura 8, che prende il nome di Web Semantico [Berners-
Lee et al., 2001].

Tutte queste tecnologie verranno puntualmente analizzate nel corso di questo capitolo e dei
successivi, insieme a tutte le altre tecnologie su cui esse si fondano e che rappresentano i capisaldi di
Internet. La comprensione di tutte queste tecnologie è necessaria per rispondere alla domanda da cui
siamo partiti, ovvero: cosa succede quando si clicca su un collegamento ipertestuale (o link) di una
pagina web?erano pensati per essere percorribili in una direzione o nell’altra indistintamente.

4. Uniform Resource Locator (URL)

Quando si legge una pagina web, il computer non mostra tutto quello che conosce sui link
ipertestuali presenti in quella pagina. Dentro quel frammento di testo sottolineato e solitamente
colorato in blu (o in viola, nel caso sia stato già visitato) che può essere cliccato, c’è nascosto un
oggetto invisibile che inizia per “http://” (o, a volte, “https://”, dipendentemente dai casi).
Quell’oggetto è un Uniform Resource Locator, o URL. Un URL rappresenta, di fatto, una sorta di
nome (o più propriamente, un indirizzo) della pagina web a cui il link punta e permette di accedere
cliccandoci sopra. Per esempio, la pagina web su Wikipedia che parla di URL presentata nel link
precedente è identificata dall’URL http://it.wikipedia.org/wiki/Uniform_Resource_Locator.

In generale, la forma di un qualunque URL presente nel Web è conforme con la seguente struttura
(ove gli elementi tra parentesi quadre sono opzionali):

<schema>://<host>[:<porta>][/<percorso>][?<interrogazione>][#<frammento>]

Le varie parti sono descritte come segue – e verranno approfondite sistematicamente nei prossimi
capitoli:

 schema – il protocollo di comunicazione usato (tipicamente “http” o “https”, che verranno


presentati nel dettaglio nei capitoli successivi) per richiedere informazioni sulla risorsa
indicata dall’URL. Se si pensasse, metaforicamente, ad un URL come un modo per descrivere
la locazione di uno specifico oggetto all’interno di una casa, il protocollo identificherebbe il
mezzo di trasporto usato (ad esempio una macchina di proprietà, un taxi, un autobus) per
raggiungere la casa che contiene il suddetto oggetto dal luogo in cui ci si trova.
 host – il nome o una sequenza numerica associata al server web (un computer “speciale”
parte del Web, che introdurremo nel dettaglio nel prossimo capitolo) che ha a disposizione le
informazioni della risorsa identificata dall’URL. Riprendendo la metafora precedente, è
l’indirizzo che identifica la particolare casa che contiene l’oggetto che si vuol raggiungere –
non per niente, di solito, gli URL che specificano soltanto lo schema e il server restituiscono
una risorsa che viene comunemente chiamata home page (ad esempio
https://www.repubblica.it). Nella realtà, questa specifica parte dell’URL potrebbe essere anche
più complessa, ed includere delle credenziali di autenticazione per accedere al server
(metaforicamente: le chiavi per accedere alla casa), ma abbiamo preferito non specificare
questo ulteriore dettaglio esplicitamente perché è di fatto molto poco usato negli URL
presenti sul Web.
 porta – il numero che identifica il particolare servizio a disposizione sul server web a cui si
vuole inoltrare la richiesta per avere informazioni sulla risorsa indicata dall’URL. In questo
caso, è come se la casa in cui si vuole accedere avesse a disposizione diverse entrate – per
esempio la principale, quella che affaccia sul giardino, o quella sul retro – e se ne deve
scegliere una per poter accedervi. Nel caso questo componente non venga specificato
nell’URL, si assume sempre di usare la porta di default associata al protocollo specificato (80
nel caso di “http”, 443 nel caso di “https”), che metaforicamente significa accedere alla casa
usando l’ingresso principale.
 percorso – la sequenza di locazioni all’interno del server web, separate da “/”, da
raggiungere per ottenere la risorsa indicata dall’URL. A livello generale, un server web è uno
speciale computer elettronico che ha memorizzati diversi documenti, organizzati in diverse
cartelle, esattamente come siamo abituati a organizzare i nostri documenti nei nostri
computer. In pratica, il percorso di un URL identifica esattamente una risorsa all’interno di
questo computer speciale. Metaforicamente, una volta entrati nella casa, il percorso potrebbe
essere usato per indicare la sequenza di locali della casa che devo attraversare per arrivare
alla stanza che contiene l’oggetto che mi interessa, indicato come ultimo elemento del
percorso – ad esempio, “scale a sinistra / primo piano / corridoio / seconda porta a destra /
camera dei bambini”.
 interrogazione – è una sequenza di coppie chiave=valore, separate da “&”, che è possibile
comunicare al server web in modo da eseguire determinate operazioni sulla risorsa indicata
dall’URL. Nell’esempio precedente, è come se, per esempio, potessimo chiedere alla casa di
eseguire determinate azioni, come accendere le luci della camera in cui ci troviamo – cosa
non tanto utopistica ai giorni nostri, se si considera l’enorme diffusione della domotica nel
nostro quotidiano.
 frammento – una sequenza di caratteri che permette di identificare una parte o una
posizione specifica all’interno della risorsa indicata dall’URL. Utilizzando sempre la metafora
precedente, è come se avessimo la possibilità di indicare uno specifico oggetto presente nella
camera dei bambini della casa in cui siamo entrati, ad esempio il letto a castello dei bambini.

L’URL di Wikipedia introdotto precedentemente a scopo esplicativo presenta solo alcuni dei
precedenti componenti, in particolare:

 lo schema specificato è “http”, che identifica l’uso del relativo protocollo, che approfondiremo
nei capitoli successivi;
 l’host specificato è “it.wikipedia.org”, che identifica il nome del server web che contiene la
risorsa a cui siamo interessati;
 il percorso specificato è “/wiki/Uniform_Resource_Locator”, che indica di cercare la risorsa
“Uniform_Resource_Locator” all’interno della locazione “wiki”.

Questi tre componenti sono, di solito, i principali utilizzati negli URL presenti nel Web e nascosti
dietro i link ipertestuali che sono specificati in una pagina Web. Ogni qual volta che, da un proprio
dispositivo (un computer, uno smartphone, etc.), si clicca su un link, il dispositivo stesso recupera
una copia della risorsa (ad esempio, della pagina Web) a cui l’URL si riferisce, per poi visualizzarla a
video. Quindi, seppur noi implicitamente diciamo che, a seguito di un click su un link, noi ci
spostiamo da una pagina web ad un’altra, quel che davvero accade è che il dispositivo usato per
“navigare” tra le pagine web in realtà scarica interamente e localmente una copia della pagina web a
cui si vuole arrivare, e poi la visualizza. Queste azioni sono di fatto implementate,
indipendentemente dal dispositivo usato, da una specifica tipologia di applicazioni chiamate browser
web (o, più semplicemente browser), introdotta di seguito.

5. I browser: cosa sono e a cosa servono


Un browser è un’applicazione software che permette di accedere e ottenere le informazioni presenti
nel Web, così da poterlo “navigare”, come si dice in gergo. Internet Explorer, Firefox, Microsoft
Edge, Safari, Google Chrome sono tutti esempi di browser.

Il primo browser della storia si chiamava WorldWideWeb (mostrato in Figura 9), come il Web stesso,
creando non poca confusione all’inizio. Era stato sviluppato da Tim Berners-Lee come applicazione
per il computer NeXT in modo da permettere ad un utente di navigare tra le pagine del Web allora
presenti – la cui prima pagina è ancora custodita negli spazi dedicati a Tim Berners-Lee del sito web
del World Wide Web Consortium, un’organizzazione non governativa e internazionale fondata da
Tim Berners-Lee per governare, nel modo più comunitario possibile, l’evoluzione del Web.

Il funzionamento di un qualunque browser, incluso il primo sviluppato, segue sempre il medesimo


schema. Come anticipato, ogni risorsa presente nel Web – sia essa una pagina web, un’immagine, un
documento PDF e quant’altro – è identificata da un certo URL. Il browser permette di specificare
quell’URL in un apposito campo della sua interfaccia, solitamente in alto, in modo da poter scaricare
in locale le informazioni relative alla risorsa indicata dall’URL e, a seconda del tipo di risorsa,
permette di visualizzarla all’interno della finestra browser (ad esempio nel caso di una pagina web) o
di salvarla in uno specifico documento nel proprio computer (ad esempio nel caso di un documento
PDF). Nel primo caso, la pagina web visualizzata è un documento ipertestuale a tutti gli effetti: può
contenere dei link che, se cliccati, indicano al browser di richiedere e scaricare la risorsa identificata
dall’URL del link stesso così da visualizzarla.

CAPITOLO CINQUE

1. Introduzione

Nel precedente capitolo, in questo, e nei successivi affronteremo tutte le tecnologie alla base di
Internet e del World Wide Web. Tuttavia, invece di affrontare questi temi in modo tradizionale,
ovvero partendo dalla descrizione architetturale di Internet per poi presentare il Web, abbiamo
voluto introdurre questi argomenti seguendo la traccia fornita da Tim-Berners Lee (l’inventore del
Web) in un noto documento esplicativo a disposizione sul suo sito Web.

In particolare, l’obiettivo è quello di rispondere ad una semplice, seppur significativa, domanda:

Cosa succede quando si clicca su un collegamento ipertestuale (o link) di una pagina Web?

In Figura 1 sono riassunte le tecnologie che abbiamo introdotto nel capitolo precedente e che ci
hanno permesso di iniziare ad introdurre gli elementi principali per rispondere alla domanda appena
presentata. In particolare, una volta che si clicca su un link di una pagina web visualizzata attraverso
un browser, il browser recupera l’URL della risorsa celato dietro il link e richiede una copia di
quella risorsa al server web che la ospita. Una volta che questa copia viene ricevuta dal browser,
questi la visualizza (nel caso sia una pagina web, per esempio) o ne permette la memorizzazione
all’interno del dispositivo da cui è partita la richiesta attraverso il browser usato.

In questo capitolo approfondiremo meglio cosa siano i protocolli di comunicazione, in particolare


quelli usati principalmente per comunicare richieste e informazione sul Web. Inoltre
approfondiremo meglio il concetto di server web, delineandone le caratteristiche principali.

2. Che cos’è un protocollo di comunicazione

Formalmente, un protocollo di comunicazione è un insieme di regole che due entità, parte di un


sistema di comunicazione, devono seguire per scambiarsi informazioni. Informalmente, può essere
considerato come un linguaggio comune, nel senso proprio del termine, usato da due entità in modo
da poter comunicare fra loro. Infatti, ogni protocollo definisce una specifica sintassi da seguire per
costruire i messaggi, accompagnata da determinate regole interpretative del messaggio così da
definirne anche la semantica. Inoltre, solitamente, un protocollo di comunicazione prevede anche dei
meccanismi per sincronizzare la comunicazione e per correggere e/o gestire eventuali errori che
possono intercorrere nello scambio dei messaggi.

Protocolli di varia natura, anche informali, sono utilizzati nella vita di tutti i giorni quando
vogliamo, per esempio, comunicare con qualcuno. Per esempio, il diagramma in Figura 2 riassume le
componenti principali del protocollo, strettamente informale, che due persone, fluenti nella lingua
italiana, utilizzano per scambiarsi delle informazioni verbalmente. In questo caso, mentre la sintassi
della lingua è veicolata da opportune regole, e la semantica delle varie parole che compongono il
messaggio è stata appresa nel tempo con l’apprendimento della lingua stessa, le altre componenti del
protocollo derivano principalmente da regole sociali (ad esempio, il parlare uno alla volta) e dalle
proprie conoscenze (ad esempio, riproponendo il senso di un messaggio usando differenti costrutti
se è poco chiaro all’interlocutore) e dall’ambiente circostante (ad esempio, alzando la voce per farsi
sentire meglio). Nel corso di questo e dei successivi capitoli, analizzeremo alcuni dei protocolli di
comunicazione più importanti per il funzionamento del Web e di Internet, a partire dal protocollo
HTTP.

3. Come funziona l’Hypertext Transfer Protocol (HTTP)

L’Hypertext Transfer Protocol, o HTTP [Fielding et al., 1999], è un protocollo di comunicazione


inizialmente sviluppato da Tim Berners-Lee per facilitare l’implementazione del Web, e poi
migliorato ed esteso negli anni successivi – ad esempio con il protocollo HTTPS, che altri non è che
un’estensione di HTTP che implementa un protocollo di comunicazione più sicuro sul Web, in
particolare quando è necessario trasmettere dati di autenticazione come nomi utenti e password.
HTTP è un protocollo basato su metodi di comunicazione di richiesta-risposta, tipico di molti
protocolli (anche informali) di comunicazione – si pensi, ad esempio, al protocollo che regola le
telefonate, dove un richiedente chiama (la richiesta) un ricevente che accetta la chiamata (la risposta)
per iniziare la conversazione.

Nel caso di HTTP, un client (l’agente che fa la richiesta, ad esempio un browser) manda un
messaggio di richiesta di una specifica risorsa, identificata da un URL, ad un server (l’agente che
dovrebbe avere informazioni su quella specifica risorsa, ad esempio un server Web), che restituisce al
client un messaggio di risposta. La composizione di questo messaggio di risposta dipende da diversi
fattori – ad esempio se la risorsa è o non è presente sul server, se è stata spostata in un’altra
locazione, etc. – e, anche, dal tipo di richiesta effettuata dal client.

Le tipologie di richieste che possono essere effettuate da un client vengono definite grazie all’uso di
uno specifico metodo, ovvero l’operazione di richiesta relativa all’URL coinvolto nella
comunicazione. In pratica è come se, quando si comunica con qualcuno, si avesse la possibilità di
scegliere tra alcune possibili operazioni che il ricevente deve eseguire, che possono andare dalla
semplice richiesta di informazioni (ad esempio, quando chiamiamo la banca per sapere lo stato del
nostro conto), ad azioni più operative che determinano l’esecuzione di una specifica azione da parte
del ricevente (ad esempio, quando chiamiamo la banca per far emettere un bonifico).

Il metodo più usato nel Web è sicuramente GET, che permette di richiedere informazioni sulla
risorsa definita dall’URL specificato. GET viene usato ogni qual volta richiediamo di visitare una
specifica pagina web, per esempio come conseguenza di un click su un collegamento ipertestuale.
Altri metodi largamente usati sono:

 PUT permette di creare sul server web contattato la risorsa specificata dall’URL utilizzato
nella richiesta, e di associare le informazioni, relative ad essa, incluse nella richiesta
effettuata;
 DELETE permette di rimuovere dal server web contattato tutte le informazioni relative alla
risorsa specificata nella richiesta tramite l’URL;
 POST permette di specificare informazioni aggiuntive, incluse nella richiesta, ad una risorsa
esistente che già risiede sul server.

Tuttavia, mentre GET è preponderante nel Web, visto che viene usato per richiedere una qualsiasi
risorsa, gli altri metodi non sempre sono liberamente utilizzabili da tutti i client. Sta sempre al
server web decidere quali di questi metodi possano essere usati nella comunicazione.

Tutti i metodi HTTP sono classificabili a seconda che siano conformi o meno a due caratteristiche
specifiche, ovvero se sono safe e/o se sono idempotenti. Un metodo si dice safe quando viene usato
solo per recuperare delle informazioni dal server web, senza cambiarne lo stato, ad esempio
aggiungendo nuovi dati. Il metodo GET è un metodo safe, considerando che viene usato soltanto per
richiedere informazioni relativamente ad una specifica risorsa, mentre PUT non lo è perché viene
usato per creare una nuova risorsa sul server web. Invece, un metodo si dice idempotente se
molteplici richieste effettuate allo stesso URL hanno lo stesso effetto, sul server web, che effettuare
una sola richiesta. Anche in questo caso, il metodo GET, così come PUT e DELETE, sono metodi
idempotenti, mentre POST non lo è, perché diverse richieste POST identiche possono di fatto
generare comportamenti differenti.

A prescindere dal metodo usato per la comunicazione, tutti i messaggi di ogni richiesta e risposta
veicolano due tipi di dati ben distinti: i metadati relativi alla comunicazione – come il nome di client
usato per effettuare la richiesta, il nome del server web che dovrebbe avere a disposizione la risorsa,
etc. – ed eventuali dati (o contenuto) da accompagnare al messaggio. Per esempio, in una
conversazione telefonica, il chiamante come prima cosa introduce chi è al ricevente (i metadati della
comunicazione), per poi passare ad esplicitare il motivo della chiamata e le informazioni che si
vorrebbero ottenere (il contenuto della comunicazione).

Considerando i messaggi consegnati utilizzando il protocollo HTTP, queste due tipologie di


informazioni, ovvero i metadati e i dati, sono contenute in due specifiche sezioni del messaggio,
rispettivamente chiamate intestazione (header) e contenuto (payload). Tipicamente, una qualunque
richiesta o risposta ha sempre l’header specificato, mentre il payload può contenere informazioni
come no. Per esempio, quando si richiede una pagina web attraverso un browser, viene effettuata
una richiesta ad un certo URL contenente soltanto i metadati nell’header, mentre il payload è
completamente vuoto. Al contrario, la risposta del server web contiene sia informazioni nell’header
sia un vero e proprio documento nel payload, ovvero la pagina web che deve essere visualizzata sul
browser richiedente, nel caso tale informazione sia a disposizione del server web a cui è arrivata la
richiesta.

Tutte le risposte, oltre che a contenere metadati nell’header e, talvolta, dati nel payload, specificano
anche un codice di stato che indica se la richiesta è andata a buon fine o se sono intercorsi dei
problemi. Un codice di stato è un numero di tre cifre, la cui prima cifra (da 1 a 5) definisce la classe
di risposta, mentre le altre due sono usate per identificare una specifica motivazione relativa alla
risposta.

Le cinque classi di risposta sono:

1. risposta informativa – la richiesta è stata ricevuta e correttamente compresa, e sono


necessari alcuni passaggi aggiuntivi (attendere, cambiare protocollo, etc.) per poter ottenere le
informazioni sulla risorsa richiesta;
2. successo – la richiesta è stata ricevuta, correttamente compresa, e accettata;
3. redirezione – il client deve effettuare specifiche azioni aggiuntive per completare la richiesta
(ad esempio, cercare le informazione sulla risorsa ad un altro URL);
4. errore del client – la richiesta presenta un qualche errore lato client (ad esempio, non si ha
il permesso di accedere alla risorsa, non è stata trovata alcuna informazione associata alla
risorsa, etc.) e non può essere soddisfatta;
5. errore del server – il server web ha incontrato un qualche problema nel soddisfare la
richiesta (ad esempio, server non è disponibile al momento a causa di un sovraccarico di
gestione, non supporta il protocollo HTTP utilizzato dalla richiesta, etc.)

Mentre i codici della classe 1 sono solitamente abbastanza rari, i più comuni, in una comunicazione
HTTP, sono i seguenti (tra parentesi le etichette esplicative ufficiali):

 codice 200 (OK) – la richiesta è stata soddisfatta con successo;


 codice 303 (See Other) – la risposta alla richiesta può essere trovata ad un altro URL;
 codice 400 (Bad Request) – la richiesta non può essere processata dal server;
 codice 403 (Forbidden) – la richiesta è valida, ma il client non ha i permessi necessari per
accedere alle informazioni relative alla risorsa richiesta;
 codice 404 (Not Found) – le informazioni relative alla risorsa richiesta non sono state
trovate
 codice 500 (Internal Server Error) – un errore generico lato server non ha permesso il
corretto processamento della richiesta;
 codice 503 (Service Unavailable) – il server è temporaneamente non disponibile.

Per riassumere: ogni qual volta un client manda una richiesta HTTP, utilizzando uno dei metodi
HTTP a disposizione, relativamente ad una certa risorsa identificata da un URL, in realtà manda uno
specifico messaggio contenente informazioni generali sulla richiesta (i metadati, contenuti nel campo
header del messaggio) e, eventualmente, dei dati (il payload del messaggio) ad un server destinatario
in qualche modo codificato all’interno dell’URL della risorsa richiesta. Il destinatario, letto il
messaggio, restituisce risposta affermativa, con codice di stato 200, accompagnata dal relativo
messaggio di risposta se può evadere la richiesta correttamente, altrimenti restituisce un opportuno
messaggio di errore, così da rendere esplicito al mittente cosa non ha funzionato nella
comunicazione.

4. Che cos’è un server web

Come anticipato nel precedente capitolo, un server web è un computer “speciale” che esegue un
software specifico che permette di ricevere, gestire, e soddisfare richieste HTTP provenienti da un
client, ad esempio un browser. Il nome del server web è incluso nell’URL che identifica la risorsa di
cui si vuole ottenere informazioni, nella parte host, come introdotto nel capitolo precedente (ad
esempio it.wikipedia.org). Tuttavia, la forma corretta e completa della richiesta HTTP mandata dal
client non è quella semplicistica introdotta precedentemente col solo URL, ma è strutturata in modo
preciso, in modo da identificare i vari componenti che ne fanno parte, incluso il nome del server
web da contattare.

In particolare, quando un client (ad esempio, un browser) richiede informazioni su una specifica
risorsa (ad esempio una pagina web) utilizzando l’URL relativo, la richiesta che viene davvero
effettuata ha la seguente forma, dove ogni parte della richiesta è di fatto derivata dall’URL:

<metodo HTTP> <percorso> <protocollo>

HOST: <nome del server>

Ad esempio, quando si vuole accedere alla pagina web all’URL


http://it.wikipedia.org/wiki/Uniform_Resource_Locator, la richiesta effettuata dal browser viene
strutturata come segue:

GET /wiki/Uniform_Resource_Locator HTTP/1.1

HOST: it.wikipedia.org

Una volta che il server web riceve una richiesta fatta in questo modo, cerca localmente informazioni
del documento indicate nel percorso della richiesta e, una volta trovate, le impacchetta in un nuovo
messaggio di risposta, restituendole al richiedente.

Tuttavia, c’è un ulteriore aspetto molto importante che non è stato ancora discusso in questo
capitolo. Seppur noi, utilizzatori di client come i browser, cerchiamo di accedere ad una risorsa a
disposizione in un certo server web usando il nome di quest’ultimo, it.wikipedia.org nell’esempio
precedente, in realtà il server web non è direttamente raggiungibile usando il suo nome, ma avviene
una cosa molto simile a quello che succede con una comunicazione telefonica. In pratica, quando
dobbiamo chiamare qualcuno col nostro cellulare, cerchiamo questa persona nella nostra rubrica
attraverso il suo nome, e chiediamo al nostro cellulare di iniziare una chiamata telefonica. Tuttavia,
quello che davvero fa il cellulare, è di prendere il numero di telefono associato a quella persona e di
attivare la comunicazione mandando una richiesta di telefonata a questo numero. Ovviamente, in
alternativa, si potrebbe anche digitare direttamente il numero di telefono della persona che si vuol
chiamare se si conosce a memoria, senza necessariamente cercarla in rubrica. In più, se il numero
chiamato è un numero fisso di casa, e in casa vivessero diverse persone, una volta che la telefonata è
stata risposta, il mittente dovrebbe chiedere esplicitamente al ricevente di poter parlare con la
persona di interesse.

Questo scenario, molto naturale, si presenta in modo totalmente analogo anche quando un client
richiede una pagina web ad un server web. Infatti, un qualunque server web è identificato in modo
univoco da una sequenza di quattro numeri separati da punti, ad esempio 130.136.130.1, ove ogni
numero può essere un valore che va da 0 a 255. Questo numero si chiama indirizzo IP, dove “IP” è
l’acronimo di “Internet Protocol”, che discuteremo in dettaglio nel capitolo successivo. In pratica,
ogni volta che si fa una richiesta HTTP, in qualche modo viene recuperato l’indirizzo IP del server
web a cui mandare la richiesta partendo dal nome di questo indicato nell’URL – il campo host – per
poi inviare il messaggio esplicitamente a quell’indirizzo, menzionando esplicitamente, come abbiamo
visto in precedenza, qual è il nome del server a cui il messaggio deve essere rivolto – nell’esempio
sopra HOST: it.wikipedia.org. Figura 3 estende il diagramma in Figura 1 includendo tutte le
tecnologie presentate in questo capitolo.

CAPITOLO SEI

1. Introduzione

Nei precedenti due capitoli, in questo, e nei successivi affronteremo tutte le tecnologie alla base di
Internet e del World Wide Web. Tuttavia, invece di affrontare questi temi in modo tradizionale,
ovvero partendo dalla descrizione architetturale di Internet per poi presentare il Web, abbiamo
voluto introdurre questi argomenti seguendo la traccia fornita da Tim-Berners Lee (l’inventore del
Web) in un noto documento esplicativo a disposizione sul suo sito Web. In particolare, l’obiettivo è
quello di rispondere ad una semplice, seppur significativa, domanda:

Cosa succede quando si clicca su un collegamento ipertestuale (o link) di una pagina Web?
In Figura 1 sono riassunte le tecnologie che abbiamo introdotto nei due capitoli precedenti e che ci
hanno permesso di iniziare ad introdurre gli elementi principali per rispondere alla domanda appena
presentata. In particolare, una volta che si clicca su un link di una pagina web visualizzata attraverso
un browser, il browser crea un messaggio di richiesta che specifica il metodo HTTP utilizzato per la
richiesta, ovvero GET, il server web a cui la richiesta deve essere fatta, e il percorso della risorsa
richiesta. Il messaggio arriva, in qualche modo, al server web, identificato da un numero univoco
chiamato indirizzo IP. Il server web elabora la richiesta e, se soddisfacibile, crea un nuovo messaggio
di risposta, a cui è associato uno specifico codice di stato a seconda del tipo di risposta da restituire,
che include una copia della pagina web richiesta nel corpo del messaggio. Una volta che questa copia
viene ricevuta dal browser, questi la visualizza (nel caso sia una pagina web, per esempio) o ne
permette la memorizzazione all’interno del dispositivo da cui è partita la richiesta attraverso il
browser usato.

In questo capitolo approfondiremo cosa sia Internet e quali sono i protocolli di comunicazione che
lo contraddistinguono dal Web. Inoltre, introdurremo alcuni strumenti che permettono il corretto
funzionamento di Internet, ovvero i router e il DNS.

2. La nascita di Internet

La prima cosa da evidenziare chiaramente è che Internet non è sinonimo di Web – infatti, i due
concetti si riferiscono a due entità distinte. Semmai, si può dire che il Web è uno dei più famosi
servizi di Internet – non il solo, basti pensare alla e-mail, il trasferimento di documenti, o sistemi
Voice over IP per comunicazioni audio e/o video come Skype o WhatsApp – perché si basa
interamente sulle tecnologie messe a disposizione da Internet.

La parola Internet in realtà è una contrazione di interconnected network, rete interconnessa in


italiano. Di fatto è una rete composta da tante altre reti più piccole di dispositivi (computer, cellulari,
etc.) in qualche modo interconnessi tra loro mediante l’uso di specifici protocolli di comunicazione.
Il concetto principale che stava dietro la realizzazione di Internet è che doveva essere
un’infrastruttura generale che potesse permettere la creazione di nuove applicazioni [Leiner et al.,
1997].
Storicamente, le ragioni principali che hanno portato alla nascita di Internet sono da recuperare
negli anni immediatamente successivi alla seconda guerra mondiale, in corrispondenza delle tensioni
internazionali che erano nate tra Russia e Stati Uniti d’America, confluite in quella che è conosciuta
come guerra fredda [Lukasik, 2011]. A seguito dei primi esperimenti atomici effettuati dalla Russia e
dal conseguente sviluppo della realizzazione di missili balistici intercontinentali, uno degli obiettivi
primari degli Stati Uniti era quello di provvedere ad una creazione di una rete di comunicazione che
fosse abbastanza robusta da continuare a garantire la comunicazione tra tutti gli stati anche in
seguito ad un attacco missilistico molto rilevante, ad esempio con testate nucleari. A tale scopo, nel
1958, come risposta al lancio dello Sputnik 1 da parte dei Russi, era stata fondata la Advanced
Research Projects Agency (ARPA), responsabile per la ricerca e lo sviluppo di tecnologie emergenti
con forte applicabilità a livello militare, che coinvolgeva esperti provenienti da diverse realtà: quella
industriale, quella accademica, e quella governativa.

Tra le tante cose che ARPA finanziò, tra cui anche l’oN-Line System sviluppato da Douglas Engelbart
introdotto qualche capitolo fa, ci fu l’Advanced Research Projects Agency Network (ARPANET),
quello che viene comunemente definito il precursore di Internet. Il primo responsabile del
programma Command and Control Research di ARPA, Joseph Carl Robnett Licklider (mostrato in
Figura 2), fu il visionario che già nel 1962 iniziò a parlare di Galactic Network [Leiner et al., 1997],
ovvero un insieme di computer interconnessi a livello globale attraverso il quale chiunque avrebbe
potuto accedere a dati e programmi da ogni punto di accesso a disposizione. Seppur non fosse più in
ARPA nel momento in cui ARPANET fu finanziata, riuscì a convincere il suo successore, Ivan
Sutherland, che il progetto era meritevole di essere proseguito.

Il primi nodi di ARPANET furono installati nel Network Measurement Center della University of
California Los Angeles (UCLA) e lo Stanford Research Institute (SRI). Il primo messaggio della
storia, registrato in un diario mostrato in Figura 3, fu inviato da Charles S. Kline, uno studente
universitario, il 29 ottobre 1969 da un computer del laboratorio di Leonard Kleinrock dell’UCLA ad
un computer dello SRI. Il contenuto del messaggio era la stringa “lo” – doveva inizialmente essere la
parola “login”, ma dopo l’invio dei primi due caratteri il sistema si bloccò, e venne ripristinato solo
un’ora più tardi.

Negli anni successivi, i nodi della nuova rete ARPANET crebbero notevolmente fino ad arrivare a 61
nel luglio del 1977 [Lukasik, 2011] (riassunti in Figura 4), mentre la rete venne ufficialmente e
pubblicamente mostrata solo nel 1972 durante la prima International Computer Communication
Conference a Washington – anno in cui venne anche dimostrata una delle prime applicazioni di
ARPANET, la posta elettronica (o e-mail) sviluppata da Ray Tomlinson. Durante questi anni, furono
sviluppate le tecnologie e i protocolli chiave che hanno permesso la nascita di Internet come la
conosciamo oggi, tra tutti la tecnica a commutazione di pacchetto per l’invio e la ricezione dei dati e
la suite di protocolli Internet (TCP/IP).

Dopo ARPANET, diverse reti sono iniziate a sorgere, inizialmente negli Stati Uniti e poi nel resto
del mondo. Tra le più importanti si ricordano:

 Computer Science Network (CSNET), finanziata nel 1981 dalla National Science Foundation
(NSF) per collegare i dipartimenti di informatica delle varie università americane che non
erano già collegate ad ARPANET;
 National Science Foundation Network (NSFNET), finanziata qualche anno dopo la
precedente sempre dalla NSF per collegare tra loro i centri che mettevano a disposizione i
supercomputer finanziati dalla stessa NSF;
 NASA Science Network (NSN), finanziata a metà degli anni ottanta dalla National
Aeronautics and Space Administration (NASA).

La suite di protocolli TCP/IP, menzionata precedentemente, è stato lo strumento grazie al quale


tutte queste reti sono state poi intercollegate tra loro, permettendo per la prima volta la
comunicazione tra computer collegati a reti differenti. La nascita di Internet avviene di fatto alla fine
degli anni ottanta, quando ARPANET e NSFNET vengono intercollegate tra loro: per la prima volta,
due reti differenti (e i computer che a esse solo collegati) possono “dialogare” tra loro mediante
l’utilizzo dei suddetti protocolli. Seppur i primi passi di Internet erano stati mossi, e nei successivi
anni sempre più reti vennero collegate tra loro in questa gigantesca infrastruttura, probabilmente la
spinta definitiva del processo di espansione e popolarità della rete come la conosciamo oggi venne
data dal Governo degli Stati Uniti d’America, in particolare dall’allora senatore Al Gore. Fin dalla
fine degli anni ottanta, Gore inizia una sua personale campagna di supporto a Internet e alle sue
potenzialità e, in particolare, alla sua drastica estensione, in modo di permettere la connessione
contemporanea di milioni di computer, non solo appartenenti a enti di ricerca o a industrie, ma (e
soprattutto) posseduti da comuni cittadini. A tal fine, dopo aver anticipato le sue idee in un noto
articolo di Scientific American [Gore, 1991], Al Gore introduce un atto, l’High Performance
Computing Act of 1991 (HPCA) (o, informalmente, Gore Bill) firmato dall’allora presidente George
H. W. Bush, che – grazie all’investimento di 600 milioni di dollari e all’attiva collaborazione di
industrie, accademia, e governo – prevedeva la creazione di un’enorme rete ultraveloce chiamata
National Research and Education Network (NREN). Questo investimento, seguito dagli successivi
sviluppi del Web e dal rilascio del primo browser interamente grafico, Mosaic (1993), sviluppato
grazie ai fondi provenienti dalla Gore Bill, hanno permesso la larga diffusione di Internet non solo
negli Stati Uniti, ma come fenomeno di carattere mondiale.

3. Pacchetti di comunicazione

Nella precedente sezione abbiamo parlato di quali siano stati gli eventi principali che hanno portato
alla nascita di Internet, visto come un insieme di reti interconnesse tra loro che permettono a due
computer, anche distanti e presenti su reti diverse, di poter comunicare mediante l’uso di opportuni
protocolli di comunicazione. Oltre ai protocolli di comunicazione utilizzati, ovvero la suite di
protocolli Internet TCP/IP, l’altra grande invenzione che ha permesso la creazione di Internet è il
concetto di pacchetto e, conseguentemente, di comunicazione a commutazione di pacchetto.

Un pacchetto è un’unità atomica in informazione, formata solitamente da due componenti: l’header,


contenente informazioni relative al controllo di una comunicazione, e il payload, ovvero i dati che il
pacchetto trasmette. Solitamente, in Internet, i pacchetti sono caratterizzati da una dimensione
massima in termini di informazione che possono contenere, per cui, quando un mittente vuole
mandare un messaggio attraverso Internet, è necessario spezzare il suddetto messaggio in diversi
pacchetti che verranno inviati nella rete per poi essere ricevuti dal destinatario del messaggio.
Solitamente, in Internet, un pacchetto contiene, nell’header, gli indirizzi IP del computer mittente e
del computer destinatario del pacchetto, e altre informazioni di utilità per la comunicazione, come il
tempo di vita del pacchetto nella rete, la dimensione dei dati che il pacchetto contiene, etc.

L’introduzione nell’uso dei pacchetti come meccanismo di comunicazione venne fatta i primi anni
del 1960, in modo indipendente, da due scienziati: Paul Baran e Donald Davies – per poi essere
perfezionata da Leonard Kleinrock, uno dei padri di ARPANET. L’idea era piuttosto rivoluzionaria
per l’epoca e sovvertiva la tecnica allora usata per le comunicazioni, la commutazione di circuito,
imposta dalla Bell, la più grande compagnia telefonica statunitense dell’epoca.
L’idea della commutazione di circuito è abbastanza semplice. Nel momento in cui un mittente e un
destinatario vogliono attivare una comunicazione, ad esempio mediante una telefonata, viene
stabilito un circuito virtuale unico di comunicazione, ovvero una sequenza finita e sequenziale di
nodi riservati che permette la sola comunicazione dal mittente al destinatario usando tutta la banda
a disposizione, e che occupa in modo esclusivo i suddetti nodi fino al termine della telefonata.

Principali differenze tra una comunicazione a commutazione di circuito (a sinistra) e quella a


commutazione di pacchetto (a destra). Nella prima, viene creato un circuito virtuale dedicato tra mittente e
destinatario che occupa tutta la banda a disposizione, e che non permette l’uso dei nodi del circuito per altre
comunicazioni se non per quella attiva, finché il messaggio non è stato completamente trasmesso. Nella
seconda, i pacchetti che formano il messaggio sono di fatto indipendenti tra loro, e non viene preallocata
alcuna banda tra i nodi che dividono il mittente e il destinatario. Inoltre, i pacchetti possono
indipendentemente seguire diverse percorsi per giungere al destinatario finale. In quest’ultimo esempio, i
numeri da 0 a 7 indicano i vari momenti temporali della comunicazione – ad esempio, al tempo 4, il
pacchetto verde si trova nel nodo 8 mentre gli altri due sono nel nodo 6.
Nella comunicazione a commutazione di pacchetto, invece, il messaggio viene, come anticipato,
spezzato in diversi pacchetti, che vengono trasmessi sulla rete senza occupare l’intera banda di un
circuito, e vengono instradati dal mittente al destinatario seguendo, potenzialmente, percorsi diversi.
Il principale vantaggio di questa tecnica su quella a commutazione di circuito è la sua tolleranza ai
guasti, ovvero la capacità di garantire la comunicazione anche nel caso in cui uno dei componenti
della rete venisse a mancare per una qualsivoglia ragione – ad esempio, seguendo la logica americana
introdotta precedentemente, a seguito della distruzione di uno dei nodi della rete mediante l’uso di
una bomba.

4. Che cos’è l’Internet Protocol (IP)

In Internet, la comunicazione, ovvero lo scambio di dati tra due computer collegati in rete, è
realizzata mediante l’uso dei pacchetti. Tuttavia, esiste una gerarchia di incapsulamento dei dati da
spedire, definita dalla suite di protocolli Internet TCP/IP, organizzata in quattro livelli, come
mostrato in Figura 6.

I quattro strati di incapsulamento, i relativi protocolli per scambiare dati su Internet, e un esempio grafico di
come i vari messaggi vengono incapsulati. Nei pacchetti dello strato più in basso, quello di accesso alla rete,
solutamente, oltre all’header, compare anche un piccolo pezzettino chiamato trailer, che determina la fine del
pacchetto.

In pratica, è come se il messaggio da inviare da un certo mittente verso un destinatario venga prima
messo dentro una scatola A, che contiene metadati del messaggio sul coperchio (l’header), e i dati
veri e propri al suo interno (il payload). Poi, la scatola viene ricevuta dal postino, che a sua volta
mette l’intera scatola A dentro una nuova scatola B, anch’essa dotata di nuovi metadati sul coperchio
(header) e il cui contenuto (payload) è l’intero messaggio definito dalla scatola A. A sua volta, la
scatola B viene ricevuta da un centro di distribuzione postale, e viene inserita all’interno di una
nuova scatola C, con dei suoi metadati (header) e con il contenuto corrispondente all’intera scatola
B. Alla fine, la scatola C viene data ad un corriere che la organizza secondo i suoi criteri in una
nuova scatola D in modo simile all’approccio usato in precedenza negli altri passaggi, e la fa
pervenire al centro di distribuzione più vicino al destinatario. Questo centro di distribuzione estrae
la scatola C, che viene passata all’ufficio postale più indicato, che a sua volta estrae la scatola B per
poi passarla al postino. Il postino, infine, arriva all’indirizzo di consegna, estrae la scatola A e la
consegna al destinatario, che la apre e ottiene il contenuto di partenza – ovvero il payload
originariamente messo dal mittente dentro la scatola A.

I quattro livelli di incapsulamento informalmente descritti sono realizzati dai seguenti quattro
“strati” definiti dalla suite di protocolli TCP/IP:

 strato applicazione – dove vengono creati i dati dell’utente (ad esempio il messaggio di
richiesta per una pagina web, o il messaggio di risposta contenente la pagina web richiesta)
ed è dove i protocolli di alto livello, come HTTP, agiscono. Questo strato permette la
connessione tra applicazioni, ad esempio un browser con il server web, e non conosce
esplicitamente le peculiarità legate al trasporto di questi dati in Internet, regolate dagli strati
successivi;
 strato trasporto – è lo strato che permette la comunicazione tra il computer mittente e il
computer destinatario, che ospitano le due applicazioni usate per la comunicazione a livello
applicazione. In Internet, questo strato è regolato dal protocollo TCP, che vedremo nel
prossimo capitolo;
 strato di rete – è lo strato che permette la comunicazione tra i vari nodi presenti in
Internet, e che di fatto permette l’instradamento dei i vari pacchetti dal mittente fino al
destinatario passando tra le varie reti di cui Internet è composto. Questo strato è regolato dal
protocollo IP, che tratteremo in questo capitolo;
 strato di accesso alla rete – è lo strato che definisce come i vari messaggi / pacchetti
devono essere instradati all’interno di una specifica rete locale, ove il protocollo usato
dipende fortemente dalla tipologia di rete in considerazione.
Data questa separazione in strati, fornire una definizione più precisa di quali siano le differenze tra
Internet e il Web risulta ancora più semplice. Internet è quell’enorme rete, creata come
interconnessione di altre reti più piccole, che regola i protocolli di comunicazione che permettono a
due computer parte della rete di parlare tra loro, ove il messaggi che si scambiano transitano nella
rete mediante l’utilizzo del meccanismo a commutazione di pacchetto, ed è regolata da due specifici
protocolli (e conseguenti strati): TCP (strato trasporto) e IP (strato rete). Il Web, invece, è quel
particolare servizio, basato sul protocollo HTTP e costruito sopra i protocolli TCP/IP, che permette
a due applicazioni (ad esempio un browser e un server web), presenti su due computer distinti
collegati a Internet, di comunicare tra loro senza conoscere direttamente la topologia della rete e i
meccanismi di instradamento dei messaggi inviati. In breve, Internet è l’infrastruttura su cui il Web è
stato costruito. L’Internet Protocol (IP) è il protocollo che regola l’instradamento attraverso i vari
nodi di Internet dei vari pacchetti IP che, in qualche modo, compongono il messaggio originale.
Attualmente, il protocollo IP ha due versioni, entrambe correntemente utilizzate in Internet: la
versione 4 (IPv4, quella usata originariamente in Internet e attualmente quella più usata) e la
versione 6 (IPv6, ovvero quella rilasciata di seguito per poter gestire un numero maggiore di
computer collegati alla rete).

Il punto cruciale dei pacchetti IP instradati dal protocollo, indipendentemente dalla versione
utilizzata, è che specificano, per ogni pacchetto, l’indirizzo IP del mittente e l’indirizzo IP del
destinatario. Come abbiamo spiegato nel precedente capitolo, un indirizzo IP (in base alla versione 4
del protocollo, mentre nella versione 6 la sua forma è leggermente diversa) è una sequenza di
quattro numeri separati da punti, dove ogni numero può assumere un qualsiasi valore tra 0 e 255,
ad esempio 130.136.130.1. Tutti i dispositivi collegati ad Internet sono univocamente identificati da
uno specifico indirizzo IP. Per cui, non solo il server web dell’esempio in Figura 1 è dotato di un IP,
ma anche il computer collegato alla rete su cui viene eseguito il browser che fa la richiesta della
risorsa ad un certo URL è dotato di indirizzo IP, ad esempio 79.40.124.122. La differenza tra i due
indirizzi IP è che mentre quello del server web è statico, ovvero non cambia nel tempo, quello del
computer su cui è installato il browser, in linea di principio, è dinamico, ovvero cambia ogni qual
volta quel computer si collega a Internet. È bene sottolineare che, dipendentemente dalle particolari
reti che devono essere attraversate, è possibile siano necessari più pacchetti IP per recapitare un
messaggio completo da un mittente a un destinatario, perché spesso ogni rete specifica una
dimensione massima per pacchetto che può essere trasportato. Di conseguenza, è possibile, come
nell’esempio di destra in Figura 5, che un messaggio venga spezzato in più di un pacchetto IP da
consegnare al destinatario. Considerando questa situazione, emerge un’altra caratteristica tipica del
protocollo IP, ovvero la comunicazione senza connessione. In pratica, i pacchetti IP di un certo
messaggio vengono instradati in modo completamente indipendente tra loro, visto che ogni
pacchetto contiene esplicitamente l’indirizzo del computer a cui deve essere recapitato. Nello strato
di rete, il mittente e il destinatario non devono mettersi d’accordo prima di inviare i dati, ma
semplicemente agiscono senza conoscere l’eventuale stato (attivo, non disponibile, etc.) dell’altro.

Di conseguenza, è possibile che i pacchetti possano perdersi, non arrivare nell’ordine in cui sono
stati mandati, arrivare duplicati, e quant’altro. Il protocollo IP, tuttavia e proprio per la sua natura di
essere senza connessione, non è responsabile della risoluzione di queste problematiche, e demanda
tutta la gestione di queste situazioni direttamente allo strato di trasporto dei due computer mittente
e destinatario coinvolti nella comunicazione, regolato dal protocollo TCP.

5. Domain Name Server (DNS) e router

Negli scenari presentati nelle sezioni precedenti, e che abbiamo in qualche modo anticipato anche
nel capitolo precedente quando abbiamo portato avanti la storia del “cosa succede quando si clicca
su un link ipertestuale”, abbiamo tralasciato due aspetti fondamentali per permettere la
comunicazione tra il mittente e il destinatario di un messaggio e, quindi, il corretto instradamento
dei pacchetti. Queste due questioni si possono riassumere nelle seguenti due domande:

 Come si fa a recuperare l’indirizzo IP del server web a cui mandare il messaggio di richiesta
preparato dal browser, ovvero i relativi pacchetti IP, se si ha solo a disposizione il nome del
server web (ad esempio, it.wikipedia.org)?
 Abbiamo visto che i pacchetti IP vengono instradati attraverso i vari nodi di Internet prima
di arrivare al destinatario, ma cosa sono davvero questi nodi?

Inizialmente, quando Internet era ancora piccola, esisteva una specifica tabella di mappatura tra il
nome dei server web della rete e il relativo indirizzo IP statico che gli era stato assegnato. In pratica,
questa mappatura era messa a disposizione su un documento che si poteva scaricare ed era
mantenuta da uno specifico ente, lo Stanford Research Institute. Tuttavia, con l’ingrandimento
esponenziale di Internet negli anni successivi, avere un meccanismo centralizzato che mettesse a
disposizione queste mappature non era più gestibile. Per ovviare al problema, agli inizi del 1980
venne creato il Domain Name System (DNS).

Il DNS altro non è che una sorta di elenco del telefono di Internet. Infatti, partendo dal nome di un
server web, ad esempio it.wikipedia.org, permette di ottenere il relativo indirizzo IP, 208.80.154.224
per l’esempio introdotto. In Internet, ci sono diversi computer speciali chiamati server DNS, il cui
ruolo è quello di restituire il corretto indirizzo IP per un certo nome a seguito di una richiesta fatta
dal DNS Resolver a disposizione sul computer mittente del messaggio. In pratica, ogni volta che si
chiede di avere informazioni una risorsa ad un certo URL, il browser prima contatta il DNS
Resolver a disposizione del computer che lo ospita e gli chiede di ottenere il relativo indirizzo IP
dell’host specificato nell’URL. Il DNS Resolver contatta il più vicino server DNS che conosce – il cui
indirizzo IP è stato configurato a mano o ottenuto dinamicamente nel momento in cui il computer
mittente si è connesso a Internet – mandandogli la richiesta di risoluzione. Una volta trovato l’IP,
eventualmente chiedendo aiuto anche ad altri server DNS sparsi per la rete, il server DNS restituisce
la mappatura al DNS Resolver, che lo mette a disposizione del browser e, eventualmente, anche ad
altre applicazioni. In questo modo, ora si ha a disposizione anche l’indirizzo del server web da
contattare, che verrà usato per preparare i vari pacchetti IP da inviare al computer destinatario.

I server DNS si aggiungono alla lista di dispositivi che abbiamo visto finora, insieme ai server web e
ai computer personali collegati alla rete, e che fanno parte di questa enorme rete di comunicazione
chiamata Internet – un’immagine parziale di rappresentazione di Internet datata 2005 è introdotta
in Figura 7. A livello astratto, ogni nodo di Internet è, di fatto, uno specifico computer che può avere
uno o più ruoli. I nostri computer personali di casa servono a noi per collegarci a Internet, reperire
e scambiare informazioni con altre persone connesse alla rete, ad esempio usando specifici servizi
come il Web o la posta elettronica. I server web sono dei computer in grado di interpretare richieste
HTTP e, di fatto, mettono a disposizione pagine web che possono essere richieste in modo da
poterle visualizzare e navigare su un browser. I server DNS sono dei computer che permettono di
recuperare un indirizzo IP a partire da un certo nome di dominio. Tuttavia, c’è almeno un altro
componente, un altro computer speciale, che è fondamentale per il corretto funzionamento della
rete, ovvero il router.

Questo dispositivo di rete – viene chiamato, normalmente, dispositivo e non computer, visto che è
esclusivamente dedicato a svolgere un compito molto peculiare e preciso – è il responsabile
dell’instradamento dei pacchetti IP dal mittente fino al destinatario. Esistono diversi tipi di router
usati in rete dipendentemente dal ruolo che svolgono. Per esempio, il router che abbiamo a casa per
permettere al nostro computer di connettersi a Internet è responsabile di metterci in contatto con il
nostro Internet Service Provider (ISP), ovvero l’operatore (ad esempio, l’azienda) che ci permette di
usufruire dei vari servizi di Internet. Altri tipi di router, invece, permettono il collegamento tra
sottoreti diverse ma sempre facenti parte di Internet. E così via.

I router agiscono principalmente sullo strato di rete, presentato in Figura 6, e svolgono il ruolo di
vigile urbano di Internet, veicolando il traffico dei pacchetti IP verso il percorso più appropriato per
raggiungere il destinatario. Il pratica, quando un router riceve un pacchetto IP, controlla qual è il
prossimo nodo a cui il pacchetto deve essere trasmesso in modo da avvicinarlo al destinatario. Una
volta identificato l’indirizzo IP del prossimo nodo, questa informazione viene incapsulata in un
nuovo pacchetto dello strato di accesso alla rete, così che venga recapitato al nodo identificato. In
generale, un router non entra mai nel merito del payload del pacchetto IP che deve trasmettere, ma
guarda soltanto il suo header in modo da capire dove sia meglio instradare il pacchetto, consultato la
sua tabella di instradamento, che può essere aggiornata in modo manuale o in modo totalmente
automatico, chiedendo informazioni ad altri router vicini. Una volta spedito il pacchetto IP, il router
non tiene traccia di alcuna informazione ad esso relativa.

La presenza dei router, così come delle altre tecnologie presentate in questo capitolo, ci permette di
estendere ulteriormente lo scenario introdotto in Figura 1 che descrive la sequenza di azione che
vengono eseguite a seguito di un click su un link di una pagina Web. Infatti, la nuova versione, in
Figura 8, mostra tutti i passaggi finora introdotti. In particolare, a seguito di un click su un link di
una pagina web visualizzata sul browser di un computer, viene composta un messaggio HTTP di
richiesta di una specifica pagina web identificata da un URL. Una volta recuperato l’indirizzo IP dal
nome del server web che ha la pagina a disposizione usando il DNS, il messaggio HTTP viene
incapsulato da uno o più pacchetti IP che vengono poi inviati dal computer mittente al router più
vicino – ad esempio il router di casa. Da lì, i pacchetti IP vengono instradati nella rete finché non
raggiungono il server web destinatario, che riceve il messaggio, e impacchetta una copia del
documento richiesto in un nuovo messaggio HTTP di risposta. A sua volta, questo messaggio viene
incapsulato in uno o più pacchetti IP inviati dal server web al router più vicino, e poi instradati fino
al mittente. Una volta ricevuto, il messaggio di risposta viene passato al browser che visualizza a
video il contenuto del payload del messaggio HTTP.

CAPITOLO SETTE

1. Introduzione

Nei precedenti tre capitoli, in questo, e nei successivi affronteremo tutte le tecnologie alla base di
Internet e del World Wide Web. Tuttavia, invece di affrontare questi temi in modo tradizionale,
ovvero partendo dalla descrizione architetturale di Internet per poi presentare il Web, abbiamo
voluto introdurre questi argomenti seguendo la traccia fornita da Tim-Berners Lee (l’inventore del
Web) in un noto documento esplicativo a disposizione sul suo sito Web.

In particolare, l’obiettivo è quello di rispondere ad una semplice, seppur significativa, domanda:

Cosa succede quando si clicca su un collegamento ipertestuale (o link) di una pagina Web?

In Figura 1 sono riassunte le tecnologie che abbiamo introdotto nei tre capitoli precedenti e che ci
hanno permesso di iniziare ad introdurre gli elementi principali per rispondere alla domanda appena
presentata. In particolare, a seguito di un click su un link di una pagina web visualizzata sul browser
di un computer, viene composto un messaggio HTTP di richiesta di una specifica pagina web
identificata da un URL. Una volta recuperato l’indirizzo IP dal nome del server web che ha la pagina
a disposizione usando il DNS, il messaggio HTTP viene incapsulato da uno o più pacchetti IP che
vengono poi inviati dal computer mittente al router più vicino – ad esempio il router di casa. Da lì, i
pacchetti IP vengono instradati nella rete finché non raggiungono il server web destinatario, che
riceve il messaggio, e impacchetta una copia del documento richiesto in un nuovo messaggio HTTP
di risposta. A sua volta, questo messaggio viene incapsulato in uno o più pacchetti IP inviati dal
server web al router più vicino, e poi instradati fino al mittente. Una volta ricevuto, il messaggio di
risposta viene passato al browser che visualizza a video il contenuto del payload del messaggio
HTTP.

In questo capitolo introdurremo l’ultimo dei protocolli di base di Internet, il TCP, e riassumeremo
nuovamente tutti i passaggi che avvengono dal momento in cui si clicca su un link di una pagina
web al momento in cui la pagina richiesta viene visualizzata sul browser.

2. Byte e bit: unità di informazione

Nello scorso capitolo abbiamo accennato al fatto che un particolare messaggio debba essere spezzato
in uno o più pacchetti IP prima che questi vengano instradati in rete. Questo è dovuto a due diversi
fattori. Il primo è il limite dato dalla massima quantità di dati che ogni pacchetto IP può trasportare
(che dipende dalla versione considerata del protocollo, IPv4 o IPv6). Tuttavia, in aggiunta a questo
limite, c’è anche il limite imposto dalla rete a cui si instradano i pacchetti, ovvero il suo Maximum
Transmission Unit (MTU). Quindi, anche se tutto il messaggio HTTP possa, in linea di principio,
essere incapsulato dentro un pacchetto IP, è possibile che debba comunque essere spezzato in più
pacchetti IP a causa del limite MTU imposto dalla rete. Questa frammentazione più avvenire sia
nello strato di rete in alcuni casi e solo se si utilizza il protocollo IPv4 per l’instradamento, o nello
strato trasporto, che sarà oggetto di questo capitolo.

Questi limiti, sia quello del protocollo IP sia quello dettato dall’MTU, sono espressi in byte. Un byte
è una delle più diffuse unità di informazione. Storicamente corrisponde al numero di bit necessari
per codificare un carattere sul computer [Bemer, 1959], e per questo è di solito l'unità minima di
informazione occupabile su un computer elettronico. In particolare, un byte corrisponde a otto bit,
ove con bit (una contrattura di binary digit) si intende l'unità minima di informazione che si può
scambiare in una comunicazione. Un bit può assumere soltanto uno di due valori: 0 o 1.

Il concetto di bit è stato indirettamente usato da diversi studiosi del passato, per esempio da Charles
Babbage con la sua macchina analitica (descritta nei capitoli precedenti) che proponeva l'uso di
schede perforate, dove la presenza o assenza di un buco in una certa posizione poteva essere
interpretata rispettivamente come l'assegnamento di un 1 o di uno 0. Tuttavia, la prima persona a
usare la parola bit fu Claude Shannon (mostrato in Figura 2) nel 1948 in un articolo che ha segnato
la nascita della teoria dell'informazione [Shannon, 1948]. In breve, la teoria dell’informazione
riguarda uno specifico campo di ricerca che studia come quantificare, memorizzare, e scambiare
informazione, che ha tuttora svariate applicazioni pratiche, oltre che aver caratterizzato e veicolato
l’invenzione di diverse tecnologie del passato, incluso lo sviluppo di Internet. Ad esempio, evincere la
capacità massima di un canale per trasmettere informazione in modo affidabile, è stato uno degli
studi della teoria dell’informazione che caratterizza qualsiasi comunicazione tra una sorgente e un
destinatario attraverso un canale di comunicazione, e ha particolare rilevanza per stabilire, per
esempio, la massima unità di informazione per pacchetto (MTU) in una particolare rete, accennata in
precedenza.

L'idea di base è che ogni carattere, numero, programma, applicazione all'interno di un computer, così
come un qualunque messaggio da scambiare in Internet, è di fatto codificato come una sequenza di
bit che, in qualche modo, vengono poi riconvertiti con la sequenza di caratteri corretta dalla
particolare applicazione che riceve ed interpreta quell'informazione. Per esempio, nella codifica
binaria tradizionale dei numeri interi, il numero 0 è rappresentato dalla sequenza "0", il numero 1 da
"1", il numero 2 da "10", il numero 3 da "11", il numero 4 da "100", e così via.

In modo indiretto, abbiamo già in qualche modo usato il concetto di byte nei capitoli precedenti. Per
esempio, tutti gli indirizzi IP (versione IPv4) che abbiamo introdotto nei capitoli precedenti sono
definiti mediante l'uso di 4 byte, uno per ogni numero. Nella codifica binaria usata, ogni byte, ovvero
8 bit, permette di definire un numero intero da 0 a 255, che sono esattamente i valori che ogni
numero dell'indirizzo IP può assumere. Il procedimento di codifica binaria, ovvero la
rappresentazione di un certo elemento (in questo caso ogni numero di un indirizzo IP) in formato
binario, è mostrato in Figura 3 e funziona come segue. Ognuno degli otto bit di un numero facente
parte dell’indirizzo IP ha assegnato uno specifico valore. In particolare, il valore 1 è associato al bit
più a destra, mentre a quello successivo verso sinistra è assegnato un valore doppio rispetto al
precedente (in questo caso 2), e così via fino ad assegnare un valore numerico ad ognuno degli 8 bit,
fino a 128. Questi valori permettono di poter specificare un qualsiasi numero compreso tra 0 e 255,
semplicemente sommandone alcuni fra loro. Infatti, sommando i soli valori di tutti i bit assegnati a 1
di un certo byte di un indirizzo IP si riesce a risalire al numero intero dell’indirizzo – ad esempio, il
byte 11010000 fa riferimento al numero ottenuto sommando di 128, 64, e 16 (ovvero i valori
assegnati ai bit impostati a 1), che è uguale a 208, il primo numero dell’indirizzo IP mostrato in
Figura 3.
Ovviamente, un qualunque messaggio e/o pacchetto spedito attraverso Internet è di fatto codificato
usando una sequenza di bit. Una parte di questi bit corrispondono a informazioni relative all’heading
del pacchetto, mentre altre sono relative al payload.

3. Che cos’è il Transmission Control Protocol (TCP)

Nella scorso capitolo abbiamo visto come l’instradamento basato sul protocollo IP non garantisce
che i pacchetti arrivino nell’ordine corretto in cui il loro payload deve essere poi ricomposto per
formare il messaggio originale. Come anticipato, sia il riordino dei pacchetti sia, in talune situazioni,
lo spezzare il messaggio originale in più pacchetti conformemente con l’MTU della rete, è gestito
dallo strato di trasporto. Il principale protocollo di questo strato è il Transmission Control Protocol
(TCP) che, insieme al protocollo IP, forma la suite di protocolli Internet, proposti da Vinton Cerf e
Robert Kahn (mostrati in Figura 4) nel maggio del 1974 [Cerf & Kahn, 1974] per essere utilizzati in
ARPANET.

Il TCP permette la consegna affidabile, ordinata, e esente da errori di un flusso di byte tra due
computer in comunicazione tra loro attraverso una rete basata sul protocollo IP, e gestisce tutti quei
processi che garantiscono la ritrasmissione di un pacchetto nel caso in cui non sia stato recapitato al
destinatario entro un certo tempo limite. Come tutti gli altri incapsulamenti visti in precedenza, ogni
pacchetto TCP è diviso in due sezioni: l’header, che contiene informazioni relative alla
comunicazione a livello trasporto tra i due computer mittente e destinatario, e il payload, ovvero le
informazioni che devono essere scambiate tra i partecipanti alla comunicazione. In particolare, tra i
campi importanti dell’header, ci sono le porte usate dal mittente e dal destinatario per la
comunicazione – quest’ultima può essere specificata nell’URL della risorsa da ottenere – e un
numero di sequenza che indica l'ordine tra i vari pacchetti in modo da poter ricostruire
correttamente il messaggio originale.

Contrariamente al protocollo IP, il protocollo TCP permette di stabilire una comunicazione


connessa, in cui il mittente e il destinatario si mettono d'accordo di iniziare una comunicazione in
modo esplicito prima di scambiarsi i dati, e dichiarano altrettanto esplicitamente quando questa
comunicazione si può ritenere conclusa. Il processo di inizio della comunicazione, per esempio, è rIn
pratica, il mittente (nell'esempio dello scenario relativo al click sul link finora discusso, il computer
con il browser) che vuole iniziare una comunicazione con un destinatario (il server web dell'esempio)
prima invia un pacchetto TCP di sincronizzazione (che verrà incapsulato in un pacchetto IP dallo
strato di rete, come spiegato nel precedente capitolo), con il campo dell'header SYN impostato ad un
numero intero scelto casualmente (il numero "A" in Figura 5). Non appena il destinatario riceve
questo pacchetto TCP, risponde al mittente inviandogli un altro pacchetto con il campo dell’header
ACK impostato al numero successivo rispetto a quello ricevuto (A+1) e con il campo SYN impostato
ad un nuovo numero intero scelto casualmente (B). Una volta che il mittente riceve questo pacchetto
TCP, risponde nuovamente al destinatario con un nuovo pacchetto, specificando nel campo ACK il
numero successivo a quello appena ricevuto (B+1). Da quel momento, il mittente è autorizzato a
mandare il messaggio, suddiviso in opportuni pacchetti, al destinatario e, conseguentemente, a
ricevere la relativa risposta. Un approccio simile si usa anche per la chiusura della connessione, ma
in questo caso si usa un four-way handshake, ovvero il mittente e il destinatario si scambiano 4
pacchetti TCP per terminare la comunicazione.

In pratica, il protocollo TCP implementa quello che normalmente avviene quando dobbiamo
chiamare, per esempio, un qualche centro servizi di un operatore telefonico per chiedere delle
informazioni. Di solito, prima ci mettiamo d'accordo col sistema (usualmente una voce pre-
registrata) su quale sia il tipo di comunicazione da effettuare (una sorta di rappresentazione
metaforica del three-way handshake), e poi la chiamata viene effettivamente risposta da un operatore
con cui interagiamo direttamente chiedendogli informazioni (il momento in cui inviamo i
dati).egolato dal meccanismo del three-way handshake, mostrato in Figura 5.

4. Altri protocolli usati su Internet

In questo e nei precedenti capitoli abbiamo visto i principali usati su Internet e un particolare
protocollo dello strato applicazione, ovvero HTTP, il principale meccanismo di comunicazione usato
sul Web. Tuttavia, HTTP non è il solo protocollo dello stato applicazione largamente usato, ma è
accompagnato da diversi altri che sono usati quotidianamente da molti utenti del Web. In questa
sezione presentiamo alcuni dei più importanti, tutti totalmente basati sul protocollo TCP per lo
strato di trasporto.
SMTP. Il Simple Mail Transfer Protocol (SMTP) è il principale protocollo di comunicazione dello
strato applicativo per spedire email. Ogni volta che si spedisce una mail, in realtà non viene
recapitata direttamente al destinatario, ma viene raccolta da un server di posta di competenza del
dominio della mail del destinatario – dominio identificato dalla parte dell’indirizzo email che segue
il carattere “@”. Questo server è come un server web, ma invece di gestire il protocollo HTTP e di
restituire pagine web, è in grado di ricevere email attraverso il protocollo SMTP, per poi inoltrarle ai
relativi destinatari quando questi ne fanno richiesta mediante l’uso del protocollo POP o IMAP,
introdotti di seguito.

POP. Il Post Office Protocol (POP) è uno dei due protocolli utilizzato per ricevere email da un
server di posta. In pratica, ogni volta che se ne fa richiesta, ad esempio attraverso un client per email
(Apple Mail, Outlook, Mozilla Thunderbird), il server di posta consegna tutti i messaggi
precedentemente inviati a quel particolare destinatario e, una volta consegnati, li cancella dal server.

IMAP. L’Internet Message Access Protocol (IMAP) è l’altro protocollo utilizzato per ricevere email
da un server di posta. È un protocollo più moderno rispetto a POP, ed è stato esplicitamente
sviluppato per facilitare la gestione di una stessa casella di posta elettronica da parte di più
dispositivi. La differenza principale rispetto a POP è che i messaggi di posta elettronica non vengono
eliminati automaticamente dal server anche se sono stati già recapitati ai rispettivi destinatari a
seguito di una loro richiesta, ma devono essere eliminati esplicitamente dall’utente, se lo desidera.

FTP. Il File Transfer Protocol (FTP) è un protocollo che permette il trasferimento di un qualunque
file da un computer ad un server e viceversa. È uno dei protocolli più adottati di Internet per
permettere lo scaricamento di una grossa mole di dati, mentre è poco adatto per scaricare documenti
molti piccoli, come pagine web.

5. Scenario completo di richiesta di una pagina web

La spiegazione del protocollo TCP permette di comprendere a pieno cosa succede davvero quando si
clicca su un link ipertestuale di una pagina web, la nostra domanda iniziale – che è stata la scusa per
poter parlare di tutte le tecnologie principali di Internet e del Web. L’esempio completo è mostrato
in Figura 6.

Quando un utente, attraverso il browser sul suo computer collegato a Internet (e, per questa ragione,
identificato da uno specifico indirizzo IP, ad esempio 79.40.124.122), clicca su un collegamento
ipertestuale della pagina che sta navigando, quello che in realtà succede è richiedere delle
informazioni associate ad uno specifico URL in qualche modo incapsulato in quel link – ad esempio
http://es.it/doc1. Il browser interpreta questa richiesta, e prepara un pacchetto HTTP contenente il
messaggio di richiesta, suddiviso in un header contenente informazioni sulla richiesta e un payload,
che in questo specifico caso è vuoto.

A partire dall’informazione relativa all’host (la parte es.it dell’URL), viene demandato al DNS
resolver il compito di recuperare l’indirizzo IP del server web che dovrebbe contenere informazioni
sulla risorsa identificata dall’URL della richiesta, così da poterla instradare correttamente in rete.
Una volta recuperata questa informazione (nell’esempio 130.136.130.1), e capito (in qualche modo
più o meno automatico) quale sia il massimo volume di dati per pacchetto che la rete può instradare,
si iniziano a preparare i vari pacchetti per la comunicazione.

Lo strato di trasporto è responsabile per la creazione dei pacchetti TCP. Una volta effettuato il three-
way handshake per iniziare la comunicazione con il server web, il messaggio HTTP viene
frammentato (se serve) e incapsulato nel payload di uno o più pacchetti TCP, che specificano
nell’header un numero di sequenza che verrà usato poi dal server web per ricostruire il messaggio
HTTP originale nel caso in cui i frammenti non pervengano nell’ordine corretto. La dimensione di
ogni pacchetto TCP è già conforme alla Maximum Transmission Unit (MTU) della rete su cui i
pacchetti verranno instradati.

A questo punto, i pacchetti TCP vengono presi in carica dallo strato di rete, che li incapsula
nuovamente all’interno del payload di altrettanti pacchetti IP, che nell’header specificano l’indirizzo
IP di computer mittente e l’indirizzo IP del server web destinatario del messaggio, quest’ultimo
recuperato in precedenza grazie al DNS. Fatto ciò, i pacchetti vengono instradati (passando dallo
strato di accesso alla rete) al router più vicino, e successivamente ai vari router presenti in Internet
in modo da poter essere recapitati al server web.

Lo strato di rete del server web riceve i pacchetti IP, ne estrae il payload (ovvero, i relativi pacchetti
TCP) e lo passa così com’è allo strato di trasporto. Lo strato di trasporto interpreta l’header, e in
particolare il numero di sequenza dei pacchetti TCP, in modo da ricostruire correttamente il
messaggio HTTP di richiesta, che viene poi passato allo strato di applicazione.
A questo punto, il server web, leggendo le informazioni contenute nell’header del messaggio HTTP,
cerca localmente il documento (nell’esempio, una pagina web) che corrisponde al percorso richiesto,
e specificato nell’URL iniziale. Una volta trovato, prepara un nuovo messaggio HTTP di risposta che
include, nel payload, una copia della pagina web richiesta.

Il messaggio HTTP di risposta viene passato allo strato di trasporto del server web, che incapsula
nuovamente il messaggio HTTP in uno o più pacchetti TCP della dimensione appropriata per essere
trasmessi correttamente in rete. A loro volta, come prima, i pacchetti TCP vengono passati allo
strato di rete, così da incapsularli in altrettanti pacchetti IP, che vengono poi instradati in Internet,
passando dallo strato di accesso alla rete, partendo dal router più vicino. Ovviamente, la connessione
TCP è già attiva, avendo fatto in anticipo il three-way handshake, e quindi non è necessario
ripeterlo. Inoltre, l’indirizzo IP e la porta su cui effettuare la comunicazione del mittente sono già
noti, essendo stati specificati nei pacchetti IP e TCP della richiesta iniziale.

Analogamente a quel che ha fatto il server web, il computer mittente ricostruisce il messaggio HTTP
di risposta, estraendo le informazioni rilevanti dai vari pacchetti IP e TCP ricevuti. Fatto ciò, il
payload del messaggio HTTP di risposta, ovvero la pagina web richiesta, viene estratta e visualizzata
sul browser – e, se serve, vengono fatte altre richieste HTTP per recuperare informazioni aggiuntive,
come le immagini o i video che di solito non sono contenuti nella pagina web ma sono solo riferiti
tramite i loro URL, come vedremo nel prossimo capitolo. Infine, la comunicazione TCP a livello di
trasporto viene chiusa utilizzando il four-way handshake.

CAPITOLO OTTO

1. Introduzione

Negli scorsi capitoli abbiamo visto nel dettaglio cosa succede dal momento in cui un utente clicca su
un link ipertestuale di una pagina web, a quando la pagina web indicata dal link stesso viene ricevuta
e poi visualizzata all’interno del browser. In questo capitolo introdurremo il linguaggio per
realizzare le pagine Web e tutti gli elementi che esse contengono: L’Hypertext Markup Language, o
HTML. Prima, però, è necessario fare una piccola deviazione per introdurre le teorie che sono alla
base di HTML, in modo da presentare cosa sia un linguaggio di markup e a cosa serve.
2. I linguaggi di markup

Nel primo capitolo di questo corso, quando abbiamo presentato per la prima volta la struttura dati
albero, abbiamo introdotto brevemente il concetto di marcatura del testo, ovvero l’annotazione del
testo così da definire esplicitamente i vari ruoli strutturali e semantici delle varie parti che lo
compongono, come l’identificazione delle sezioni, capoversi, dialoghi, etc. Riprendiamo nuovamente
l’esempio tratto dal primo capitolo di Alice’s Adventure in Wonderland di Lewis Carroll [Carroll,
1866]:

<<Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to
do: once or twice she had peeped into the book her sister was reading, but it had no pictures or
conversations in it, “and what is the use of a book,” thought Alice, “without pictures or
conversations?”

So she was considering in her own mind, (as well as she could, for the hot day made her feel very
sleepy and stupid,) whether the pleasure of making a daisy-chain would be worth the trouble of
getting up and picking the daisies, when suddenly a white rabbit with pink eyes ran close by her.>>

Come abbiamo già anticipato, tutte le strutture che annotano il testo (dialoghi, capoversi, capitoli,
etc.), mostrate in Figura 1 per l’esempio di cui sopra, sono organizzate per contenimento, dove la
struttura principale, chiamata book, è descritta da una sorta di scatola che contiene diverse scatole
più piccole chiamate chapter, una per ogni capitolo. Ognuna di queste, a sua volta, contiene altre
scatole chiamate paragraph, una per ogni capoverso, e così via. L’organizzazione a scatole appena
presentata descrive un albero (mostrato in Figura 2), dove la più grande (ovvero book) altro non è
che la radice dell’albero che contiene i vari chapter, e questi a loro volta contengono i paragraph, e
così via.

In modo da definire formalmente la marcatura relativa a un certo testo, sono stati sviluppati diversi
linguaggi di markup. Quelli che hanno maggiore rilevanza nel contesto del Web seguono una sintassi
specifica introdotta per la prima volta nello Standard Generalized Markup Language (SGML),
rilasciato nel 1986, e poi ripresa dal suo successore, l’Extensible Markup Language (XML), la cui
prima versione è datata 1996. SGML e XML sono, di fatto, metalinguaggi, ovvero definiscono le
regole sintattiche che devono essere seguite per specificare la marcatura di un testo, ma non
impongono alcun vocabolario particolare per il nome da assegnare ai vari marcatori – cosa che
invece viene poi fatta quando si definisce un linguaggio di marcatura vero e proprio basato su queste
regole sintattiche.

Conformemente alla sintassi di XML, con il termine elemento si denota il nome informativo che
esprime la semantica della porzione del testo al quale l’elemento si riferisce. Ogni elemento è
identificato da due etichette che delimitano il testo in esso contenuto, chiamati tag. In particolare, un
tag è una sequenza di caratteri che corrisponde al nome dell’elemento collocato all’interno di
parentesi angolari “<” e “>”. Come mostrato in Figura 3, per ogni elemento esistono sempre due tag:
il tag di apertura, che determina dove inizia l’elemento, e quello di chiusura, che determina dove
finisce l’elemento.

Inoltre, tutti gli elementi, nel loro tag di apertura, possono avere specificati degli attributi nella
forma nome_attributo="valore", come mostrato in Figura 4. Un attributo contiene delle informazioni
aggiuntive associate a quell’elemento che li specifica. Un elemento può avere nessuno, uno o più
attributi.

Infine, è possibile specificare dei commenti, ovvero delle informazioni opzionali che possono venire
inseriti in qualsiasi punto del documento marcato, ma non fanno parte effettiva del contenuto, sono
solo usati per fornire del contenuto informativo su determinate parti del contenuto. Grazie ai
commenti, specificati come mostrati in Figura 5, si possono inserire informazioni, ad esempio sui
marcatori utilizzati, sulla struttura e organizzazione del documento di markup.

Un esempio di documento marcato considerando le regole sintattiche appena introdotte e partendo


da quello mostrato in Figura 1 è il seguente:

<!-- Questo è l’elemento radice, che contiene tutti gli altri -->

<book language="english">

<chapter>

<paragraph>

Alice was beginning to get very tired of sitting by her

sister on the bank, and of having nothing to do: once or


twice she had peeped into the book her sister was reading,

but it had no pictures or conversations in it,

<quotation>“and what is the use of a book,”</quotation>

thought Alice, <quotation>“without pictures or

conversations?”</quotation>

</paragraph>

<paragraph>

So she was considering in her own mind, (as well as she

could, for the hot day made her feel very sleepy and

stupid,) whether the pleasure of making a daisy-chain

would be worth the trouble of getting up and picking the

daisies, when suddenly a white rabbit with pink eyes ran

close by her.

</paragraph>

<!-- Qui ci sono altri paragrafi -->

</chapter>

<chapter> <!-- Il contenuto del secondo capitolo --> </chapter>

<!-- Qui ci sono altri capitoli -->

</book>

Nella scrittura della marcatura di un documento, come in quella precedente, è buona prassi
utilizzare l’indentazione, ovvero l’uso di una sequenza di spazi, per far rientrare il testo quando ci
sono elementi contenuti (o annidati) in altri elementi. L’utilizzo di questa tecnica è molto utile,
siccome agevola la lettura della marcatura mentre la si sta scrivendo e, soprattutto, quando si devono
apportare eventuali modifiche e aggiornamenti.
3. Hypertext Markup Language (HTML)

L’Hypertext Markup Language (HTML) è una delle tecnologie fondamentali del Web, essendo il
linguaggio di markup usato per creare tutte le pagine web e le applicazioni presenti sul Web. Nella
sua ultima versione, è un linguaggio che segue una sintassi simile a quella XML presentata nella
sezione precedente, e che mette a disposizione uno specifico vocabolario di elementi ed attributi per
identificare i vari ruoli strutturali e semantici di una pagina web. In pratica, ogni qual volta viene
fatta una richiesta per una pagina web, viene restituita una copia di un documento HTML
contenente opportuni marcatori che il browser è in grado di interpretare e visualizzare a video in
qualche modo.

La prima versione di HTML, basata su SGML, è stata creata da Tim Berners-Lee nel 1990 in
concomitanza con la creazione del primo browser (WorldWideWeb, introdotto nel capitolo 4),
seppur la prima menzione pubblica del linguaggio avviene solo nel 1991. Dal 1994, le specifiche
delle varie versioni di HTML sono gestite direttamente dal World Wide Web Consortium (W3C),
un’organizzazione internazionale creata da Tim Berners-Lee volta a veicolare e gestire l’evoluzione
del Web e delle sue tecnologie.

Proprio in quegli anni, HTML inizia ad avere una fortissima diffusione in seguito ai primi utilizzi
commerciali del Web. Negli anni successivi, durante la cosiddetta prima guerra dei browser tra
Netscape e Microsoft, le definizioni di nuove specifiche del linguaggio HTML si susseguono,
rincorrendo le estensioni e le modifiche proposte dai produttori dei browser che cercano di
accaparrarsi quote di mercato.

Negli anni a venire, vengono rilasciate diverse versioni di HTML, fino ad arrivare alla versione 4.01
del 1999. Questa versione, nonostante i miglioramenti apportati dalle precedenti, era piuttosto
caotica: alcuni marcatori funzionavano soltanto su alcuni browser o su versioni specifiche di questi,
mentre le indicazioni per gestire gli errori di sintassi erano molto generiche e per nulla chiare. In
modo da ovviare a questo problema, il W3C decide di iniziare a lavorare ad una nuova versione di
HTML basata interamente sulla sintassi XML, chiamata XHTML, pubblicata ufficialmente nel 2000.
La versione di XHTML rilasciata migliora l'interoperabilità con altri linguaggi basati su XML della
stessa famiglia, come quello per creare immagini vettoriali (Scalable Vector Graphics, o SVG) e per
descrivere formule matematiche (Mathematical Markup Language, MathML), oltre che a offrire una
versione specifica per la telefonia mobile. Questi miglioramenti, seppur lodevoli, erano stati
introdotti sacrificando la piena compatibilità con HTML.

Al termine del W3C Workshop on Web Applications and Compound Documents del giugno 2004,
dopo una accesa discussione e successiva votazione, si decide (e solo per una manciata di voti) di non
mantenere la retrocompatibilità con le versioni precedenti nello sviluppo della nuova versione di
XHTML e, conseguentemente, con HTML stesso. Tuttavia, un gruppo di forti sostenitori di HTML,
scontenti del risultato del workshop e supportati dalle aziende principali produttori di browser in
circolazione (Apple, Mozilla Foundation, Opera Software, e Google), fonda il Web Hypertext
Application Technology Working Group (WHATWG) per proseguire il lavoro di miglioramento di
HTML al di fuori del W3C.

Il WHATWG inizia lo sviluppo di una nuova versione di HTML, più orientata allo sviluppo di
applicazioni Web così da rendere le pagine ancora più interattive. La comunità Web, inclusi i comuni
utenti fino alle aziende, preferiscono seguire la linea dettata WHATWG piuttosto che quella indicata
dal W3C, in particolare considerando che i siti web interamente basati su XHTML erano in larga
minoranza.

Il 27 ottobre 2006, Tim Berners-Lee ammette pubblicamente, nel post Reinventing HTML sul
proprio blog, di aver sbagliato nel perseguire in modo così netto lo sviluppo della nuova versione di
XHTML abbandonando completamente HTML, e annuncia la creazione di un nuovo gruppo di
ricerca orientato ad HTML e a quello che sta facendo il WHATWG. Da quel momento in avanti il
W3C e il WHATWG collaborano fino al 2011, ma continuano ad avere obiettivi inconciliabili. Da
una parte, il W3C vuole cristallizzare e pubblicare la specifica della nuova versione di HTML5
(quella in uso correntemente nel Web) in un documento ufficiale e definitivo, mentre il WHATWG
non vuole la pubblicazione di una specifica versione ma piuttosto un living standard in evoluzione
continua. La disputa si conclude con la pubblicazione di entrambi i documenti: il W3C con la sua
Recommendation, e il WHATWG con la sua specifica in costante aggiornamento.

4. Elementi HTML principali

Una pagina web è un documento HTML testuale che, attraverso il markup che specifica, permette la
strutturazione del contenuto della pagina, la creazione di link ipertestuali, e di riferimenti a
immagini e/o altri oggetti multimediali. Tutti questi oggetti marcati vengono interpretati dal browser
e visualizzate su schermo in modo appropriato.

Come anticipato, l’operazione di marcatura, o di tagging, è un’operazione che permette di associare


delle etichette, che definiscono determinati ruoli, alle varie parti del testo. Per portare un esempio,
potremmo immaginare di essere in una cucina con un blocco di post-it in mano, dove ogni post-it
ha una parola scritta sopra, ad esempio “frigorifero”, “caffè”, “zucchero”, “sale”, “mela”, “banana”,
“uva”, “corn-flakes”, “tavolo”, “sedia”, “forno”, etc. L’azione di etichettare ciascun oggetto della cucina
con il rispettivo post-it che lo descrive – associare all frigorifero blu il post-it “frigorifero”, alla mela
verde il post-it “mela”, e così via – è di fatto una marcatura a tutti gli effetti. Scrivere codice HTML
equivale a svolgere lo stesso esercizio, ma invece di etichettare oggetti e cibo presente in cucina, si
marca, con opportuni elementi identificati da un tag di chiusura e uno di apertura, il contenuto
testuale di un documento. Una cosa importante da notare è che i vari post-it descritti sopra hanno
etichette come “frigorifero” o “mela”, non “frigorifero blu” o “mela verde”. Questo perché i post-it
servono a descrivere il contenuto dell’oggetto etichettato, ma non a delinearne le sue caratteristiche
esteriori. In modo del tutto simile, gli elementi HTML permettono di descrivere il contenuto della
pagina, ma non danno indicazioni dirette su come questo contenuto deve essere presentato a video –
anche se c’è uno specifico linguaggio per fare questo chiamato CSS, che introdurremo alla fine di
questo capitolo.

Come anticipato, il vocabolario degli elementi e degli attributi che si possono usare per marcare un
documento è prestabilito da HTML ed è stato proposto per un uso abbastanza mnemonico. Ad
esempio, si usa l’elemento p per identificare un paragrafo, table per identificare una tabella, title per
identificare il titolo della pagina, ecc.
Struttura di base una pagina HTML

Paradossalmente, il primo elemento con il quale inizia un documento HTML non è un elemento
HTML, ma è la Document Type Declaration, che informa il browser su qual è la versione di HTML
che dovrà interpretare. In particolare, <!DOCTYPE html> è la dichiarazione che indica al browser
che il documento in questione utilizza le regole di marcatura di HTML5.

Il primo elemento, la radice dell’albero, di un documento HTML è html. Questo elemento contiene
tutti gli altri elementi che descrivono la pagina HTML. Tra i tanti attributi che si possono specificare
su questo (ma anche altri) elementi, esiste l’attributo lang, che viene usato per definire la lingua
principale dei contenuti della pagina HTML. Il valore dell’attributo lang è il codice della lingua
espresso da due caratteri [Phillips & Davis, 2006]. Alcuni esempi di codici espressi da due caratteri
sono “it” (italiano), “en” (inglese), “fr” (francese), e “es” (spagnolo). Ad esempio, se si vuol indicare che
il testo del documento HTML è in italiano, basta associare il valore “it” all’attributo lang contenuto
nel tag di apertura dell’elemento html: <html lang="it">.

L’elemento html contiene due elementi per distinguere due sezioni importanti della struttura base di
un documento HTML:

 head, le informazioni, tipicamente metadati (come title, il titolo del documento)


particolarmente utili all’indicizzazione della pagina HTML da parte dei motori di ricerca;
 body, il contenuto vero e proprio del documento (descritto da elementi come header, nav,
h1, article, section, div, p, a, img, video, table, ul, ol, etc.), che verrà visualizzato dal browser.

Per esempio, le strutture fondamentali che regolano l’organizzazione di un documento HTML, che
contiene l’estratto di Alice’s Adventure in Wonderland di Lewis Carroll mostrato precedentemente,
sono le seguenti:

<!DOCTYPE html>

<html lang="en">

<head>

<title>Alice’s Adventure in Wonderland</title>


</head>

<body>

<!-- il contenuto dell’estratto va qui -->

</body>

</html>

Il testo e la sua marcatura

Il contenuto testuale di un documento HTML può essere organizzato mediante l’uso di appropriati
elementi HTML, che veicolano una precisa semantica. Nelle prossime sottosezioni presentiamo i più
importanti.

Titoli

I titoli (heading) vengono usati per organizzano gerarchicamente il contenuto di un documento


HTML. I titoli sono definiti in ordine di importanza, dal più importante al meno importante: la
lettera h (iniziale del termine inglese heading) è seguita da un numero progressivo da 1 (più
importante) a 6 (meno importante), che vengono visualizzati dal browser con dimensioni diverse,
così da sottolinearne l’importanza, come mostrato in Figura 6.

Enfasi

Enfatizzare porzioni di testo in HTML si specifica mediante i seguenti due elementi:

 em (abbreviazione del termine inglese emphasized) leggera enfasi, visualizzata di default in


corsivo dal browser;
 strong (abbreviazione dei due termini inglesi strongly emphasized) enfasi forte, visualizzata
di default in grassetto dal browser.

Ovviamente, associare l’enfasi ad una parola o ad una sequenza di parole veicola anche un forte
significato semantico per il testo enfatizzato. Un esempio di come questi due elementi possono
essere utilizzati è mostrato di seguito, sempre riprendendo l’estratto del libro di Lewis Carroll già
presentato. Il modo in cui le enfasi sono mostrate sul browser è descritto in Figura 8.
Citazioni

HTML mette a disposizione tre differenti elementi per specificare le citazioni in un testo:

 cite descrive il titolo di un lavoro (libro, film, canzone, gioco, opera d’arte, rivista, ecc.) che
viene citato nel testo e, nel browser, viene tipicamente visualizzato in corsivo;
 q indica una citazione in linea inserita all’interno del paragrafo. Differenti versioni di
browser potrebbero visualizzare la citazione, marcata con l’elemento q, tra virgolette “…” o
sergenti «…»;
 blockquote indica una citazione situata come blocco a se stante rispetto al paragrafo. Il
browser di default indenta la porzione di testo racchiusa dall’elemento blockquote, ovvero dà
un rientro rispetto al resto del testo.

Il seguente frammento mostra l’uso di tutte e tre gli elementi HTML.

<p>

Riprendiamo nuovamente l’esempio tratto dal primo capitolo

di <cite>Alice’s Adventures in Wonderland</cite> di

Lewis Carroll:

</p>

<blockquote>

<p>

Alice was beginning to get <em>very tired</em> of sitting by

her sister on the bank, and of having nothing to do: once or

twice she had peeped into the book her sister was reading,

but it had no pictures or conversations in it,


<q>and what is the use of a book,</q>

thought Alice, <q>without pictures or

conversations?</q>

</p>

<p>

So she was considering in her own mind, (as well as she

could, for the hot day made her feel very sleepy and

stupid,) whether the pleasure of making a daisy-chain

would be worth the trouble of getting up and picking the

daisies, when suddenly a <strong>white rabbit</strong>

with pink eyes ran close by her.

</p>

</blockquote>

Liste

Una lista permette di organizzare dei frammenti di testo in forma di elenco ordinato secondo una
numerazione oppure non ordinato. In HTML esistono due elementi che permettono di creare una
lista:

 ol per la lista ordinata (acronimo dei termini inglese ordered list);


 ul per la lista non ordinata (acronimo dei termini inglesi unordered list)

Le singole voci della lista, sia ordinata che non ordinata, vengono indicate usando l’elemento li
(acronimo dei termini inglesi list item). In particolare, all’interno dell’opportuno elemento lista che
vogliamo usare, devono essere presenti tanti elementi li quanti sono le voci della lista che vogliamo
considerare. Ovviamente, gli elementi li possono contenere non solo testo, ma anche altri elementi
HTML.
Il frammento qua sotto mostra due liste, la prima ordinata che rappresenta l’indice dei capitolo del
libro Alice’s Adventures in Wonderland, mentre la seconda non ordinata elenca i vari personaggi che
compaiono nel libro. La loro visualizzazione su browser è mostrata in Figura 10.

<ol>

<li>Nella conigliera</li>

<li>Lo stagno di lagrime</li>

<li>Corsa scompigliata. Racconto con la coda</li>

<li>...<!-- altri capitoli --></li>

</ol>

<ul>

<li>Alice</li>

<li>Coniglio</li>

<li>Gatto del Cheshire</li>

<li>...<!-- altri personaggi --></li>

</ul>

Tabelle

In HTML, una tabella (elemento table) è composta da una sequenza di righe (elemento tr, per table
row), ognuna delle quali contiene una o più celle che possono essere di due tipi: celle contenenti dati
(td, per table data) o celle che definiscono intestazioni per le righe o le colonne identificate dalla
tabella (th, per table heading). Seppur la tabella sia organizzata in righe, ovviamente tutte le celle
nella medesima posizione di ogni riga identificano, in maniera astratta, una particolare colonna della
tabella, come mostrato in Figura 11.
L’esempio di seguito mostra una tabella di quattro righe, in cui la prima ha la funzione di
intestazione, contenente alcuni personaggi del libro Alice’s Adventures in Wonderland e il capitolo
dove appaiono per la prima volta. La visualizzazione della tabella è mostrata in Figura 12.

<table>

<tr><th>Personaggio</th><th>Capitolo</th></tr>

<tr><td>Alice</td><td>Capitolo 1</td></tr>

<tr><td>Coniglio</td><td>Capitolo 1</td></tr>

<tr><td>Gatto del Cheshire</td><td>Capitolo 6</td></tr>

</table>

Collegamenti ipertestuali

I collegamenti ipertestuali (o link) sono il meccanismo utilizzato per creare l’ipertesto che è sotteso
dalle varie pagine Web esistenti. Ogni risorsa sul Web, sia essa un documento HTML, un’immagine,
un video, un audio, etc., senza l’esistenza dei link sarebbe separata dalle altre risorse. L’intero Web,
definendo di fatto un ipertesto, si basa pesantemente sui link, che possono essere cliccati per
“navigare” verso un'altra pagina Web, un’altra sezione della stessa pagina Web, un’altra immagine, un
altro video, etc.

Il link definibile in HTML si compone di due parti principali:

 l’etichetta del link, ovvero quella porzione del contenuto cliccabile, solitamente evidenziata in
blu con una sottolineatura, che permette l’identificazione visuale del link sul browser;
 la destinazione, ovvero l’URL della particolare risorsa che si vuole “raggiungere” una volta
che si è cliccato sull’etichetta.

In HTML, l’elemento per creare un link è a (abbreviazione del termine inglese anchor, àncora in
italiano) accompagnato:

 dall’attributo href (abbreviazione dei due termini inglesi hypertext reference) che ne definisce
la destinazione;
 dal testo (e/o da altri elementi HTML) che contiene, che ne definiscono l’etichetta.

Ad esempio, il link alla versione di Wikisource del libro Alice’s Adventures in Wonderland,
introdotta negli esempi precedenti, può essere definito come segue (e viene visualizzato sul browser
come mostrato in Figura 13):

Riprendiamo nuovamente l’esempio tratto dal primo capitolo di <a


href="https://en.wikisource.org/wiki/Alice%27s_Adventures_in_Wonderland_(1866)"><cite>Alice’s
Adventure in Wonderland</cite> di Lewis Carroll</a>: …

Un link si dice interno alla pagina quando la sua destinazione è un’area dello stesso documento
HTML che lo definisce. In questo caso, per definire l’area precisa a cui si vuole arrivare a seguito di
un click su un link interno, bisogna usare l’attributo id, con valore una stringa alfabetico a piacere
(ad esempio id="capitolo_1"), sull’elemento HTML su cui si vuole arrivare a seguito del link. Fatto
questo, l’URL della destinazione include soltanto la parte dedicata al frammento, ovvero il carattere
# seguito dalla stringa associata al valore dell’attributo id dell’elemento a cui si vuole arrivare (ad
esempio <a href="capitolo_1">vai al primo capitolo</a>).

Multimedia

Le immagini – logo, fotografie, disegni, grafici, ecc. – sono parte importante di un documento
HTML. L’elemento HTML per specificare un’immagine è img, un elemento che non contiene alcun
testo ma che deve specificare i seguenti due attributi:

 src (abbreviazione del termine inglese source), il cui valore indica l’URL dove reperire il
l’immagine;
 alt (abbreviazione dei due termini inglesi alternative text) il cui valore indica un testo
alternativo mostrato al posto dell’immagine se quest’ultima, per qualsiasi ragione, non è
visualizzabile.

In modo analogo, l’elemento video usato insieme all’elemento source permettono di inserire un
video in un documento HTML. L’elemento source deve avere specificato l’attributo src che, come per
le immagini, si riferisce all’URL dove reperire il video.
Il contenuto di una pagina web

HTML permette di specificare le varie aree logiche di una pagina Web a seconda dei contenuti che
queste contengono. Per esempio, un documento può essere suddiviso in diverse sezioni, come la
testata, il piè di pagina, una barra laterale di navigazione, etc. In Figura 14 viene mostrato un
possibile modello per l’organizzazione delle varie parti di un documento HTML, in modo da rendere
meglio l’idea di quali sono le varie aree logiche che si possono utilizzare, e come si potrebbero
posizionare.

Gli elementi introdotti in Figura 14 sono i seguenti:

 l’elemento header contrassegna l’area della testata della pagina e raggruppa gli elementi
introduttivi e di ausilio alla navigazione, ad esempio il titolo del sito Web, il logo, il menu di
navigazione, il campo di ricerca, etc.:
 l’elemento footer individua l’area del “piè di pagina” dove si inseriscono informazioni sul
copyright della pagina, i contatti, l’anno di pubblicazione della pagina, etc.;
 l’elemento section rappresenta una sezione generica per organizzare, correlare e
contraddistinguere, da un punto di vista tematico, i contenuti. La sua funzione è simile a
quella dei capitoli di un libro o delle sezioni di una tesi di laurea. Al suo interno puoi avere,
ad esempio: articoli, titoli, paragrafi, liste, tabelle, immagini, video, audio, etc.;
 l’elemento article indica un blocco di contenuto indipendente dal contesto nel quale si trova,
un’entità a sé stante e collocabile anche in un’altra posizione. Il significato semantico
dell’elemento article è inteso in senso ampio: un insieme di informazioni che abbiano un
significato compiuto e che non necessitano di altri elementi per essere comprese. Il
contenuto del blocco marcato con article può essere l’articolo di una rivista o di un
quotidiano, il post di un blog, o, più in generale, un qualsiasi blocco di contenuto che sia
indipendente e abbia un significato proprio anche se estratto dal contesto della pagina.
 l’elemento nav individua l’area con i link (o voci) che guidano l’utente nella navigazione del
sito Web;
 l’elemento aside individua l’area i cui contenuti sono in parte in relazione, arricchiscono o
approfondiscono, i contenuti principali, ad esempio i link di navigazione secondari, i banner
pubblicitari, le categorie di un blog, etc. Solitamente tale area è posizionata a lato, per questo
è chiamata anche “barra laterale”, ma nulla vieta di posizionarla in altre aree.
5. Separazione tra markup e presentazione: i CSS

Nel 1996 viene rilasciata per la prima volta la specifica del Cascading Style Sheet (CSS), ovvero un
ulteriore linguaggio che permette di definire il livello presentazionale degli elementi di HTML. I CSS
definiscono l’aspetto grafico dei documenti HTML, ad esempio permettendo di specificare:

 il colore e la dimensione del testo contenuto nei titoli e nei paragrafi;


 la posizione di sezioni, articoli, immagini o video;
 l’animazione dinamica quando si posiziona il cursore del mouse su una voce del menu e/o
sui link

CSS è stato creato per permettere la netta separazione tra la struttura del contenuto, definito dagli
elementi del documento HTML, e come questo contenuto deve apparire o essere visualizzato sul
browser, definito dal CSS. Ogni documento CSS è descritto usando uno specifico linguaggio con una
sintassi completamente diversa da HTML. In particolare, CSS permette di definire un insieme di
proprietà presentazionali (colore, font, posizione, ecc.) su determinati elementi HTML. Ad esempio,
per assegnare il colore grigio e l’allineamento giustificato a tutti gli elementi p (paragraph) della
pagina HTML basta definire la seguente regola:

p{

text-align: justify;

color: grey;

Nell’esempio, p è il selettore che si riferisce al relativo elemento HTML p. Il blocco delle regole o
dichiarazione di stile associate a quel selettore sono incluse tra parentesi graffe { }. All’interno delle
parentesi si possono indicare una o più coppie proprietà:valore (separate da dei punti e virgola) che
permettono di definire regole di visualizzazione degli elementi selezionati.

CAPITOLO NOVE
1. Introduzione

Al giorno d’oggi, l’uso delle tecnologie informatiche è estremamente pervasivo, visto che concilia,
regola, e scandisce ogni momento delle nostre attività quotidiane. Basti pensare a quante volte
accediamo a Internet in una giornata, guardiamo una pagina Web per una qualsiasi ragione (una
ricetta, una ricerca, etc.), accediamo ai social network, scambiamo messaggi con amici attraverso
applicazioni come WhatsApp e Telegram, e chi più ne ha più ne metta.

Lo studio delle materie umanistiche non fa eccezione. Il processo di digitalizzazione di artefatti fisici
– come lettere, carteggi, libri, archivi – in documenti digitali ha reso possibile il loro accesso e
studio in modo totalmente remoto, senza necessariamente recarsi nel luogo dove l’opera viene
custodita ma richiedendola in digitale – un esempio di questo genere è l’archivio di Giovanni
Pascoli.

In questo capitolo conclusivo, verrà fornita una breve panoramica dei vari progetti e/o branche di
ricerca che coinvolgono l’utilizzo diretto di tecnologie informatiche. Un più esaustivo trattato su
questi temi è reperibile in [Drucker et al., 2014], su cui questo capitolo è basato.

2. Progetti digitali relativi a studi sulle scienze umane

Tutti i progetti digitali che riguardano le scienze umane hanno delle caratteristiche comuni. In primo
luogo, ognuno di essi mette a disposizione una piattaforma, solitamente Web, che permette di
usufruire del contenuto digitale del progetto e di presentarlo al pubblico. La scelta della piattaforma
da usare, ovviamente, va in base alla particolare esigenza del progetto in considerazione. Esistono
strumenti generalisti, come WordPress o MediaWiki (si veda, ad esempio, la Figura 1), che possono
essere utilizzati facilmente in diversi contesti. Altri strumenti invece, più specialistici, come Omeka S
e ResearchSpace [Oldman & Tanase, 2018] (si veda, ad esempio, la Figura 2), sono stati sviluppati da
studiosi delle scienze umane per scopi molto più specifici e settoriali, come la pubblicazione di
collezioni digitali relative al patrimonio culturale conservato nei musei o nelle biblioteche.

Una volta decisa la piattaforma da usare, un qualunque progetto di questo genere deve, di fatto:
 gestire delle risorse digitali, ad esempio un insieme di documenti salvati in uno o più file in
un certo formato;
 organizzare queste risorse in modo strutturato e informativo, così da essere facilmente
interpretabili non solo dagli esseri umani ma anche da agenti software intelligenti;
 permettere l’accesso a queste risorse così da fare ricerche e studi specifici su di esse, ed
eventualmente rispondere a determinati quesiti usando le informazioni a disposizione;
 visualizzare appropriatamente a video le informazioni rilevanti e di rilievo per una specifica
ricerca, così da rendere l’esperienza di navigazione tra le varie risorse messe a disposizione
dalla piattaforma efficace ed efficiente.

Queste caratteristiche sono di fatto comuni in tutte queste tipologie di progetti, che poi sono
declinati in modo appropriato a seconda della tipologia di risorse digitali gestite e della piattaforma
che meglio si confà alla loro pubblicazione.

3. Markup ed edizioni digitali

La codifica e l’analisi dei testi, siano essi letterari o no, è una delle attività principali dell’umanista.
Acquisire competenze relativamente alle tecniche e alle problematiche relative alla creazione e alla
disseminazione di documenti elettronici e di archivi digitali testuali è un componente caratterizzante
un qualsiasi percorso di studi umanistico. In questo contesto, diventa fondamentale conoscere i
meccanismi per rappresentare il testo digitale ed etichettarne le varie parti con opportuni marcatori.
Nel capitolo precedente abbiamo visto uno specifico linguaggio di markup, HTML, particolarmente
adatto alla pubblicazione su Web. Tuttavia, non è il solo linguaggio di markup a disposizione ed
efficacemente usato per la rappresentazione di testi digitali anche complessi.

Per esempio, Text Encoding Initiative (TEI) è uno dei più famosi linguaggi di markup usati per la
rappresentazione di testi letterari e per la creazioni di edizioni digitali. Negli ultimi anni, diversi
progetti hanno adottato TEI come linguaggio primario per la codifica di testi antichi in formato
digitale – ad esempio si veda il progetto della Bodleian Library di Oxford sul First Folio di
Shakespeare, mostrato in Figura 3.

TEI viene anche usato per alcune delle principali attività della filologia, come la ricostruzione della
forma originaria di un testo attraverso l’analisi delle fonti che lo testimoniano, o la creazione di
edizioni critiche, dove si mettono a confronto due varianti dello stesso testo. Questa attività di
marcatura, se supportata da strumenti visuali che facilitano la creazione della versione digitale delle
varianti in considerazione, risulta particolarmente efficace ed efficiente per un’analisi qualitativa di
queste varianti – per esempio, si veda il PhiloEditor [Italia et al., 2015], mostrato in Figura 4.

4. Collezioni di dati

Oltre ad un documento testuale, esiste un’altra tipologia di entità di cui si sente spesso parlare in
diversi contesti, senza mai darne una definizione precisa, ovvero il concetto di dato. La parola “dato”
deriva dalla parola latina “datum” che significa “cosa data”. Seppur intuitivamente tutti parliamo di
dati, una definizione formale di cosa sia un dato potrebbe essere la seguente: una frase dichiarativa
soggetto-predicato-oggetto che attribuisce ad una entità (il soggetto), attraverso il predicato, un
valore o la mette in relazione con un’altra entità (l’oggetto). I dati possono essere rappresentati in
svariate forme, ma la forma più comune è quella tabellare, tipica dei programmi come Excel, per fare
un esempio. Nel caso delle tabelle, ogni riga in qualche modo contiene dati su una certa entità,
mentre ogni singola cella, accoppiata con l’etichetta associata alla colonna a cui la cella si riferisce, di
fatto definisce un dato. Prendiamo per esempio i dati in Tabella 1. Ogni riga della tabella, eccetto la
prima che ha la funzione di intestazione, definisce una particolare persona, un musicista in questo
caso. In particolare, il musicista definito nella prima riga (il nostro soggetto) ha come nome “John” (il
primo dato), come cognome “Lennon” (il secondo dato), e come genere “maschio” (il terzo dato).
Seguendo l’approccio soggetto-predicato-oggetto introdotto in precedenza, possiamo definire questi
tre dati anche come segue:

1. il musicista identificato dalla prima riga (soggetto) ha nome (predicato) John (oggetto);
2. il musicista identificato dalla prima riga (soggetto) ha cognome (predicato) Lennon (oggetto);
3. il musicista identificato dalla prima riga (soggetto) ha genere (predicato) maschio (oggetto).

Quando si ha un grande insieme di dati, organizzati in forma tabellare come mostrato in Tabella 1 o
in qualche altro modo, è possibile organizzarli all’interno di una base di dati. Una base di dati altro
non è che una collezione di dati organizzati secondo determinati criteri che ne abilita l’accesso
mediante opportuni linguaggi di interrogazione che permettono, per esempio, di restituire dati che
forniscono risposte a domande come “quali sono i musicisti maschi che si chiamano John?”.
Le basi di date ormai sono strumenti abbastanza pervasivi non solo nel contesto di domini
nativamente digitali, ma anche nelle scienze umanistiche. I dati relativi ai libri posseduti da una
biblioteca, interrogabili attraverso un computer, così come la descrizione di oggetti museali messi a
disposizione su un sito Web, sono tutti contenuti in opportune basi di dati, così da facilitarne
l’interrogazione e lo studio. Per esempio, Il progetto Zeri & LODE [Daquino et al., 2017] (mostrato
in Figura 5) mette a disposizione una significativa base di dati, collegati tra loro e con entità esterne
contenute in altre basi di dati, come Wikidata e GeoNames, su fotografie di opere d’arte relative alla
pittura italiana del XVI secolo collezionate nel tempo dal famoso critico d’arte Federico Zeri e
conservate dalla Fondazione Federico Zeri dell’Università di Bologna.

Un altro esempio rilevante in questo settore è il progetto ArCo, Architettura della Conoscenza,
mostrato in Figura 6, dalla collaborazione con il Centro Nazionale delle Ricerche (CNR) e l’Istituto
Centrale per il Catalogo e la Documentazione (ICCD). Il progetto ha pubblicato sia svariati modelli
concettuali per la descrizione dei dati relativi a beni culturali materiali e immateriali – incluse le
loro schede catalografiche, gli eventi che coinvolgono i beni culturali, e la loro localizzazione
geografica e amministrativa – sia larghe collezioni di dati su questi beni culturali presenti in Italia.

5. Conclusioni

In questo capitolo abbiamo voluto fare, come chiusura del corso, una piccola e assolutamente non
esaustiva panoramica dell’utilizzo delle tecnologie informatiche per studi e ricerche attinenti alle
scienze umane. Nell’intenzione degli autori, lo scopo di questa digressione era quello di mostrare
alcuni esempi concreti di applicazioni e progetti sviluppati in questo senso, così da rendere noto al
lettore il fatto che, al giorno d’oggi e contrariamente a quel che avveniva ancora una ventina di anni
fa, risulta praticamente impossibile non considerare le tecnologie informatiche nell’approccio allo
studio di materie e argomenti prettamente umanistici. In questo contesto, l’informatica e il pensiero
computazionale non devono essere visti come oggetti ostili, ma piuttosto come strumenti non solo
utili ma fondamentali per uno studio completo, appropriato ed efficace delle discipline umanistiche.

Potrebbero piacerti anche