15.3 I metodi di programmazione

Scrivere programmi è un’attività delicata poiché sebbene sia relativamente facile scrivere programmi, è difficile scrivere buoni programmi. Un buon programma non è quello che funziona, ma quello che, oltre a funzionare, permette un’agevole manutenzione. Di seguito sono elencate delle regole generali utili per la scrittura di buoni programmi, anche se l’esperienza e le capacità del programmatore rimangono comunque i fattori determinanti della bontà di un programma.

Quando si scrivono programmi, oltre a conoscere bene il linguaggio di programmazione utilizzato (la sua sintassi, le sue funzioni, ...) la prima cosa da non sottovalutare è la leggibilità del codice. Al computer non importa affatto della leggibilità del codice, ma è sufficiente che non vi siano errori di sintassi per poter eseguire il programma. Bisogna però considerare che quel programma andrà manutenuto o comunque eventualmente corretto e quindi la sua correzione (che potrebbe avvenire anche in un momento piuttosto distante da quello di termine dei lavori o da persone diverse da quelle che lo hanno scritto) risulterà di gran lunga agevolata quanto più sarà facile comprenderne il codice. A tal fine, oltre ad essere estremamente consigliato l’utilizzo di un linguaggio di programmazione ad alto livello, si possono utilizzare vari espedienti, come l’uso di nomi esplicativi di varibili e funzioni (v. sez. 15.4), l’uso adeguato di commenti e dell’indentazione2 delle istruzioni, ...

Per migliorare la leggibilità del codice è anche opportuno seguire le regole della programmazione strutturata3. Il riutilizzo di porzioni di codice già scritte è da incoraggiare, ma ciò non deve andare a scapito della comprensibilità del codice. In pratica, si tratta di eliminare i salti nell’ordine di esecuzione del codice a blocchi di istruzioni scritti qua e là nel programma (questo generalmente viene fatto con istruzioni tipo goto4), preferendo una logica di esecuzione sequenziale ed utilizzando costrutti più vicini alla logica umana, come quelli seguenti

La sintassi dei linguaggi ad alto livello contiene questi tipi di costrutti, che aiutano a rendere più agevole e chiara la scrittura del codice.

Esiste comunque anche un uso dei salti di esecuzione all’interno del codice che va incontro alla programmazione strutturata, ovvero che non va a scapito della chiarezza dei programmi. Questo accade quando tale istruzione è utilizzata per uscire dai cicli (anche annidati), anche se i linguaggi di programmazione mettono a disposizione apposite istruzioni per tale esigenza.

Parti di codice indipendenti e già collaudate, che devono essere riusate spesso nei programmi, possono essere utilizzate per formare delle librerie (ovvero scritte e compilate una volta per tutte e messe a disposizione per ulteriori utilizzi).

Inoltre, quando ci si accinge a scivere un programma è opportuno chiedersi se qualcun’altro si sia già scontrato con il problema che si tenta di risolvere, in modo da poterne eventualmente riutilizzare parte del codice (che magari è anche già testato).

Sempre nell’ottica di migliorare la riusabilità del codice, la sua comprensione e manutenibilità, è stata introdotta negli anni ’90 la programmazione ad oggetti (OOP - Object Oriented Programming) che estende il concetto classico di programmazione funzionale (o per funzioni), suddividendo il programma in un insieme di oggetti indipendenti di più facile manutenzione che possono essere riutilizzati in altri programmi, come blocchi precostruiti, agevolandone la realizzazione. Sono così nati i linguaggi di programmazione ad oggetti (come il Java, il C++, l’Eiffel, ...) che permettono la scrittura di codice ad oggetti. In particolare, la programmazione ad oggetti ha delle potenzialità in più rispetto alla programmazione funzionale, poiché ha il vantaggio di avere una relazione gerarchica tra gli oggetti, che permette di gestirne l’ereditarietà, ovvero la specializzazione degli oggetti ed il polimorfismo, cioè la capacità di un oggetto di comportarsi come un suo “antenato”.

Infine, per avere ulteriori garanzie di sicurezza, si può sfruttare la tecnica di programmazione per contratto (design by contract) di B. Meyer. Essa si basa sull’utilizzo di test sui dati subito prima della chiamata di un metodo (precondition) e subito dopo il suo ritorno (postcondition). In questo modo se il test fallisce significa che è inutile proseguire perché si andrebbe incontro a una situazione imprevedibile. Questo sistema rende leggermente più lenta la fase di scrittura del codice a vantaggio di una più agevole fase di debug.

[da completare ...]