# Fondamenti di programmazione

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 il software individua gli errori più banali che un programmatore può commettere.

## Le Fasi della programmazione

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

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

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 dalle linee 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

Al fine di creare un programma efficiente occorre progettarne con attenzione l'algoritmo. Ad esempio potremmo creare un algoritmo che esegue i seguenti passi:
* Esamina una lista di numeri e riconosci quello più basso;
* Inserisci il numero più basso nella variabile X;
* 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 il programma in funzioni (informatica).

### La codifica del programma

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 dallo pseudocodice, 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

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 sé 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

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

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 programmazione che 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

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.

## Le Tecniche di Programmazione

Esistono varie tecniche di programmazione, le più comuni ed utilizzate sono le seguenti:
* Programmazione non strutturata - in cui il programma è costituito da un unico blocco di istruzioni (detto main) che vengono eseguite in maniera sequenziale.
* Programmazione procedurale - in cui vi sono blocchi di istruzioni che fungono da sottoprogrammi e svolgono funzioni ben definite.
* Programmazione modulare - in cui è possibile utilizzare procedure messe a disposizione da altri programmi e permettere a questi di poter utilizzare le proprie.
* Programmazione orientata agli oggetti - in cui vengono creati degli "oggetti" che possono funzionare autonomamente o interagire tra di loro. Ogni oggetto possiede in sé delle specifiche proprietà e funzioni (se ipotizziamo come oggetto un'automobile, una caratteristica sarà il suo colore o la sua marca e le funzioni saranno l'accelerare o il frenare).