Cos’è un programma? E’ un elenco di istruzioni che deve essere dato a qualcuno che dovrà eseguirle.

Troppo generico.

Facciamo per un momento un passo indietro, e pensiamo un attimo al significato della parola informatica. Cosa vuol dire informatica?

Se lo chiedete ad un matematico, questi vi risponderà che il termine nasce dalla contrazione delle parole INFORmazione e mateMATICA, e sta ad indicare un processo per il trattamento matematico delle informazioni, cercando ancora una volta di accaparrarsi la paternità della neonata scienza.

In realtà il termine informatica nasce dalla contrazione delle parole INFORmazione e autoMATICA, e sta ad indicare un processo per il trattamento automatico delle informazioni.

Cavilli? può darsi. Ma la differenza c’è, e si sente.

Un banale esempio: la matematica ci insegna che enunciato un problema ed i suoi dati, applicando una serie di procedimenti (matematici), possiamo giungere alla soluzione.

Es. Il nonno di Luisa ha in cantina, tra bianco e rosso, 810 litri di vino. I 2/3 sono di vino rosso.
Quanti litri di vino rosso ha il nonno? Quanti sono i litri di vino bianco?

(810 : 3) x 2 = 540 l (vino rosso)
810 – 540 = 270 l (vino bianco)

Il nonno ha 540 litri di vino rosso e 270 litri di vino bianco.

L’informatica ci permette di classificare il problema, partendo da una soluzione nota o desiderata, creando un procedimento che può essere adattato ad ogni problema della stessa classe per risolverlo in maniera automatica.

Es. desidero ingrandire o ridurre una qualsiasi immagine di un qualsiasi fattore di scala.

per ogni punto dell’immagine
moltiplica la posizione del punto per il fattore di scala,
al posto del punto disegna un quadrato che ha per lato il fattore di scala.

In matematica abbiamo risolto il problema applicando un procedimento, una formula, arrivando al risultato. In informatica abbiamo creato un procedimento, un algoritmo, un programma, che può essere applicato ad ogni problema della stessa classe (riduzioni o ingrandimenti di immagini, che può essere applicato a qualsiasi immagine e per qualsiasi fattore di scala) ma, cosa più importante, in maniera automatica, cioè senza alcun intervento umano (o perlomeno estremamente ridotto).

Potremmo, banalizzando, affermare che siano una l’opposta dell’altra o che (eresia!) la matematica possa in qualche modo sfruttare l’informatica per la risoluzione dei problemi. La verità, come sempre, sta nel mezzo. Le due discipline si compenetrano: la matematica usa procedimenti, creati dai grandi matematici fin dalla notte dei tempi, mentre l’informatica permette di creare quei procedimenti, per lo più applicando formule e procedimenti matematici.

Alla fine di tutto questo bel paragrafo, potremmo quasi asserire che Pitagora, Euclide e compagnia bella fossero programmatori! e i matematici a seguire i loro esecutori! scommetto che i matematici alla lettura avranno la loro da dire (fieri ed orgogliosi quali sono, da bravi matematici)!

Ovviamente si tratta di ironia, gente… evitiamo inutili flame!

Chiarito cosa sia l’informatica e cosa un programma, andiamo avanti.

Il programma che resta nella testa del programmatore è fine a se stesso (al più può alimentare il senso di autocompiacimento/autostima del programmatore): questo è un dato di fatto.

Affinché possa essere utile a qualcuno (programmatore compreso) il programma deve essere scritto.

In che lingua? in una lingua conosciuta da colui che dovrà eseguire il programma: l’esecutore.

L’esecutore è il soggetto che fisicamente leggerà, comprenderà ed eseguirà il programma passo passo, così come lo ha previsto il programmatore in fase di scrittura.

Comprato un mobile all’IKEA? aperto l’involucro di cartone hai trovato le istruzioni? hai seguito le istruzioni passo passo ed hai montato il mobile? bene, TU sei stato l’esecutore, le istruzioni il programma, i pezzi del mobile i dati, il mobile il risultato. Non hai eseguito le istruzioni passo passo, alla lettera, e il mobile è venuto una schifezza? TU sei stato un’anomalia, un bug, qualcosa che non ha consentito al programma di funzionare correttamente (e non c’è da andarne fieri).

Facciamo finta, per un attimo, che il tempo si sia fermato agli inizi degli anni ’80. I computer potenti erano grossi come grandi stufe, i personal computer (PC) non esistevano ancora, ed iniziavano ad affacciarsi i primi home computer. Tutti in comune avevano una potenza di elaborazione ad oggi ridicola, scarsa o nessuna possibilità di archiviazione dei dati, e ciascuno il proprio dialetto di linguaggio macchina per la programmazione, dato dal modello di microprocessore montato a bordo.

Esatto. Linguaggio macchina. L’esecutore del programma era il microprocessore (cosa che avviene tutt’oggi a 40 anni di distanza, tralasciando quello che c’era prima in quanto poco utile ai fini di questa spiegazione), una macchina in grado di processare informazioni sotto forma di segnali elettrici, e di fornire altrettante informazioni, anch’esse sotto forma di segnali elettrici, prodotte da un programma inserito nella sua area di lavoro.

Pertanto il programmatore che volesse scrivere un programma per un dato microprocessore, doveva scriverlo nella sola lingua che l’esecutore potesse comprendere, ovvero segnali elettrici, che opportunamente combinati in un set di istruzioni, il linguaggio macchina, consentivano al microprocessore di eseguire somme, salti e spostare dati in memoria. Istruzioni che opportunamente organizzate, hanno portato alla realizzazione di programmi sempre più complessi, sistemi operativi, applicazioni, web, fino a questo testo che state leggendo.

Tavola sinottica delle istruzioni del microprocessore intel 8086.

Pensate che siano cose lontane anni luce? pensate che ad oggi funziona ancora tutto esattamente così (certo, con l’unica eccezione del computer quantistico), solo infinitamente più velocemente e con capacità di memorizzazione, ai tempi, inimmaginabile. Cose, velocità ed archiviazione, che hanno consentito lo svilupparsi di tutti i sistemi software ed hardware di cui possiamo disporre oggi.

Dai segnali elettrici si è passati ai codici esadecimali, e da questi ai codici mnemonici (con l’introduzione del linguaggio assembly), ma il programma veniva scritto ancora in linguaggio macchina, solo che stavolta per il programmatore era più facile ricordare un’istruzione, per sommare ad esempio due numeri, del tipo ADD AX, BX piuttosto che una lunga sequenza di segnali accesi/spenti, 1/0, o un numero esadecimale. Il programma così scritto in assembly veniva dato in pasto ad un altro programma, scritto da qualcun altro, l’Assembler, che convertiva il codice mnemonico in linguaggio macchina.

Ma anche così scrivere programmi complessi presentava una non trascurabile difficoltà, che si ripercuoteva sui tempi di consegna ed i budget investiti. Così iniziò la corsa alla scrittura dei vari linguaggi di programmazione, che tra gli anni ’70 e gli anni ’80 ha visto la sua epoca d’oro. Nacquero linguaggi di ogni genere e tipo, specializzati nei più variegati settori: dal BASIC per facilitare l’apprendimento e l’ingresso nel mondo della programmazione, il COBOL specializzato per costruire programmi gestionali e di contabilità, il FORTRAN che metteva a disposizione funzioni matematiche di ogni genere e pertanto usato in ambito scientifico, il PROLOG finalizzato al trattamento logico dei dati, e così via, passando per ADA, PASCAL, e molti, molti altri. Tutti questi avevano una sola cosa in comune: un particolare programma in grado di convertire lo specifico linguaggio in linguaggio macchina (che resta comunque la sola cosa che la macchina può eseguire): il compilatore. Così come l’assembly aveva il suo Assembler, così ogni linguaggio aveva il suo compilatore.

E per i programmatori iniziò a diventare più facile scrivere programmi. E molti più programmi iniziarono a vedere la luce, facendo crescere la necessità di prestazioni migliori, e maggiore capacità di archiviazione. Necessità dovuta anche al fatto che più si sale di livello, quindi allontanandosi dal livello del codice macchina a favore di una maggiore semplicità di programmazione, più diventa difficile/impossibile ottimizzare il programma generato dal compilatore.

Da qui in avanti il programmatore non doveva più fare riferimento al microprocessore nello scrivere il suo programma, bensì al linguaggio di programmazione da egli scelto. Anche perché i linguaggi di programmazione più alla moda avevano il proprio compilatore per i vari processori presenti sul mercato, certo con qualche differenza gli uni dagli altri dovuta alle differenze dei vari microprocessori (non potevano essere tutti uguali, altrimenti il mercato si sarebbe ben presto appiattito anziché diventare quella fucina di idee che ha portato fino agli smartphone che ora abbiamo tra le mani).

E dai linguaggi di programmazione si passò ai sistemi operativi: collezioni di programmi che facevano il possibile per mettere a disposizione funzionalità di base per gestire gli schermi, via via più sofisticati, le tastiere, le stampanti, e i dischi, sia quelli rimovibili che quelli fissi. E nacquero i primi sistemi DOS, capaci di essere eseguiti da un floppy.

E da lì i programmatori dovettero iniziare a pensare i propri programmi in funzione del linguaggio, del microprocessore ed anche del sistema operativo su cui sarebbero stati eseguiti, dapprima ancora testuali come il DOS, poi grafici.

E poi fu la volta degli interpreti, che gradualmente, grazie all’aumento delle prestazioni dell’hardware, presero il posto dei compilatori, al grido di “scrivi una volta, esegui dappertutto!”: programmi che anziché tradurre il codice in linguaggio macchina si limitavano ad eseguirlo istruzione dopo istruzione, passo dopo passo, assumendosi il compito di esecutore. E anche qui, a discapito dell’ottimizzazione. Inoltre ciò portava con sé la terribile conseguenza del dover distribuire il codice sorgente del programma affinché l’interprete potesse leggerlo ed eseguirlo passo passo, cosa ovviamente inaccettabile per le aziende, tanto gelose ed impegnate a custodire i propri segreti industriali.

Ma nonostante tutto il concetto di interprete piacque così tanto da portare alla realizzazione delle macchine virtuali, Java su tutte, evolvendo il concetto dello “scrivi una volta, esegui dappertutto” in “compila una volta, esegui ovunque”: non era più necessario distribuire il codice del programma, ma bastava darlo in pasto in appositi compilatori in grado di produrre un codice macchina specifico per un microprocessore non esistente realmente, virtuale appunto, che la macchina virtuale, presente sui più disparati sistemi, avrebbe interpretato alla stregua di un microprocessore reale.

E ancora, a seguire, compilatori JIT, runtime di ogni tipo e genere, e via via, spostando sempre l’ago della bilancia sulla facilità di produrre programmi, rispetto alle prestazioni ed alle ottimizzazioni, e portando a spremere sempre di più i limiti fisici per la produzione di microprocessori sempre più veloci, sempre più memoria, sempre più spazio di archiviazione.

Tutta questa bella prosopopea solo per dire che, oggi come allora, chi vuole intraprendere la via del programmatore, deve fare i conti con l’esecutore di riferimento, che sia un microprocessore (computer, smartphone, tablet, smart tv, sistemi embedded), una macchina virtuale (Java, .NET, etc.), un linguaggio particolare (JavaScript, C#, Python, Lua, etc.).

Se poi siete qui perché volete sviluppare videogiochi, dovrete tenere anche in considerazione le varie piattaforme esistenti, dai sistemi desktop (windows, macOs, linux), ai dispositivi mobili, al web, alle varie console (sony, microsoft, nintendo, etc.), ciascuna con le proprie peculiarità, e non da ultimo, l’engine ed il linguaggio di programmazione che intenderete utilizzare.

Questo non deve scoraggiarvi, dovete solo essere preparati a quello che andrete incontro.

L’esecutore è al tempo stesso, il vostro migliore alleato ed il vostro peggior nemico. Farete bene a conoscerlo a fondo.

Di SYSOP

Lascia un commento