Una delle caratteristiche peculiari dei Sistemi di Calcolo, che ne ha accompagnato l'evoluzione sin dalle origini negli anni '40, é la complessità. Tale caratteristica si riperquote in diverse attività di un "informatico" quali la progettazione, realizzazione, uso, comprensione di un sistema di calcolo.
Al fine di poter trattare sistemi molto complessi, gli informatici hanno sviluppato una serie di "contromisure", tra le quali la più efficace é la decomposizione in livelli di astrazione diversi. Tale decomposizione viene ottenuta normalmente attraverso l'introduzione dei concetti di Macchina Virtuale, Linguaggio e di Codifica delle informazioni.
Si possono dare delle definizioni matematiche rigorose di tali concetti. Definiamo l'alfabeto di una macchina virtuale come un insieme finito di simboli diversi tra loro riconoscibili ed utilizzabili dalla macchina virtuale. Il linguaggio della macchina virtuale é definito come la descrizione di tutte le sequenze di simboli dell'alfabeto che identificano dei comandi eseguibili dalla macchina virtuale o dei dati usati o prodotti dalla macchina virtuale durante l'esecuzione dei comandi.
Prima di addentrarci nello studio dei sistemi di calcolo con l'ausilio del concetto di macchina virtuale é utile fare qualche considerazione "di buon senso" basata sulla esperienza quotidiana di ciascuno di noi. É infatti importante comprendere che l'informatica ed i sistemi di calcolo non sono estranei alla vita quotidiana, e questo non soltanto perché una quota sempre maggiore di elettrodomestici e strumenti di uso comune fanno uso di tecnologie informatiche, ma anche perché molto spesso noi stessi ragioniamo in termini informatici (probabilmente senza neanche rendercene conto).
Cominciamo quindi a considerare un esempio dalla vita domestica: l'uso di una lavabiancheria per il bucato. Indipendentemente dalla presenza di un "microprocessore" all'interno della macchina (molto probabile in un modello recente), possiamo subito individuare una peculiarità di questo elettrodomestico di potersi adattare a diversi tipi di tessuti da lavare ed a diversi livelli di risultati in termini di bucato prodotto.
Tipicamente, dopo aver inserito il bucato ed il detersivo, dobbiamo girare una o più manopole (oppure premere pulsanti) per la scelta del tipo di lavaggio desiderato. Alternative tipiche possone essere: "Cotone", "Colorati", "Sintetici", "Lana", ecc. Tali nomi formano ciò che in termini informatici viene detto un "linguaggio" (nel nostro caso particolare si tratta di un linguaggio degenere che si riduce ad un semplice vocabolario) mediante il quale noi possiamo impartire ordini che verranno eseguiti alla lettera dalla macchina, senza alcun controllo "intelligente". Per esempio, se inseriamo nella macchina dei tessuti con colori delicati, e la programmiamo per l'attivazione di un ciclo di lavaggio adatto per lenzuola bianche, la lavabiancheria eseguirà l'ordine ricevuto riscaldando l'acqua alla temperatura di 90 gradi, con risultati disastrosi per il bucato. É compito dell'utilizzatore di impartire alla macchina ordini coerenti utilizzando il linguaggio di programmazione descritto sul manuale d'uso.
La comprensione del manuale d'uso e l'uso della lavabiancheria prescindono da come la macchina realizza effettivamente il lavaggio. Quando la nostra macchina si guasta, il tecnico della manutenzione che viene ad effettuare la riparazione userà delle descrizioni dello stesso elettrodomestico diverse dal manuale d'uso (schemi elettrici, catalogo delle parti, ecc.) per portare a termine la riparazione, evidenziando quindi un modo totalmente diverso di osservare e manipolare la stessa macchina (un diverso livello di astrazione).
Passiamo ad un esempio più complesso: il problema di procurarsi una pizza per mangiare. Possiamo anzitutto scegliere tra due alternative: cucinare la pizza in proprio, oppure recarsi in una pizzeria. Cominciamo ad esaminare la prima alternativa.
Per cucinare la pizza in casa occorre procurarsi gli ingredienti (acqua, farina, lievito, ecc.), la ricetta (per esempio da un libro di cucina), ed una serie di attrezzi per la realizzazione della ricetta (mattarello, tavolo, forno, ecc.). Una volta procurate tutte queste cose possiamo passare alla fase di preparazione, seguendo i passi descritti nella ricetta.
La ricetta farà uso di un linguaggio che noi dobbiamo essere in grado di comprendere correttamente e dovrà descrivere il procedimento di preparazione in termini di passi elementari che noi dobbiamo essere in grado di realizzare. Se per esempio la ricetta fosse scritta in dialetto napoletano noi dovremmo sapere che il termine "pummarola" indica la passata di pomodoro. D'altra parte, se leggendo la ricetta incontriamo l'istruzione "scaldare il forno", dobbiamo essere in grado di accendere il forno e portarlo alla temperatura corretta; le procedure possono essere diverse per un forno a legna, a gas o elettrico, e non é detto che una persona in grado di scaldare un forno elettrico sia capace di scaldare correttamente anche un forno a legna, nel qual caso avrebbe bisogno di istruzioni più dettagliate per poter portare a termine correttamente l'operazione.
In termini informatici, la realizzazione di una pizza seguendo passo passo le indicazioni di una ricetta costituisce una attività detta interpretazione da parte di una macchina virtuale (noi stessi nella fattispecie).
L'eventuale interruzione della interpretazione della ricetta al momento del riscaldamento del forno per andare a leggere su un altro manuale le istruzioni dettagliate di accensione e regolazione della temperatura, in termini informatici costituisce una estensione procedurale per sopperire ad una mancanza di corrispondenza precisa tra le istruzioni contenute nella ricetta (programma da eseguire) e l'insieme delle istruzioni che la macchina virtuale (noi stessi) conosce ed é in grado di eseguire direttamente. Al termine dell'interpretazione della procedura "scaldare il forno" la macchina virtuale può tornare all'interpretazione del programma principale, dal punto in cui l'aveva interrotto.
La seconda alternativa può risultare più dispendiosa ma anche più comoda, in quanto qualcun altro svolgerà il ruolo di macchina virtuale al posto nostro. Normalmente, in pizzeria l'interazione avviene con un cameriere, il quale assume agli occhi del cliente il ruolo di macchina virtuale.
Inizialmente, il linguaggio usato per la comunicazione tra cliente e cameriere sarà quello dei nomi delle pizze scritte sul menù ("margherita", "quattro stagioni", "napoletana", ecc.). Tale linguaggio può essere considerato ad alto livello, in quanto ogni parola corrisponde direttamente con una particolare esigenza dell'utilizzatore della macchina. Ordinando al cameriere "una quattro stagioni" noi comandiamo alla macchina virtuale pizzeria l'esecuzione di una attività complessa, il cui risultato é quello di far arrivare al nostro tavolo la pizza desiderata. L'utente tuttavia non é normalmente interessato ai dettagli di realizzazione della pizza, per cui si pone ad un livello di astrazione superiore e percepisce l'attività della macchina virtuale pizzeria come un tutt'uno che termina con il recapito della pizza desiderata al proprio tavolo dopo una certa quantità di tempo.
Il cameriere si pone invece ad un livello di astrazione inferiore per poter realizzare la macchina virtuale con le funzionalità richieste dal cliente sulla base delle macchine virtuali di cui lui stesso può disporre. Tipicamente il cameriere scriverà l'ordine su un pezzo di carta col duplice scopo di passare l'ordine al pizzaiolo e di tener traccia della consumazione per poter poi presentare il conto. Normalmente, per risparmiare tempo, userà delle convenzioni per codificare in forma abbreviata l'ordine ricevuto dal cliente; per esempio qualcuno potrebbe scrivere "4S" (al posto di "quattro stagioni"), qualcun altro potrebbe scrivere "X4", qualcun altro ancora potrebbe scrivere "2" (se il nome "quattro stagioni" compare al secondo posto nella lista dei nomi del menù, come nel nostro esempio).
Una volta trascritto l'ordine, il cameriere passa l'ordine al pizzaiolo e può dedicarsi al servizio di un altro tavolo, demandando quindi il completamento dell'esecuzione dell'istruzione ad un'altra macchina virtuale (per un produttore di automobili questa tecnica verrebbe chiamata "catena di montaggio", mentre gli informatici preferiscono usare il termine pipeline).
La macchina virtuale pizzaiolo interpreta gli ordini ricevuti dal cameriere mediante applicazione di una serie di passi elementari che ha imparato ad eseguire una volta per tutte e che ricorda in permanenza (stendere la pasta, aggiungere la passata di pomodoro, aggiungere la mozzarella, ecc.). In termini informatici, il pizzaiolo esegue una istruzione della sua macchina virtuale interpretando una sequenza di micro istruzioni presenti in una sua memoria permanente (firmware) ed univocamente associate a ciascun codice che il cameriere scrive sull'ordine.
L'esecuzione delle micro istruzioni può essere interrotta solo
nel caso si manifestino delle eccezioni (o trap),
ad esempio per esaurimento degli ingredienti o per mancato riconoscimento
del codice di un comando.
Il trattamento di una eccezione può comportare un ritardo nel completamento
dell'esecuzione del comando (per esempio chiedendo a voce al cameriere di
chiarire che tipo di pizza era stato richiesto, a causa della sua brutta
calligrafia) o l'aborto (col cameriere che torna dal cliente e si
scusa di non poter soddisfare l'ordine a causa dell'esaurimento dei carciofini).
Ragionando in termini puramente astratti possiamo quindi concludere che ogni istruzione del livello L5 (per esempio ogni istruzione del linguaggio Pascal) può essere descritta in termini di sequenze di istruzioni del livello L1. Questo é vero anche in termini pratici: potremmo pensare di monitorare e registrare il comportamento dei dispositivi fisici che compongono il sistema di calcolo al livello L1, ed associare una serie complessa di attività all'esecuzione di una singola istruzione di livello L5. Concettualmente potremmo quindi arrivare a concludere che la stratificazione proposta nella tabella non ha motivazioni teoriche per esistere, in quanto i programmi potrebbero essere scritti dal programmatore direttamente usando il linguaggio della macchina virtuale L1, invece del Pascal. Questo tentativo di "semplificazione" del problema é destinato a fallire miseramente in quanto non tiene conto di un vincolo fondamentale: il limite intrinseco alle capacità cognitive del programmatore destinato ad usare la macchina virtuale sistema di calcolo. Nessuno di noi riuscirebbe a raccapezzarsi nella descrizione di alcune decine o centinaia di migliaia di istruzioni elementari del livello di astrazione L1 corrispondenti a poche istruzioni di un programma Pascal per la somma di due numeri interi e la stampa del risultato.
Scopo della stratificazione in livelli di astrazione é dunque
quello di colmare il divario (semantic gap) tra il modo di
pensare alla soluzione dei problemi da parte del programmatore ed il modo
di realizzare delle macchine che sfruttando fenomeni fisici conosciuti
siano in grado di eseguire il programma che porta alla soluzione del problema.
Tale tecnica viene applicata più volte nel caso di soluzione di problemi
complessi: anche lavorando con una macchina virtuale di livello L5 il programmatore
può sentire la necessità (o sfruttare l'opportunità)
di definire una ulteriore stratificazione in livelli di astrazione diversi,
a cui corrisponde una pila di macchine virtuali destinate a colmare
il divario tra le istruzioni fornite dal linguaggio di programmazione
e il suo modo di risolvere concettualmente un problema complesso.