Giovedì 29 Giugno 2006

- Sezione 4 - Dal 1946 al 1979 - Temi principali

Software

Dopo un lungo percorso che vede lo sviluppo della matematica e la comparsa delle scienze della natura (fisica, chimica, biologia, medicina) la logica si caratterizza sempre più come proprietà formale (cioè del linguaggio scritto!)

Con la crisi della fine dell’ottocento (descritta nella sezione precedente) inizia un percorso che si conclude verso la metà del novecento con la comparsa di una grande innovazione: i linguaggi di programmazione; pur essendo legati indissolubilmente alla nascita e all’evoluzione del computer, hanno in realtà una profonda autonomia: per indicare tutte le problematiche e i prodotti relativi si usa la parola software, coniata in opposizione (ed analogia) ad hardware.

Compaiono subito due ordini di problemi:

  • come risolvere un problema specifico con un computer: software applicativo;

  • come usare in maniera efficiente le risorse di un computer (nella soluzione di problemi): software di base.

IL SOFTWARE DI BASE

Nell’uso dei computer (a programma memorizzato) occorreva introdurre programma e dati nella memoria: all’inizio lo si faceva attraverso la console, una apparecchiatura che mostrava il contenuto (in forma binaria) di ogni cella di memoria e permetteva di variarlo; era un processo lungo, soggetto ad errori e occupava la maggior parte del tempo di funzionamento del computer, impedendogli di svolgere il “suo” lavoro da elaboratore; inoltre era laborioso ottenere i risultati (che rimanevano nella memoria e dovevano essere “letti” attraverso la console. Furono intraprese due strade (parallele):

  1. una consisteva nel progettare un programma (sempre residente in memoria) con lo scopo di acquisire in maniera rapida i programmi e i dati che risolvevano i problemi e di rendere facilmente disponibile i dati all’esterno;

  2. l’altra nel progettare linguaggi che permettessero di descrivere “facilmente” il procedimento per la soluzione dei problemi e fossero “facilmente” trasformabili nella forma che doveva essere trasferita nella memoria del computer.

La prima strada ha dato origine ai sistemi operativi, la seconda ai linguaggi “assemblatori” (e ai compilatori).

Il primo compito dei sistemi operativi è stato quello di permettere ai computer di risolvere un problema e di mettere i risultati a disposizione senza “perdere tempo” nel passaggio da un problema a un altro: quello che aposteriori è stata chiamata “monoprogrammazione”.

Con l’aumentare della difficoltà e della dimensione dei problemi da risolvere non era più possibile che i dati (e i risultati) fossero tutti (contemporaneamente) nella memoria (del computer): occorreva acquisirli da una memoria esterna; il secondo compito dei sistemi operativi fu quello di “assistere” i programmi a fare questo scambio (traducendo i dati dalla rappresentazione esterna a quella “interna” e im­pe­dendo al programma di dover conoscere i dettagli del funzionamento del supporto esterno): era nato il cosiddetto filesystem (che risolve anche il problema della visualizzazione dei risultati, trattando le stampanti in maniera “uniforme” alle memorie esterne).

Già verso il finire della seconda generazione, però, con l’aumento della velocità di elaborazione, si poneva di nuovo lo stesso problema: il computer era inattivo per lunghi periodi di tempo poiché la velocità di scambio dei dati con la memoria esterna era incomparabilmente più lento della capacità di elaborazione; nasce così la “multiprogrammazione”, cioè sistemi operativi che sanno gestire più programmi in memoria, facendo eseguirne uno mentre per gli altri si stanno scambiando i dati con l’esterno. Nasce e si affina così il concetto di task (compito) e multitasking cioè la capacità di eseguire più task (dando l’impressione che siano eseguiti contemporaneamente). Compaiono in rapida successione il timesharing (a ogni programma viene garantito una certa percentuale dell’unità di tempo in cui può essere eseguito) e il realtime (certi programmi predeterminati sono eseguiti ogni volta che si verifica un certo evento, in modo da “reagire” appropriatamente agli stimoli esterni).

La caratteristica, però, che ebbe più impatto sul mercato (e sulle applicazioni riguardanti i sistemi informativi) fu la diffusione dei (sotto)sistemi transazionali che permettono a una comunità di utenti di utilizzare e modificare in maniera prestabilita una vasta quantità di informazioni; dal punto di vista tecnico erano una combinazione (attenuata) delle due caratteristiche appena viste.

La maggior parte di questi concetti fu messa a punto in due sistemi operativi che non ebbero rilevanza commerciale: Multics (iniziato al MIT nel 1964 e terminato alla fine degli anni ’70) e THE (messo a punto a Eindhoven, Olanda, nel 1968).

Alla fine degli anni ’60 iniziò, per reazione alla complessità di Multics, l’elaborazione di Unix, destinato ad essere l’esemplare più famoso e longevo di sistema operativo.

Agli inizi degli anni ’60 comparve la memoria virtuale: il concetto è quello di avere una memoria illimitata, che solo all’occorrenza viene “realizzata” (dal sistema operativo) nella memoria realmente esistente del computer; viene sfruttato in sistemi commerciali dalla IBM e diventa uno standard dalla quarta generazione.

Si sviluppa il software per gestire le telecomunicazioni: sia il colloquio tra diversi mainframe sia tra uno di questi e i terminali. Si diffondono varie convenzioni: nel 1974 viene ideato TCP che nel 1978 diventa TCP/IP e verso la fine del periodo diventa uno standard adottato da ARPA.

Ogni (tipo di ) computer (hardware) ha le sue regole con cui deve essere preparata la successione di operazioni e dati che costituiscono il programma che può eseguire: tali regole sono genericamente chiamate “linguaggio (della) macchina”. Un passo fondamentale fu l’idea di scrivere (nel modo appena detto) per ogni (tipo) di computer un solo (!) programma, detto assemblatore, che leggesse dei dati, li trasformasse opportunamente e li lasciasse nella memoria, in modo da essere interpretati come programma. Naturalmente i “dati” che l’assemblatore leggeva avevano una struttura tale da essere “facilmente” preparati da un operatore umano (per risolvere un problema), ma anche da essere facilmente tradotti nel programma eseguibile (da parte del computer). Questi linguaggi simbolici per descrivere la soluzione dei problemi sono detti assembler.

Gli assembler, per quanto più semplici da usare rispetto al linguaggio della macchina, già dall’inizio avevano due difetti (resi più gravi con l’aumentare del numero e della complessità dei problemi che hardware sempre più potenti permettevano di risolvere):

  • richiedevano comunque una approfondita conoscenza della particolare macchina su cui il problema veniva risolto,

  • non erano trasportabili da un computer ad un altro.

IL SOFTWARE APPLICATIVO

I linguaggi di programmazione, cioè i modi di descrivere la soluzione dei problemi, si evolvono in questo periodo essenzialmente per rendere agevole la soluzione di classi problemi, cioè in vista della efficienza del processo intellettuale di soluzione di un problema (la stesura del programma, appunto) a scapito della soluzione effettiva (l’esecuzione del programma); a metà degli anni ’50 compare, ad opera di John Backus il Fortran (FORmula TRANslation) orientato alle applicazioni scientifiche e alla fine del decennio, sotto la spinta del Pentagono, il Cobol (COmmon Business Oriented Language) per le applicazioni gestionali (fino a verso il 2000 è il linguaggio più usato). Contemporaneamente nasce la riflessione e lo studio teorico sui linguaggi (la loro sintassi e semantica) che culmina nella messa a punto dell’Algol (ALGOrithmic Language) tra il ‘58 e il ‘60.

Dopo circa un decennio compaiono altri due linguaggi destinati ad avere una grande diffusione: il C, una sorta di linguaggio assembler che fa riferimento a una macchina ideale (quindi svincolato dal particolare hardware) e il Pascal (da parte di Niklaus Wirth) che è una semplificazione estremamente efficace e duttile dell’Agol.

Nel frattempo si approfondisce la riflessione sui linguaggi: vengono individuati i “paradigmi di programmazione”, cioè le maniere “essenzialmente differenti” di descrivere la soluzione dei problemi. Tutti i linguaggi finora elencati vengono riconosciuti come una estensione del linguaggio macchina e battezzati “imperativi” o “procedurali”; si delineano altri tre paradigmi: funzionale, riconosciuto in un linguaggio apparso alla fine degli anni ’50 il Lisp (LISt Processing ad opera di John McCarty)), ad oggetti (Simula negli anni ’60 e Smalltalk negli anni ’70) e logico o dichiarativo (Prolog, PROgrammation en LOGique messo a punto da Alan Colmerauer e Robert Kowalski agli inizi degli anni ‘70).

Agli inizi la programmazione era considerata un compito altamente specializzato che richiedeva conoscenze sia dell’hardware sia dei problemi da risolvere; con il diffondersi, negli anni ’60, dei linguaggi di programmazione (imperativi) l’attenzione si concentrò, per i problemi scientifici, sulla conoscenza specifica: si viene a identificare cosi lo studio degli algoritmi (che si occupa delle procedure di carattere generale non numeriche) e quello della complessità (che si occupa del numero di “operazioni” intrinsecamente necessarie la soluzione di un problema). D’altra parte la enorme diffusione di applicazioni non scientifiche, segnata dallo sviluppo del COBOL e dalla costruzione di computer sempre più potenti, richiede un grande numero di programmatori le cui competenze sembrano limitarsi alla conoscenza del linguaggio (essendo semplici quelle dei problemi).

Alla fine degli anni ‘60 comincia ad essere evidente la incongruenza, da una parte, tra la stabile crescita della potenza delle macchine e del numero dei programmatori e, dall’altra, la incapacità di risolvere, in tempi, costi e qualità prevedibili il gran numero di problemi, apparentemente semplici, posti dai sistemi informativi. È la cosiddetta crisi del software, che si “risolve” dopo un lungo percorso di oltre un decennio, con l’affermarsi della programmazione come disciplina autonoma insegnabile (e distinta dalla teoria degli algoritmi e dalla conoscenza dei linguaggi). Un ruolo di rilievo viene svolto da Edsger Dijkstra e Michael Jackson che, nel corso degli anni ’70, fissano le regole della cosiddetta “programmazione strutturata” cioè il modo “corretto” e (in qualche modo) riproducibile di usare i linguaggi procedurali: da questo riceve grande impulso la diffusione delle applicazioni.

Le applicazioni della informatica abbracciano, in questo periodo, uno spettro vastissimo della “elaborazione di dati”: da quelle prevalentemente scientifiche in cui l’accento è (inizialmente !) sulla elaborazione (studio degli algoritmi e della complessità) a quelle di tipo gestionale in cui l’accento è su(lla grande quantità d)i dati. Per fronteggiare questi ultimi problemi (in un periodo sostanzialmente contemporanea alla crisi del software e alla sua soluzione) è sempre più sentita la necessità, detta astrazione (dei dati), della separazione tra la descrizione dei dati (inerente ai problemi) e i particolari della loro registrazione sui supporti di memori esterni (inerente alla tecnologia hardware). Si afferma, verso la fine degli anni ’70, il concetto di data base, come contenitore in cui esistono separatamente i dati e la descrizione dello loro struttura.

Si delineano tre modelli di data base: gerarchico (molto usato fino alla fine degli anni ’80), reticolare (mai veramente implementato) e relazionale (ideato da Edgar Codd nel 1970 e implementato solo verso la fine del periodo e, comunque, in maniera sempre poco fedele alla definizione originale).

Home Tour virtuale Sezione 4 Temi principali