Fondamenti di Programmazione

I Computer e la Programmazione

Siamo così abituati ai computer che pervadono le nostre vite (desktop, portatili, smartphone, ipad, ecc.) che è facile dimenticare quanto siano stupefacenti. Sono macchine polivalenti (general-purpose): un computer può funzionare da word processor, da spreadsheet, può navigare nel web, inviare e ricevere email, tenere la contabilità, mostrare video, e diventare tantissime altre cose.

Applicazioni varie

Questo è possibile perché i computer sono programmabili. Ogni applicazione è un programma che "dice" al computer cosa fare: aprire una finestra, eseguire una certa computazione, rispondere agli eventi (click del mouse, tasti premuti, ecc.), salvare un file, ecc.

Immaginiamo per un attimo che i computer programmabili non siano mai stati inventati. Quasi tutte le applicazioni che usiamo abitualmente non esisterebbero, ad esempio, i web browser (anche perché Internet e il web senza i computer non potrebbero esistere). Le pochissime applicazioni rimanenti sarebbero delle macchine fisiche a sè stanti, ad esempio al posto dei word processor ci sarebbero delle macchine simili alle vecchie macchine da scrivere. Quindi sarebbero comunque molto meno versatili, meno utili e molto più costose ed ingombranti. Se i computer non esistessero l'Informatica stessa non esisterebbe. Sicuramente sarebbe un mondo piuttosto diverso, forse simile a quello immaginato nel film Brazil. Si pensi a tutti i sistemi critici gestiti e controllati dai computer e realtivi programmi. Sistemi per la diagnostica per immagini come la Risonanza Magnetica e la TAC usano il computer per controllare i segnali e formare le immagini che il medico può interpretare. Una moderna automobile ha decine di piccoli computer che controllano i freni e la stabilità dell'autovettura in varie situazioni. Lo stesso è vero per treni, barche, aerei, ecc.. E anche per infrastrutture come i sistemi per il controllo del traffico aereo, sistemi di gestione delle reti elettriche e delle reti telefoniche. I sistemi militari sono interamente dipendenti dai computer così come i sistemi finanziari mondiali.

L'aspetto essenziale e caratterizzante dei computer è quindi proprio l'essere programmabili. Ma cosa significa realmente? La programmazione di un computer è simile alla progettazione di un manufatto come un tostapane, una lavatrice, un'automobile, un ponte, un aeroplano, ecc. Un programma è il progetto di un'applicazione. La "costruzione" dell'applicazione avviene quando l'applicazione è eseguita. In questa analogia, il computer è la fabbrica che eseguendo il progetto (il programma) costruisce l'applicazione. Così il programma di un web browser è il progetto dell'applicazione stessa e quando si lancia il browser il computer lo "costruisce". Ovvero il computer stesso diventa, in un certo senso, il web browser.

C'è però una sostanziale differenza. Nel caso ad esempio di un'automobile, il passaggio dal progetto alla effettiva costruzione è molto più difficile. Richiede una vera fabbrica con attrezzature grandi e costose, materiali, molti operai e molto tempo. Ma anche per manufatti molto più semplici come un tostapane il passaggio dal progetto alla costruzione richiede atrezzature specializzate, materiali, tempo e denaro. Invece il processo di "costruzione" di un'applicazione (qualunque essa sia) è gratis e prende al massimo qualche secondo. Questa differenza è invero importantissima. Se un giorno avessi l'idea per un nuovo tostapane e avessi le competenze per tradurre l'idea in progetto avrei comunque il problema di costruire almeno un prototipo. E questo non è banale, dovrei affidarmi a qualche officina specializzata che magari costruirebbe anche il mio prototipo ma, essendo un pezzo unico, mi costerebbe assai. Se invece avessi l'idea per una nuova applicazione (una app) dopo averla progettata, ovvero dopo aver scritto il programma, il computer la "costruirebbe" immediatamente e gratis.

Dunque, la programmazione, cioè l'attività di scrivere programmi per il computer, è molto simile alla progettazione di un manufatto, però il passaggio alla effettiva costruzione, nel caso dei computer, è enormemente più facile. Le somiglianze tra la programmazione e la progettazione riguardano anche le difficoltà tipiche della progettazione, come ad esempio il dover considerare tutti i possibili usi e circostanze d'uso di un certo manufatto (o applicazione). E così come è molto più facile progettare un tostapane che un'automobile, è molto più facile programmare un text editor che un web browser. La programmazione di certe applicazioni molto complesse, come ad esempio, un web browser può essere difficile quanto il progetto di un aeroplano di linea o di un grattacielo di 150 piani.

Per fortuna, la programmazione aiuta se stessa. Nel senso che ci sono molti strumenti software (cioè, sempre programmi) che aiutano i programmatori: compilatori, interpreti (dei compilatori e interpreti ne parleremo più avanti), text editors specializzati, IDE (Integrated Development Enviroment), e tanti altri.

Programmazione

Questa è un'altra fantastica conseguenza della programmabilità universale dei computer. Si possono scrivere programmi che aiutano a scrivere programmi. Esistono e sono esistiti anche molto tempo prima dei computer macchinari programmabili. Ad esempio, il famoso telaio di Jacquard che fu inventato nei primi del 1800 e che permetteva di tessere complessi disegni, in modo automatico, tramite programmi su schede perforate. Però la programmabilità di tali macchinari era ed è molto specializzata, ad esempio ben difficilmente il telaio di Jacquard si può estendere per realizzare anche scarpe di diverse foggie determinate da opportuni programmi. Invece i computer godono di una programmabilità universale: qualsiasi computazione che può essere espressa in modo preciso e non ambiguo può essere programmata in un computer, se tralasciamo considerazioni pratiche come la velocità e i requisiti di memoria. Per inciso, attualmente i telai di Jacquard sono sostituiti da telai computerizzati, è difficile immaginare che possa essere accaduto il vicecersa, cioè, un computer realizzato tramite un telaio di Jacquard?. Questo risultato è stato messo in evidenza negli anni '30, prima quindi della realizzazione del primo computer programmabile accaduta negli anni '40, e va sotto il nome di tesi di Church-Turing.

Ricapitolando, un computer (cioè l'hardware) senza il software (i programmi) è una sofisticatissima macchina ma completamente inerte (ovviamente anche il software senza l'hardware è totalmente inerte). Il software dà "vita" al computer che può così diventare una varietà sterminata di macchine usate per svago, per comunicare, per lavorare, per studiare, per socializzare, per diagnosticare, ecc. La programmazione progetta e implementa il software, è simile alla progettazione di manufatti fisici e può essere altrettanto difficile. Però il computer "costruisce" i programmi in modo estremamente più facile di come avviene la costruzione dei manufatti. Una delle conseguenze di questo fatto è che i programmi tendono ad essere molto più complessi di progetti di manufatti. Per approfondire tale aspetto di possono leggere gli interessanti articoli di Jack W. Reeves. Un'altra conseguenza è che da molti decenni è in corso una controversia senza fine sulla questione se lo sviluppo software debba essere considerato o meno una disciplina ingegneristica, come le attività di progettazione di manufatti che sono tipicamente considerate discipline ingegneristiche. Strettamente connesso a tale controversia c'è anche un dibattito circa le migliori metodologie per lo sviluppo software che finora ha prodotto una serie interminabile di articoli e libri. Per fortuna questo è un corso introduttivo alla programmazione e non dovremmo occuparci di tali aspetti. D'altronde tutto ciò non è sorprendente, i computer programmabili sono le macchine più straordinarie e meravigliose che siano mai state inventate e la loro programmazione è una attività interdisciplinare, ricchissima di idee e potenzialità ma è anche stranamente misteriosa (come ogni programmatore esperto sa).

Prima di iniziare a parlare concretamente di programmazione conviene fare una breve panoramica circa l'organizzazione dell'hardware, la rappresentazione delle informazioni in un computer e una brevissima storia dei linguaggi di programmazione.

L'Hardware

L'organizzazione di un computer, da un punto di vista logico-funzionale, non è cambiata molto da quando è stata proposta con sorprendete chiarezza e preveggenza da John von Neumann nel 1945 e che è conosciuta con il nome appunto di architettura di von Neumann. Ma ecco qui sotto l'organizzazione di un tipico computer attuale:

Organizzazione dell'hardware di un tipico computer

Le due parti più importanti sono il processore centrale, o CPU (Central Processing Unit) e la memoria, o RAM (Random Access Memory). La CPU esegue i programmi e tramite essi governa e controlla l'hardware dell'intero computer. I programmi e i dati che i programmi necessitano per l'elaborazione sono mantenuti nella memoria. La CPU legge e scrive direttamente la memoria centrale. RAM è il nome generico di un tipo di tecnologia per le memorie, la memoria centrale comprende in realtà una gerarchia di memorie che oltre alla RAM vera e propria include memorie più piccole e veloci dette memorie cache. La CPU e la RAM sono connesse tramite una linea di comunicazione ad altissima velocità denominata bus di sistema. La RAM è una memoria volatile, cioè mantiene il suo contenuto solamente mentre il computer è in funzione. Il disco o i dischi sono memorie permanenti, dette memorie secondarie, che mantengono invece il loro contenuto anche quando il computer è spento. I contenuti della RAM possono all'occorrenza essere scritti su disco e viceversa i contenuti del disco possono essere caricati in RAM. Tramite i controllori hardware, i programmi in esecuzione sulla CPU possono essere "avvertiti" quando, ad esempio, il mouse è mosso o un suo bottone è premuto, quando un tasto delle tastiera è premuto o in generale quando un'azione è effettuata su un qualsiasi dispositivo di input connesso al computer. Così il programma può reagire allo stimolo esterno e ad esempio effettuare un'azione su un dispositivo di output, come ad esempio un monitor. Tutti i controllori o adattatori dei dispositivi di input/output sono connessi al bus di sistema tramite un altro tipo di bus detto bus di I/O.

CPU

La Memoria e i Dati

Come sono rappresentati i dati (o informazioni) in un computer? L'hardware "conosce" un solo tipo di dato elementare che è il bit (binary digit) capace di assumere solamente due stati 0 e 1. Quindi tutti i dati (numeri, testi, immagini, musica, video, ecc.) in un computer sono rappresentati tramite opportune sequenze di bit (ovvero sequenze di 0 e 1). Da qui anche l'uso dell'aggettivo digitale in riferimento a tutto ciò che può essere elaborato da un computer o trasmesso tramite una rete di computer. Quindi qualsiasi cosa che può essere rappresentata digitalmente, cioè tramite opportune sequenze di bit, può essere elaborata da un computer (o trasmessa tramite reti di computer come Internet).

Nella terminologia delle reti l'unità bit è tuttora usata per esprimere la velocità delle connessioni (cioè, il numero di bit che possono essere trasmessi in un secondo). Nei computer il bit è un'unità di informazione troppo piccola e si preferisce usare il byte che corrisponde a 8 bit consecutivi. byte è la contrazione di bynary octette, e in inglese significa morsetto, bocconcino. Un byte può assumere 256 stati, pari infatti a 2^8, cioè tutti i possibili stati di una sequenza di 8 bit. Un byte può rappresentare ad esempio tutti valori interi da 0 a 255. Inoltre un byte può rappresentare tutte le lettere dell'alfabeto sia maiuscole che minuscole, in totale 52, e tutte le cifre decimali, in totale 10, e molti altri caratteri come la punteggiatura, le parentesi, ecc. Bisogna solamente mettersi d'accordo sul codice da usare, cioè quali sequenze di 8 bit corrispondono ai diversi caratteri. Questo codice è stato introdotto molti decenni fa ed è ormai universalmente adottato, si tratta del codice ASCII (American Standard Code for Information Interchange). Ogni carattere alfabetico, numerico, di punteggiatura e alcuni altri è associato ad un codice univoco che numericamente è compreso tra 0 e 127. Il codice ASCII è stato pensato per l'inglese che ha la fortuna di non avere le lettere accentate e quindi non comprende quest'ultime. Purtroppo, non c'è un codice altrettanto universalmente accettato che estenda il codice ASCII anche alle lettere accentate. Esistono parecchi codici che estendono l'ASCII usando anche i codici tra 128 e 255 e che codificano le lettere accentate ma non sono compatibili fra loro.

La codifica di altri dati oltre i caratteri può prendere più di un byte. Ad esempio i numeri a seconda dell'intervallo dei valori e se interi o con virgola possono richiedere gruppi di 2, 4, 8, o più bytes. Altri dati più complessi sono codificati di solito concatenando la codifica di dati più semplici. Ad esempio, un testo è codificato tramite la sequenza di byte ognuno dei quali codifica un carattere del testo. Un immagine in alcuni tipi di codifiche (esistono tantissimi tipi di codifiche per le immagini, tiff, png, gif, ecc.) è la concatenazione delle codifiche dei singoli pixel che a loro volta sono codificati con tre numeri interi che rappresentano i valori dei colori RGB.

La memoria centrale può essere vista, da un punto di vista funzionale, come una lunghissima sequenza di byte. Ogni byte della memoria è accessibile tramite il suo indirizzo, il primo byte ha indirizzo 0, il secondo 1, il terzo 2 e così via. Quindi la CPU, ovvero un programma, può leggere o scrivere un qualsiasi byte della memoria.

Oggigiorno le memorie sono molto grandi e anche i dati da elaborare. L'unità di misura byte è troppo piccola così si usano delle unità più grandi: un kilobyte (KB) sono 1024 byte, un megabyte (MB) sono 1024 KB, un gigabyte (GB) sono 1024 MB, un terabyte (TB) sono 1024 GB (e si potrebbe continuare sempre per multipli di 1024 coi i petabyte e i zetabyte).

I primi PC apparsi negli anni '80 avevano 64KB di RAM e 750KB di floppy disk (senza hard disk). Un PC di oggi ha una RAM dell'ordine dei GB (quindi decine di migliaia di più dei vecchi PC) e dischi con capacità dell'ordine delle centinaia di GB o qualche TB.

La CPU e i Programmi

La memoria non contiene solamente i dati che devono essere elaborati ma anche i programmi. I programmi sono posti in una zona a loro riservata nella memoria. Un programma è una sequenza di istruzioni. Ogni istruzione rappresenta un comando che dice alla CPU cosa fare ed ha una sua codifica in termini di sequenza di byte. Le istruzioni che una CPU accetta sono molto elementari e appartengono ad un repertorio piuttosto ristretto (ad es. nessuna CPU ha un istruzione per leggere un file o per visualizzare un immagine). I principali tipi di istruzione sono i seguenti:

Una CPU esegue un semplice ciclo ripetutamente. Legge la prossima istruzione dalla memoria, la decodifica e la esegue leggendo qualche dato dalla memoria, effettuando qualche operazione aritmetica o logica e scrivendo il risultato in memoria o in qualche registro. Poi ritorna all'inizio del ciclo leggendo un'altra istruzione, e così via. I processori sono velocissimi, potendo eseguire un'instruzione in una frazione di nanosecondo (un miliardesimo di secondo), cioè, più di un miliardo di istruzioni al secondo. Generalmente la velocità di un processore, cioè il numero di istruzioni che può eseguire al secondo, può essere approssimata non troppo rozzamente dal numero di cicli che l'hardware esegue al secondo. L'unità di misura è l'hertz che corrisponde ad un ciclo al secondo. Un kilohertz (KHz) sono 1000 hertz, un megahertz (MHz) sono 1000 KHz, un gigahertz (GHz) sono 1000 MHz. I primi PC degli anni '80 avevano processori a meno di 5MHz, quelli di oggi superano i 3Ghz e sono quindi circa mille volte più veloci. In realtà sono circa 10000 volte più veloci per via di altre migliorie come la presenza di più core, del parallelismo interno e delle memorie cache.

Ogni tipo di CPU ha il suo repertorio di istruzioni e questo è chiamato linguaggio macchina. Ad esempio, il linguaggio macchina di un processore Intel è differente da quello di un processore SPARC ed entrambi sono differenti dal linguaggio macchina di un processore MIPS. In linea di principio un qualsiasi computer potrebbe essere programmato direttamente nel suo linguaggio macchina. Ecco un programmino nel linguaggio macchina MIPS dove ogni linea contiene una istruzione:

00100100000100000000000000000001
00100100000100010000000000000010
00100100000100100000000000000011
00000000000100001001100000100001
00000010011100010000100000101010
00010000001000000000000000000001
00000000000100011001100000100001
00000010011100100000100000101010
00010000001000000000000000000001
00000000000100101001100000100001

Non fa molto, calcola il massimo di tre numeri contenuti in altrettanti registri. Non ci dovrebbero essere dubbi sul fatto che è illeggibile (anche per chi conosce la codifica delle istruzioni). Eppure i primissimi computer potevano essere programmati solamente in questo modo. Nonostante i programmi di allora non fossero molto grandi si sentì subito l'esigenza di poter programmare in un linguaggio più leggibile e quindi meno suscettibile a semplici errori di scrittura. Già negli anni '50 fu introdotto il linguaggio assembly. Questo linguaggio permette di scrivere le istruzioni in un modo simbolico più facile per noi esseri umani da comprendere. Ecco lo stesso programma di sopra scritto nel linguaggio assembly di MIPS:

        LI $s0, 1
        LI $s1, 2
        LI $s2, 3
        MOVE $s3, $s0
        BGE $s3, $s1, else  
        MOVE $s3, $s1
else:   BGE $s3, $s2, end
        MOVE $s3, $s2
end:

La traduzione può essere eseguita da un opportuno programma chiamato assembler. L'assembler è un primo esempio di un programma che manipola un altro programma. Questa è un idea molto potente che è al cuore di rivoluzioni significative nel campo dello sviluppo software.

Il linguaggio assembly e sicuramente più agevole per la scrittura di programi del linguaggio macchina ma è ancora un linguaggio molto difficile da usare per scrivere programmi medio-grandi. Inoltre, al pari del linguaggio macchina è specifico di una certo tipo di processore. Un programma scritto nell'assembly di una particolare CPU, diciamo un processore Intel di un Mac o PC sarà differente da un programma per lo stesso compito per una differente CPU, ad esempio il processore ARM di un cellulare. Se si vuole convertire un programma in assembly per un processore in uno in assembly di un altro processore, il programma deve essere completamente riscritto. Ed è un lavoro molto duro. Per queste ragioni sono stati molto presto introdotti i cosidetti linguaggi ad alto livello.

Il Software

Software è un termine generale per indicare sequenze di istruzioni che fanno sì che un computer faccia qualcosa di utile. Ovvero il software sono i programmi. Questi non sono più scritti direttamente in linguaggio macchina o in linguaggio assembly (eccetto casi molto rari) ma in linguaggi più facili da usare (per noi essere umani) e più leggibili, detti linguaggi ad alto livello. Ci penserà il computer stesso tramite opportuni programmi a tradurre i programmi scritti in un linguaggio ad alto livello in linguaggio macchina.

Linguaggi di Programmazione ad Alto Livello

Tra la fine degli anni '50 e l'inizio degli anni '60 fu fatto uno dei più importanti passi nella storia della programmazione dei computer: lo sviluppo di un linguaggio ad alto livello, cioè un linguaggio indipendente dalla specifica architettura della CPU. Oltre a ciò, un linguaggio ad alto livello è più vicino al modo di esprimersi degli esseri umani rispetto al linguaggio assembly. Un programma scritto in un linguaggio ad alto livello è convertito da un programma traduttore, detto compilatore, nel linguaggio macchina o nel linguaggio assembly di uno specifico processore.

Uno dei primi linguaggi ad alto livello fu il FORTRAN (nome derivato da Formula Translation), sviluppato da un team dell'IBM, utile per calcoli scientifici e ingegneristici. Un'altro linguaggio della fine degli anni '50 è il COBOL (Common Business Oriented Language) specialmente orientato appunto per software gestionale e di contabilità, ed è ancora usato. Il BASIC (Beginner's All-purpose Symbolic Instruction Code), sviluppato a Dartmouth nel 1964, fu concepito per l'insegnamento della programmazione. Per la sua semplicità fu il primo linguaggio ad alto livello dei primi personal computers. Bill Gates iniziò proprio scrivendo un compilatore per il BASIC per il microcomputer Altair nel 1975. Il BASIC continua a vivere nel linguaggio Visual Basic della Microsoft. Ecco un esempio di un programa in BASIC così come poteva essere scritto alla fine degli anni '70. In questo esempio, il programma prende in input un intero n è determina se è o meno un numero primo:

10   LET n = 0: LET p = 0
20   INPUT "Enter number: "; n
30   GO SUB 1000
40   IF p = 0 THEN PRINT n;" is not prime!"
50   IF p <> 0 THEN PRINT n;" is prime!"
60   GO TO 10
1000 REM ***************
1001 REM * PRIME CHECK *
1002 REM ***************
1010 LET p = 0
1020 IF n/2 = INT(n/2) THEN RETURN 
1030 LET p = 1
1040 FOR i = 3 TO SQR(n) STEP 2
1050 IF n/i = INT(n/i) THEN LET p = 0: LET i = SQR(n) 
1060 NEXT i
1070 RETURN

Anche se non si conosce il linguaggio BASIC si può più o meno intuire cosa fa ed è sicuramente molto più leggibile di una versione scritta in linguaggio assembly.

Decenni fa i computer erano molto più lenti e limitati di quelli attuali e si era preoccupati che i programmi scritti in linguaggi ad alto livello potessero essere molto più lenti dei programmi scritti direttamente in assembly da esseri umani. Oggi questa preoccupazione, a parte rare circostanze, non ha più ragion d'essere perché grazie alla maggiore velocità dei computer e al contemporaneo miglioramento dei compilatori il codice macchina prodotto da un compilatore può essere persino più efficiente di quello che potrebbe produrre un programmatore molto esperto. Ancora un altro esempio di programmi che manipolano con successo altri programmi.

I linguaggi come il FORTRAN, il COBOL e il BASIC devono in parte il loro successo all'essere focalizzati su specifiche aree di applicazione e intenzionalmente non tentarono mai di gestire ogni possibile compito programmativo. Durante gli anni '70 furono creati linguaggi per la programmazione di sistema (system programming) cioè per scrivere assembler, compilatori e sistemi operativi. Quello che ha avuto maggiore successo è il linguaggio C, sviluppato nel 1973, è ancora usato. Negli anni '80 furono introdotti linguaggi come il C++ con l'intento di aiutare a gestire la complessità di programmi molto grandi. Il C++ si è evoluto a partire dal C ad è oggi uno dei linguaggi più usati. Ad esempio, la maggior parte del software su Mac è scritto in C e Objective-C (un dialetto del C), Word è scritto in C e C++, i sistemi operativi Unix e Linux sono scritti in C e Firefox e Chrome sono scritti in C++.

Durante gli anni '90 vari linguaggi furono sviluppati in congiunzione alla crescita di Internet e del World Wide Web. Lo scopo originale del linguaggio Java era la programmazione di piccoli sistemi incorporati in elettrodomestici e apparecchi elettronici. Ma invece fece la sua comparsa nel mondo come linguaggio per programmare servizi web. Quando si visita un sito come eBay, il nostro computer esegue codice scritto in C++ and JavaScript ma i servers di eBay possono usare Java per preparare le pagine che sono inviate al nostro browser. Java è più semplice del C++ ma più complicato del C. A metà degli anni '90 fu creato JavaScript da Netscape per essere usato in un browser per produrre effetti dinamici in pagine web. Oggigiorno quasi tutte le pagine web includono codice JavaScript.

Sebbene tutti i lunguaggi di programmazione sono logicamente equivalenti non sono affatto tutti ugualmente adatti per i vari tipi di compiti da programmare. C'è un mondo di differenza tra scrivere un programma in JavaScript che controlla una sofisticata pagina web e scrivere un programma in C++ che implementa il compilatore JavaScript. È difficile trovare programmatori esperti nel fare entrambe le cose.

Sono stati inventati migliaia, forse decine di migliaia, di linguaggi di programmazione ma solo poche centinaia sono abbastanza usati. Secondo alcune recenti analisi sulla popolarità dei diversi linguaggi di programmazione quelli più usati/popolari sono: C, Java, C++, PHP, JavaScript, Python, C#, Perl, Ruby, VB, Objective-C (vedi Programming Language Popularity, 5 Ways to Tell Which Programming Languages are Most Popular, TIOBE Index)

Sviluppo Software

Un compilatore, un web browser (come Firefox, IE, Safari) o un sistema operativo (come Linux, Mac, Windows) è un programma (o un insieme di programmi) che può avere centinaia di migliaia o milioni di linee di codice. I grandi sistemi software possono avere anche centinaia di milioni di linee di codice. Per progettare, scrivere e mantenere tali sistemi occorrono centinaia o migliaia di persone che lavorano insieme e la vita del sistema può durare anni o decenni. Software di tali dimensioni richiedono squadre di programmatori, collaudatori, documentatori, diversi livelli di gestione e una interminabile serie di riunioni.

Per fortuna, ben difficilmente chi si accinge a scrivere un programma (sopratutto se abbastanza grande) deve partire da zero. Come in una qualsiasi altra attività che ha a che fare con costruzioni complesse, anche la programmazione può usufrire di componenti già fatte e pronte all'uso. Per esempio, se si vuole scrivere un'applicazione per Windows, Mac o Linux, ci sono librerie di programmi già pronti per tutti gli elementi di una interfaccia grafica (menu, bottoni, editors di testo, grafica, ecc.). Così la maggior parte del lavoro consiste nel capire le componenti e nel combinarle insieme. Molte compomenti sono a loro volta complesse e sono costruite a partire da librerie di componenti più semplici. Tutto ciò, a volte, per parecchi livelli. Al di sotto di tutto, c'è il sistema operativo che è un programma molto complesso che gestisce l'hardware e controlla qualsiasi cosa accade nel computer (compresa l'esecuzione di un qualsiasi programma). L'intero software che è eseguito su un computer è organizzato in strati per gestire meglio la complessità dei programmi. Lo strato più basso è l'hardware che è essenzialmente immutabile (a parte quando si aggiunge qualche dispositivo). Il prossimo strato è il sistema operativo. Quello ancora sopra è un insieme di librerie che forniscono servizi utili così che i programmatori non debbano riscriverli (calcolo di funzioni matematiche, date e tempo, crittografia, grafica, compressione, ecc.). Le applicazioni sono l'ultimo strato. Una tipica applicazione usa sia librerie che servizi del sistema operativo (quest'ultimi sono chiamati system calls).

Gli ostacoli dello sviluppo software non si esauriscono con la complessità intrinseca nelle grandi dimensioni del software ma derivano anche dalla natura stessa della programmazione che è stata ben descritta in un epigramma di Alan Perlis:

Programming is an unnatural act. — Epigrams on Programming

Non a caso, nessun programma abbastanza grande funziona la prima volta (a volte neanche la seconda, neanche la terza,…). La programmazione richiede un'attenzione perfetta ai dettagli che gli esseri umani difficilmente riescono a mantenere a lungo. Però, l'onnipresenza degli errori non deve sorprendere, in un certo senso, i programmi riflettono la complessità della vita che è notoriamente difficile da gestire. Così essenzialmente tutti programmi avranno errori che produrranno comportamenti non voluti. Questi errori sono chiamati bugs (un termine inglese che significa piccolo insetto). Cosa c'entrano gli insetti con gli errori nella programmazione? Nel 1947 in uno dei primi computer, l'Harvard Mark II, fu trovata una falena morta e una delle progettiste del computer disse che stavano faccendo il "debugging" della macchina. Da qui anche il termine debugging per indicare l'attività, appunto, di trovare e correggere gli errori nei programmi. Tuttavia, il termine bug per indicare un errore o comunque un problema in una macchina è molto più antico e risale al 1889 ed è dovuto al famoso inventore americano T. Edison che lo usò a proposito della scoperta di un problema nel suo fonografo.

Per avere un'idea di come il software è diventato sempre più complesso, si pensi che il sistema operativo Unix del 1975 consisteva in appena 9000 linee di codice C e fu scritto da due persone (Ken Thompson e Dennis Ritchie). Oggi Windows 7 ha all'incirca 100 milioni di linee di codice e Linux ne ha più di 10 milioni e sono entrambi il frutto del lavoro di migliaia di persone per decenni.

Python

Nel 1989, Guido van Rossum era in un gruppo che stava lavorando su un nuovo sistema operativo distribuito chiamato Amoeba. Vi era la necessita di avere uno strumento software che rendesse facile l'amministrazione di sistema. I strumenti che di solito vengono usati per tali compiti sono o il linguaggio C o i linguaggi di scripting. Però nessuno di questi era soddisfacente. Così Guido pensò che fosse una buona idea sviluppare un linguaggio adatto allo scopo ma che non fosse uno strumento specifico per il sistema Amoeba e che quindi potesse essere usato anche in altri contesti.

Un linguaggio utile all'amministrazione di sistema è di solito un cosidetto linguaggio di scripting, che è un linguaggio che permette di scrivere programmi che automatizzano l'esecuzione di compiti che altrimenti dovrebbero essere eseguiti manualmente da un operatore umano in modo molto più lento e tedioso. I linguaggi di scripting non sono usati solamente per l'amministrazione di sistema ma anche in altri ambiti. Una caratteristica che li accomuna è che non hanno bisogno di sfruttare al massimo la velocità del computer perché i compiti che sono soliti automatizzare demandano il lavoro "duro" a altri programmi (librerie) già pronti. Uno script, così è chiamato solitamente un programma scritto in tali linguaggi, è come il capomastro di un cantiere che non deve da solo tirare su un muro in un ora ma può impartire l'ordine a una squadra di muratori. Gli script, non avendo bisogno della velocità del codice compilato, vengono eseguiti tramite un programma che si chiama interprete che fa risparmiare il tempo richiesto dalla fase di compilazione. Un interprete per un linguaggio L esegue un programma scritto nel linguaggio L direttamente, senza cioè compilarlo preventivamente in linguaggio macchina. Può essere visto come una macchina simulata via software il cui linguaggio macchina è proprio il linguaggio L. Anche se l'esecuzione di un programma compilato è più veloce di quella prodotta dall'interprete, il tempo di compilazione può fare la differenza.

Dal punto di vista di chi vuole creare un nuovo linguaggio di programmazione un interprete offre due importanti vantaggi rispetto a un compilatore.

  1. È, generalmente, molto più facile da scrivere.

  2. Può essere portato su un'altra macchina più facilmente.

Probabilmente anche questi aspetti hanno giocato un ruolo nella scelta di Guido di scrivere un interprete (piuttosto che un compilatore) per il suo nuovo linguaggio. Intorno al 1991 la prima versione del linguaggio era pronta. Il nome Python che Guido diede al suo linguaggio deriva da Monty Python's Flying Circus. Python venne subito usato con successo nel progetto Amoeba e in altri progetti. Quasi tutti i linguaggi derivano da linguaggi precedenti e Python non fa eccezione riprendendo molte idee dai linguaggi ABC e Modula-3.

Nel tempo Python è stato via via migliorato e oggi è un linguaggio collaudato e maturo. Ha una libreria standard molto ricca ulteriormente estesa da una sterminata collezione di librerie esterne che facilitano lo sviluppo software in una vasta gamma applicazioni (web, grafica, giochi, multimedia, calcolo scientifico, ecc.). Anche grazie a ciò l'uso di Python è andato crescendo in tutti gli ambiti professionale/commerciale, scientifico ed educativo. Inoltre, è un linguaggio molto facile da apprendere e da usare.

Installare Python

Attualmente Python ha due versioni che sono leggermente incompatibili fra loro la 2.x e la 3.x (ad oggi, settembre 2012, sono la 2.7.3 e la 3.2.3). Per questo corso useremo la 2.7.3 perché ci sono molte e importanti librerie esterne che non sono ancora funzionanti con la nuova versione 3.x. Per tutte le informazioni sul linguaggio si può consultare il sito ufficiale di Python. L'installer del linguaggio dipende ovviamente dalla piattaforma.

Una volta che Python è installato si può iniziare a provarlo dalla cosidetta shell di Python, che si apre invocando il comando python da terminale (prompt dei comandi). La shell permette di usare Python in modo interattivo. Una buona guida per i primi esempi è questa introduzione.

La documentazione completa di Python e della sua libreria standard è documentazione