Sei sulla pagina 1di 8

Compilatore[modifica]

Un compilatore è il programma base per compilare. Questo scorre il codice sorgente e lo traduce nel
corrispondente binario per l'architettura su cui questo dovrà essere eseguito.

Spesso la compilazione non è una traduzione "letterale" ma quanto scritto dal programmatore è
verificato e dove possibile ottimizzato.

Il primo controllo eseguito dal compilatore è quello sintattico. Ovvero come ogni linguaggio anche
quello di programmazione ha le sue precise regole. Il controllo sintattico non fa altro che verificare se
queste regole sono state rispettate e restituisce un errore se così non fosse. Un secondo controllo che
il compilatore fa è quello semantico, ovvero controlla che le istruzioni siano coerenti tra loro. Ad
esempio se un'operazione richiede due numeri interi e gliene viene dato solo uno il compilatore si
fermerà generando un errore. Alcuni compilatori sono in grado di trovare anche errori logici, ad
esempio un ciclo infinito di istruzioni che non termina mai. Ai compilatori inoltre è affidato l'arduo
compito di ottimizzare il codice binario risultante, a volte anche sopperendo ad una programmazione
non proprio attenta. Spesso questo avviene eliminando istruzioni inutili, ignorando codice che non potrà
mai essere eseguito o altro ancora. Ma soprattutto l'ottimizzazione avviene sfruttando al massimo le
opportunità offerte dall'architettura di destinazione. Il compilatore quindi può essere determinante per la
velocità finale di un programma. Pur non potendo sostituire l'uso di tecniche di programmazione
efficaci, l'impatto del compilatore sulle prestazioni può essere sensibile. Tuttavia una compilazione
troppo spinta che sfrutti euristiche ancora non ben testate può comportare la creazione di un codice
binario errato, che andrà in errore anche se non per colpa del programmatore.

Non necessariamente il compilatore crea un binario che può essere eseguito da solo. Capita molto
spesso infatti che siano compilate delle librerie di codice e non un programma vero e proprio. Tali
librerie non sono altro che un insieme di funzioni, anche molto generiche, che sono poi riutilizzate da
altri programmi. Il sorgente di una libreria viene quindi compilato in una maniera particolare per cui il
risultato è un file binario che dovrà poi essere collegato al programma vero e proprio che ne vorrà
utilizzare le funzionalità. Quest'ultimo procedimento viene eseguito all'avvio del programma dal Linker.

Linker[modifica]
Il linker è il programma che si occupa di collegare l'eseguibile alle librerie da questo usate.
Quest'operazione può essere eseguita in due tempi diversi, in fase di compilazione oppure all'avvio del
programma. Nel primo caso si parlerà di link statico, nel secondo di link dinamico.

Link statico[modifica]

Il link statico delle librerie avviene direttamente in fase di compilazione. Linker più semplici inglobano
nell'eseguibile finale l'intera libreria, mentre quelli più avanzati solo la parte di codice realmente usata,
evitando quindi inutile spreco di spazio e riducendo i tempi di avvio del programma e la quantità di
memoria principale usata.

Il vantaggio del link statico sta nella facilità di distribuzione dell'eseguibile. Dal momento che tutte le
funzioni usate sono già incluse in esso è sufficiente distribuire il solo eseguibile, senza preoccuparsi di
eventuali dipendenze o conflitti tra librerie. Tuttavia vi sono molti aspetti tecnici che lo rendono poco
preferibile. Questo concetto si capirà meglio affrontando il link dinamico.
Link dinamico[modifica]

Il link dinamico viene eseguito dal linker al momento del caricamento del programma in memoria. In
questo caso l'eseguibile è compilato in modo tale da contenere richiami a librerie esterne che il linker
dovrà trovare e collegare prima di poter eseguire il programma. Se sul sistema in cui si tenta di
eseguire il programma manca una di queste librerie verrà generato un errore. Un errore può essere
generato anche nel caso in cui la libreria installata non contenga la funzione richiesta. Questo potrebbe
avvenire se non è della versione attesa. Se precedente, infatti, la funzione usata potrebbe non essere
ancora stata implementata, mentre se è una versione sucessiva la funzione usata potrebbe essere
stata rimossa. Com'è comprensibile l'uso del link dinamico può comportare non pochi problemi di
distribuzione del programma proprio per via delle dipendenze con le varie librerie o i conflitti che si
possono generare. Anche le librerie, infatti, possono fare riferimento ad altre librerie, generando così
una catena di dipendenze anche molto lunga. Si tratta, tuttavia, di problemi quasi sempre superabili con
un'attenta configurazione del sistema. Pur con questi inconvenienti il link dinamico è usato molto
spesso perché offre moltissimi vantaggi, tali da compensare i disagi sopra esposti. Questi sono:

 Condivisione delle librerie. Se una libreria è usata da molti programmi il link dinamico
permette di installare sul sistema la libreria una sola volta. Non solo, può essere caricata nella
memoria principale un'unica volta. Ipotizzando che dieci programmi usino una libreria grande 10
MB il link dinamico fa si che questa sia caricata una sola volta e che quindi occupi solo 10 MB di
ram. Diversamente, se la libreria fosse compilata in maniera statica, lo stesso codice sarebbe
ripetuto dieci volte nella memoria, occupando 100 MB.
 Minore dimensione dell'eseguibile. Mancando il codice incluso nelle librerie il file eseguibile è
più piccolo. Questo comporta un risparmio di spazio a volte consistente, favorendone la
distribuzione.
 Migliora la mantenibilità. Se una libreria è stata aggiornata è sufficiente sostituire solo quella
per far si che tutti i programmi che l'usano si giovino delle modifiche. Diversamente il link statico
obbligherebbe a ricompilare ed aggiornare tutti i programmi. Se la libreria è molto usata questo può
richiedere un'operazione molto laboriosa. A titolo d'esempio si può ricordare la scoperta in passato,
quasi contemporanea, di un bug all'interno di due librerie molto usate per la visualizzazione di
immagini che comportavano seri problemi di sicurezza. La prima, usata su di un sistema in cui i
programmi sono compilati in maniera statica, impose l'aggiornamento di numerosi programmi, dal
browser e la posta elettronica ai programmi di videoscrittura e di foglio elettronico. La seconda,
usata su un sistema in cui i programmi sono tipicamente compilati in maniera dinamica, fu
sufficiente modificare la libreria di pochi kb per risolvere definitivamente ed in maniera sicura il
problema. Nel primo caso, infatti, l'unico modo che gli utenti avevano per essere sicuri era quello di
non usare i programmi incriminati fino a che non fosse disponibile la versione aggiornata. Ma
trattandosi di una funzionalità così diffusa era anche difficile per un utente rendersi conto di quali
programmi fossero o meno a rischio.
IDE[modifica]
Nei linguaggi di programmazione, esistono due aspetti fondamentali: la sintassi e la semantica. Per
introdurre questi concetti, è necessario chiarire il concetto di linguaggio, di alfabeto e di stringa; con
alfabeto si intende un insieme di simboli, con stringa si intende un raggruppamento di simboli di un
certo alfabeto, che hanno un certo significato nell'ambito del linguaggio stesso.
In queste condizioni, la sintassi si occupa di verificare che una certa stringa appartenga o no al
linguaggio, mentre la semantica riguarda la generazione di tutte le strighe di un certo linguaggio.

Con il termine algoritmo si intende un metodo per la soluzione di un problema adatto a essere
implementato sotto forma di programma.
Il termine deriva dal nome del matematico persiano Muhammad ibn Mūsa 'l-Khwārizmī. Un algoritmo è
un procedimento di azioni specificate per mezzo di regole precise e non ambigue, tali che è possibile
eseguire l'algoritmo "automaticamente", cioè applicando le regole senza pensare al significato, oppure
direttamente da una macchina.
Vi sono molti modi per descrivere un algoritmo (da quelli più astratti a quelli più particolareggiati). Un
problema algoritmico è, invece, costituito da:

 Precondizione: una specifica precisa dei tipi dei dati di partenza (input) e delle condizioni cui
essi devono soddisfare.
 Postcondizione: una specifica precisa delle condizioni cui devono soddisfare i dati di arrivo
(output), e in particolare della relazione che vi deve essere fra l'input e l'output. Ossia una specifica
R(x,y) che definisca qual è, per ogni istanza x dell'input, la risposta o l'insieme delle possibili
risposte y che si vogliono ottenere.
https://www.arcetri.astro.it/~lfini/AGauld/

Un programma è una serie di istruzioni in codice binario che vengono eseguite dalla CPU. Si può
pensare come una lunga catena di 1 e 0 (i segnali elettrici) che attivano all'interno della CPU i corretti
circuiti logici che effettueranno i calcoli e le operazioni necessarie. Ogni operazione è richiamabile da
una precisa sequenza di 1 e 0. L'insieme delle combinazioni che identificano tutte le operazioni possibili
è denominato API, mentre il codice che viene eseguito è definito codice macchina. Ogni CPU
ovviamente ha un'API diversa da tutte le altre architetture, e pertanto un codice macchina creato per
una determinata architettura non può funzionare su altre.

Inizialmente i programmatori erano costretti a definire il programma scrivendo direttamente il codice


macchina, ovvero precisamente le combinazioni corrette di 1 e 0 che la CPU doveva eseguire. Come è
facile immaginare non era un lavoro facile e la probabilità di commettere errori alta. Col tempo sono
stati introdotti strumenti sempre più complessi per facilitare lo sviluppo delle applicazioni, consentendo
la scrittura di codice più comprensibile per gli uomini, poi codificato in linguaggio macchina da altri
programmi. Questi ultimi sono i compilatori e verranno trattati nel prossimo capitolo.

Esiste quindi una differenza sostanziale tra quello che il programmatore scrive, chiamato codice
sorgente, e quello che effettivamente è l'eseguibile, ovvero le istruzioni binarie frutto della compilazione,
chiamato anche codice binario o oggetto. Il codice sorgente è scritto in un linguaggio, detto appunto
linguaggio di programmazione, ed è indipendente dal linguaggio macchina. Sarà infatti il compilatore ad
assumersi il compito di tradurre il sorgente in codice binario seguendo le API dell'architettura su cui il
programma dovrà poi essere eseguito.

L'evoluzione dei linguaggi di programmazione, unita all'incremento della potenza di calcolo, ha visto la
nascita anche di linguaggi che non sono compilati ma interpretati. Un esempio è il ben noto javascript,
utilizzato nei siti web. Questi linguaggi di programmazione sono letti da un programma, detto interprete,
che esegue le operazioni previste. Intuitivamente svolge a livello software quello che fa la cpu a livello
hardware. Le istruzioni attivano le varie funzioni dell'interprete che eseguirà poi il lavoro vero e proprio.
Si aggiunge quindi un ulteriore livello di astrazione, che porta molti vantaggi tra cui la portabilità del
programma, ma anche lo svantaggio di avere minori prestazioni.

I fondamenti di programmazione sono quelle conoscenze basilari che occorre possedere per


la programmazione (informatica) in un qualunque linguaggio di programmazione.

Per scrivere le righe di codice dei linguaggi di programmazione è sufficiente utilizzare un


normale elaboratore testi, o un programma ad hoc detto editor. Nel secondo caso ilsoftware individua
gli errori più banali che un programmatore può commettere.

Indice
  [nascondi] 

 1 Le Fasi della programmazione


o 1.1 Il problema da risolvere
o 1.2 La progettazione del programma
 1.2.1 Gli Algoritmi
o 1.3 La codifica del programma
o 1.4 La verifica del risultato
 2 Lo sviluppo in ambito aziendale
 3 Esempio: addizione di due numeri
 4 Programmi Decisionali
 5 Le Tecniche di Programmazione
 6 Bibliografia
 7 Voci Correlate
 8 Collegamenti esterni

Le Fasi della programmazione[modifica]


I passi con cui si sviluppa un programma efficiente sono simili tra di loro per quasi tutti i contesti
di programmazione (informatica) (aziende, hobby, lavoro, ecc.). Le prime fasi sono strettamente legate
alla logica di quello che si va a creare e del suo funzionamento, mentre le ultime sono orientate verso lo
specifico linguaggio di programmazione che si intende utilizzare.

Il problema da risolvere[modifica]
La prima operazione da svolgere per la creazione di un qualunque programma è definire nel modo più
preciso ed accurato possibile quale problema intendiamo risolvere. Questo vale sia per una
semplice funzione matematica che per un complesso database. L'input che il programma riceve è
legato all'output che intendiamo restituire dopo l'elaborazione.

Questa fase può presentare una grande complessità dovuta al lavoro astratto che impone
al programmatore di immaginare il risultato finale e la sua formalizzazione.

La progettazione del programma[modifica]


Superata la definizione del problema che si vuole risolvere occorre progettare delle possibili soluzioni,
porle a confronto tra loro e risalire a quella più efficiente (ricordando che una soluzione non efficiente
per un determinato problema potrebbe essere utile allo sviluppo di altri programmi). Per confrontare
l'effettiva differenza tra una soluzione ed un'altra possono essere utilizzati due diversi strumenti:

 Uno di essi è il diagramma di flusso: con un grafico molto intuitivo si può illustrare un processo
in tutte le fasi che lo caratterizzano. Ogni fase è collegata con le altre dallelinee di flusso che
indicano la direzione del processo interno al programma.

 Un efficace metodo di progettazione è lo pseudocodice, una forma di scrittura in codice affine


alla lingua parlata dal programmatore. La sua stesura è simile ad una scaletta di operazioni che si
definiscono quando si deve eseguire una determinata azione. La scrittura dello pseudocodice deve
essere dettagliata almeno quanto il codice finale, ma rispetto ad esso non si richiede una sintassi
precisa lasciando il programmatore libero di concentrarsi sui problemi principali del programma.
Gli Algoritmi[modifica]
Per approfondire, vedi la voce Algoritmo.

Al fine di creare un programma efficiente occorre progettarne con attenzione l'algoritmo. Ad esempio


potremmo creare un algoritmo che esegue i seguenti passi:

1. Esamina una lista di numeri e riconosci quello più basso;


2. Inserisci il numero più basso nella variabile X;
3. Stampa la variabile X;

È importante precisare che la lista di passi deve contenere istruzioni chiare, precise e non ambigue,
ovvero il cui significato non dipenda dal contesto in cui lo si scrive, ma sia chiaramente identificabile.

I programmi possono inoltre essere divisi in sezioni in modo che i vari compiti possano essere eseguiti
attraverso sequenze più semplici di passi. A tale scopo viene suddiviso ilprogramma in funzioni
(informatica).

La codifica del programma[modifica]


Avviene in questa fase la scelta del linguaggio di programmazione con cui sviluppare il progetto
(Java, C++, BASIC, Perl, ecc.). Occorre passare dai diagrammi di flusso o dallopseudocodice, ad una
sintassi più rigorosa e specifica del linguaggio scelto.
L'operazione di codifica è quella più soggetta ad errori di natura logica e sintattica In teoria
il programma potrebbe essere pronto in questa fase, ma in realtà esso presenta nella quasi totalità dei
casi degli errori, che verranno analizzati con la fase successiva.

La verifica del risultato[modifica]


Completato il programma è frequente la presenza di errori derivanti da ragioni varie.

La fase di verifica e di messa a punto del programma è detta debugging ed ha lo scopo di ricercare e


correggere gli errori riscontrati, detti bug. Si tratta di una fase molto lunga ed importante in cui
il programmatore verifica la bontà del proprio lavoro. La correzione di un bug potrebbe essere causa di
nuovi errori, occorre quindi prestarci la massima attenzione.

Per evitare un debugging di un programma troppo complesso ed articolato è preferibile creare


un prototipo, ovvero una versione del risultato finale che non presenta in se tutte le funzioni previste dal
progetto originale, ottenendo una maggiore velocità di correzione dei bug principali.

Alla fine di questa fase avremo il prodotto finito. Le operazioni svolte durante lo sviluppo vanno
documentate così da rendere più semplice una futura modifica.

Lo sviluppo in ambito aziendale[modifica]


Lo sviluppo di un sistema di programmi all'interno di un'azienda fa parte di un processo molto più ampio
di analisi e progettazione. Il risultato oltre ad essere efficiente deve soddisfare specifiche richieste
dell'attività aziendale per cui è pensato.

Inizialmente si procede con un' analisi dettagliata dei problemi che la creazione del programma mira a
risolvere. L'analista deve proporre queste informazioni e stilare delle proposte idonee in sede di
progettazione.

Conclusa l'analisi, si passa alla progettazione del nuovo sistema. Tale operazione coinvolge un grande
numero di persone e di idee. I migliori progetti saranno scelti e sviluppati secondo un' ottica di
guadagno economico e di efficienza.

Approvato il progetto migliore si passa allo sviluppo. Ciò consiste nell'acquisto del
materiale software (ed eventualmente di quello hardware) necessario alla verifica del funzionamento
del nuovo sistema. Per molte aziende il software presente sul mercato risulta spesso inadatto alle
proprie esigenze ed è necessario lo sviluppo di programmi personalizzati o la modifica di quelli già
esistenti. A questo scopo esistono altre ditte specializzate in questo tipo di servizi.

Una volta creato e verificato il nuovo sistema, si procede all'installazione dello stesso all'interno
dell'azienda ed al suo funzionamento a pieno regime. Tale impatto può essere traumatico per
un'azienda abituata a vecchi sistemi, ragion per cui si procede in diverse maniere, secondo il caso:

 L'installazione diretta, in cui si disattiva il vecchio sistema e si sostituisce col nuovo appena
creato. Se tale sostituzione presenta dei problemi non previsti in fase di sviluppo, non
esiste backup dei vecchi programmi, causando enormi problemi. Tale soluzione è adottata soltanto
in assenza di alternative valide.
 L'installazione parallela, in cui il lavoro previsto per il nuovo sistema è distribuito in parti uguali
su di esso e su quello obsoleto, in modo da far fronte ad un eventuale problema del nuovo
utilizzando temporaneamente il vecchio. Quando il nuovo sistema raggiunge un discreto livello di
affidabilità, sostituisce totalmente il vecchio.

 L'installazione scaglionata, in cui il nuovo sistema è introdotto per gradi, man mano che
vengono risolti gli errori riscontrati, esso sostituisce il vecchio secondo varie fasi. Adottando tale
soluzione, eventuali problemi avranno conseguenze meno disastrose interessando soltanto una
singola fase. Svantaggio di questo tipo di installazione sono i tempi molto lunghi.

 L'installazione pilota, in cui il nuovo sistema viene utilizzato soltanto per una piccola parte
delle attività aziendali e, se funzionante regolarmente, viene esteso a tutta l'azienda. In caso di
problemi essi risulteranno ristretti soltanto a quella parte di attività che adotta il nuovo sistema,
senza pregiudicare l'intera attività aziendale.

Superata l'installazione, il programma fornirà all'azienda un servizio efficiente e regolare, richiedendo


comunque manutenzione, in cui vengono risolti i problemi riscontrati ed introdotti cambiamenti attui a
migliorare le prestazioni dei programmi.

Esempio: addizione di due numeri[modifica]


Il programma più semplice ed intuitivo è sicuramente quello che presi due numeri in input, restituisce
come output la loro somma. A seconda del linguaggio di programmazioneche si utilizza la struttura
cambia e si articola in maniera diversa.

 In un linguaggio macchina un determinato comando x1 carica un numero che si trova in


una locazione di memoria y1 (generalmente definita da una cifra esadecimale) all'interno
della CPU. Il comando x2 somma il numero che si trova nella locazione di memoria y2 con quello
caricato precedentemente. Infine un comando x3 trasferisce il risultato ottenuto in una locazione di
memoria y3 rendendolo disponibile per nuove operazioni.

 In un linguaggio assembly si definiscono tre locazioni di memoria che indicheremo con le lettere


A, B, C. Quando il programma parte esso carica nella CPU il numero presente in A e lo somma con
quello che si trova nella posizione B memorizzando il risultato in C.

 In un linguaggio BASIC il programma da semplicemente la direttiva che il numero


nella locazione di memoria C deve essere uguale alla somma dei numeri nelle posizioni A e B.

Programmi Decisionali[modifica]
Per approfondire, vedi la voce Struttura di controllo.

I programmi informatici risultano essere molto più articolati di un processo lineare come l'addizione di
due numeri. Per dare al programma una struttura più complessa si utilizzano i seguenti strumenti:
 Le diramazioni consistono nel fornire al codice delle funzioni che possono cambiare lo
svolgimento dell'algoritmo a seconda del risultato della condizione espressa.

 I cicli sono sequenze di istruzioni eseguite ripetutamente fin quando non viene soddisfatta una
determinata condizione. Ogni ripetizione è detta iterazione.