prof. Nunzio Brugaletta | Programmazione e linguaggio C |
Accade spesso, specie nei problemi complessi, che una stessa sequenza di istruzioni compaia nella stessa forma in più parti dello stesso programma o che sia utilizzata in più programmi. Gli algoritmi riguardano elaborazioni astratte di dati che possono essere adattate a problemi di natura apparentemente diversi (dal punto di vista informatico due problemi sono diversi se necessitano di elaborazioni diverse e non se trattano di cose diverse). Per fare un esempio riguardante altre discipline basta pensare per esempio alla Geometria: il calcolo dell’area di una superficie varia in relazione alla forma geometrica diversa e non alla natura dell’oggetto. L’area di una banconota o di una lastra di marmo si calcolerà sempre allo stesso modo trattandosi in ambedue i casi di rettangoli, quindi per tornare all'ambito informatico, l’elaborazione riguardante il calcolo dell’area di un rettangolo ricorrerà nei problemi di calcolo di blocchi di marmo così come nei problemi di calcolo di fogli su cui stampare banconote.
Per risparmiare un inutile lavoro di riscrittura di parti di codice già esistenti, i linguaggi di programmazione prevedono l’uso dei sottoprogrammi. Sostanzialmente un sottoprogramma è una parte del programma che svolge una funzione elementare.
L’uso di sottoprogrammi non è solo limitato al risparmio di lavoro della riscrittura di parti di codice, ma è anche uno strumento che permette di affrontare problemi complessi riconducendoli a un insieme di problemi di difficoltà via via inferiore. Tutto ciò consente al programmatore un controllo maggiore sul programma stesso nascondendo nella fase di risoluzione del singolo sottoprogramma, le altri parti in modo tale da isolare i singoli aspetti del problema da risolvere.
Si tratta del procedimento di stesura per raffinamenti successivi (o top-down). Quando la complessità del problema da risolvere cresce, diventa difficoltoso tenere conto contemporaneamente di tutti gli aspetti coinvolti, fin nei minimi particolari, e prendere contemporaneamente tutte le decisioni realizzative: in tal caso sarà necessario procedere per approssimazioni successive, cioè decomporre il problema iniziale in sottoproblemi più semplici. In tal modo si affronterà la risoluzione del problema iniziale considerando in una prima approssimazione risolti, da altri programmi di livello gerarchico inferiore, gli aspetti di massima del problema stesso. Si affronterà quindi ciascuno dei sotto-problemi in modo analogo.
In definitiva si comincia specificando la sequenza delle fasi di lavoro necessarie anche se, in questa prima fase, possono mancare i dettagli realizzativi: si presuppone infatti che tali dettagli esistano già. Se poi si passa all’esame di una singola fase di lavoro, questa potrà ancora prevedere azioni complesse ma riguarderà, per come è stata derivata, una parte del problema iniziale. Iterando il procedimento mano a mano si prenderanno in esame programmi che riguardano parti sempre più limitate del problema iniziale. In tal modo la risoluzione di un problema complesso è stata ricondotta alla risoluzione di più problemi semplici (tanti quante sono le funzioni previste dalla elaborazione originaria).
Le tecniche di sviluppo per raffinamenti successivi suggeriscono cioè di scrivere subito il programma completo, come se il linguaggio di programmazione a disposizione fosse di livello molto elevato ed orientato proprio al problema in esame.
Tale programma conterrà, oltre alle solite strutture di controllo, anche operazioni complesse che dovranno poi essere ulteriormente specificate. Queste operazioni verranno poi descritte in termini di operazioni ancora più semplici, e così via fino ad arrivare alle operazioni elementari fornite dal linguaggio di programmazione utilizzato.
http://ennebi.solira.org | ennebi@solira.org |