<--! Converted with AFC/easyHTML (c) Francesco De Napoli --> The New AMIGAzette - L'evoluzione della programmazione: dagli Spaghetti Code agli Oggetti. Prima parte.
L'evoluzione della programmazione: dagli Spaghetti Code agli Oggetti.
Prima parte.

Oggi si fa un gran parlare di OOP, e spesso a sproposito, viene da molti additata come la panacea a tutti i mali che affliggono la dura arte dello sviluppo del software, purtroppo cosí non é. La loro posizione é comprensibile essendo quasi tutti Tool Vendor con almeno un linguaggio di 4ª generazione, incapsulato in un prodotto Computer Aided Software Engineering,a listino. Un prodotto CASE é uno strumento che, almeno secondo le intenzioni di chi lo produce e vende, aumenta la produttivitá del gruppo di sviluppo che lo utilizza, fornendo sofisticati strumenti per l'analisi del problema e lo sviluppo del software.

Nonostante i buoni propositi, possiamo affermare che siamo ancora in una fase pionieristica dello sviluppo del software, dove si naviga ancora a naso, ma ci sono sufficienti indizi per ritenere che siamo giunti quasi alla fine del tunnel. Ci si incomincia a rendere conto che fino ad ora si é proceduto quasi senza alcun criterio, affidandosi per lo piú alla buona sorte o all'intuito dei singoli membri dei vari gruppi di sviluppo, e ci si domanda se esista un modo diverso di procedere. I prodotti CASE e la OOP sono solo alcuni degli ultimi tentativi di trovare una via universalmente valida per affrontare il complesso problema dello sviluppo del software, e certamente non saranno gli ultimi.

In principio era il Linguaggio Macchina, estremamente potente, oscuro, poco versatile e fonte dell'esaurimento di tanti informatici dell'epoca, i quali erano costretti a pensare ed operare direttamente con sequenze di 0 ed 1. Le sequenze dovevano essere immesse manualmente direttamente nella memoria del calcolatore. All'epoca programmare un computer non era certo un attivitá da poco, ad ogni errore era necessario cominciare tutto da capo! Il passo successivo fu quello di associare un codice mnemonico a ciascuna sequenza di bit che costituiva un comando per l'elaboratore, in questo modo gli esseri umani potevano finalmente impiegare un linguaggio a loro piú consono, ed era lo stesso calcolatore ad eseguire la traduzione da codice mnemonico in sequenze di bit, una volta inserito il sorgente nella memoria del calcolatore. Era nato il linguaggio Assembly, un primo tentativo di astrazione dall'architettura del processore, anche se famiglie di processori diversi adottavano, per forza di cose, codici mnemonici diversi. Nonostante il grande vantaggio offerto dall'Assembly, la gestione dei progetti di grande dimensione era ancora estremamente difficile. La maggior parte dei programmatori non riesce a tenere ben a mente il codice (ed il suo scopo) se questo eccede un paio di schermate, ed essendo le istruzioni Assembly molto elementari é necessario accorparne molte per eseguire un compito anche banale.

Il passo successivo fu compiuto dai tecnici dell'IBM.

Crearono un linguaggio ad un livello di astrazione piú alto rispetto l'Assembly, e lo battezzarono Fortran, dalla contrazione delle parole Formula Translator.

Il Fortran era un linguaggio studiato per risolvere problemi matematici, a differenza di quanto accade oggi, i computer erano usati esclusivamente da centri di ricerca o grandi organizzazioni che dovevano macinare enormi quantitá di calcoli. Il vantaggio consisteva nello scrivere i programmi in modo ancora piú intellegibile per gli esseri umani, e come per l'Assembly lo stesso calcolatore si sarebbe sobbarcato l'oneroso lavoro di tradurlo in Linguaggio Macchina.

Un effetto collaterale non trascurabile fu: la portabilitá del software. Fino ad allora adattare un programma ad un diverso calcolatore equivaleva alla sua ristesura, ora era sufficiente che sull'altra macchina esistesse un compilatore Fortran. La strada era spianata, e spuntarono come funghi altri linguaggi, per lo piú dedicati a compiti specifici.

Come non citare il LISP (LISt Processor), ProLog, COBOL (COmmon Business Object Language), Forth...

Nonostante la disponibilitá di strumenti piú versatili, la maggior parte dei programmatori continuava ad utilizzarli allo stesso modo dell'Assembly. I programmi sviluppati erano scarsamente organizzati, farciti di salti a subroutine, condivisione di tutti i dati, spesso i programmi erano infestati da subroutine gemelle, semplicemente perchè non si ricordava piú di aver giá risolto un determinato problema. Questo genere di programmi fu bollato come "Spaghetti Code", in quanto il sorgente risultava contorto ed intrecciato come un piatto di spaghetti.

Successivamente fece la comparsa il Basic (Beginner's All-purpose Symbolic Instruction Code), avvicinando alla programmazione anche i neofiti, contribuí al dilagare dello Spaghetti Code.

Essendo dispendioso programmare si tendeva a ridurre al minimo il numero di linee, e per far ció si effettuavano frequenti salti da un punto ad un altro, rendendo la situazione ancora piú contorta, ed impossibile da decifrare da altri programmatori, o dallo stesso autore del codice a distanza di tempo.

L'istruzione piú usata era il GOTO, trasposizione ad alto livello della JUMP comune a tutti gli Assembly, tanto che in breve tempo é nato un comitato anti-goto, ed ancora oggi si tende a denigrare chi si ostina ad usarli, anche se la maggior parte dei linguaggi continuano ad offrire tale obsoleto comando, ma che in alcune situazioni rappresenta l'unica via elegante.

Esempio di SpaghettiCode

Il primo tentativo di arginare l'improvvisazione imperante fu quello della "scomposizione" del codice.

Il software, o meglio l'intero progetto doveva essere decomposto in sotto unitá, ciascuno era indipendente dagli altri, e raggruppava subroutine omogenee, dette procedure. Non piú sorgenti chilometrici, ma piccole unitá piú facilmente gestibili. In questo modo si costruivano delle collezioni di routine (il piú possibile) generiche, dette librerie, che potevano essere reciclate, ovvero usate anche per risolvere analoghi problemi sorti in altri progetti, agevolando cosí lo sviluppo di nuovo software, e soprattutto rendendo piú economica l'operazione, poichè erano necessarie meno ore-uomo per completare ciascun lavoro. In questo modo si cerca di confinare il caos all'interno delle singole procedure, rendendo l'aspetto del programma meno ingarbugliato.

Con la Programmazione Procedurale si cerca di scomporre rigidamente il problema iniziale in sottoproblemi sempre piú elementari, con la filosofia, spesso vincente in Informatica del "Divide et Impera", sbriciolando la complessitá del progetto, in modo che sia facilmente dominabile.

Una volta decomposto il progetto, é piú facile assegnare a diversi programmatori le singole parti, e solo quando tutte le parti sono state realizzate e testate si procede alla ricucitura delle varie unitá.

Affinchè tutto ció sia fattibile é necessario lo scambio di informazioni non solo tra i componenti del software, ma anche tra i membri del gruppo di sviluppo. Si comincio a parlare di "interfaccia" e di "astrazione", e di "documentazione" delle specifiche di ciascuna unitá, per far ció era necessario pianificare tutto nei minimi dettagli prima di avviare la fase di codifica vera e propria, che si riduceva a semplice traduzione delle specifiche in un linguaggio comprensibile dalla macchina. Questo modo di procedere consente ai vari membri del gruppo di conoscere il lavoro affidato a ciascuno di essi, evitando cosí lo spreco di risorse preziose per sviluppare subroutine gemelle, ma é anche possibile eliminare o rimpiazzare qualche programmatore, o aggiungerne altri nel tentativo di accelerare lo sviluppo, i nuovi arrivati devono solo studiare la dettagliata documentazione del progetto.

Il passo successivo fu quello di passare dalla scomposizione del progetto alla Programmazione

Strutturata, nella quale si adottano particolari accorgimenti stilistici, che impediscono la scrittura di codice contorto, eliminando il caos residuo anche dall'interno delle procedure, cosí il sorgente guadagna in leggibilitá e chiarezza, ed piú facile farne la manuntenzione a distanza di tempo. Nei linguaggi compaiono comandi tipo REPEAT/UNTIL e WHILE,che consentono di realizzare cicli, che a differenza di quelli realizzati con il comando FOR, sono di tipo dinamico, ovvero il ciclo viene ripetuto fino a quando non si verifica un evento, o una condizione non é piú valida, situazione che in precedenza veniva simulata con controlli IF/THEN e salti GOTO. Un ottimo strumento per strutturare il programma é la realizzazione del FlowChart.

Si tratta di un diagramma che rappresenta il flusso delle elaborazioni che verranno eseguite dal calcolatore.

Piú che di una metodologia di programmazione vera e propria, si puó parlare di uno stile di programmazione atto a conferire, a programmi che di per sè sarebbero intricati, l'aspetto di un flusso ordinato tra un inizio ed una fine. I programmi continuano a venir scritti secondo il paradigma procedurale, ma prestando attenzione alla strutturazione delle singole procedure, e non solo dell'intero progetto.

Questa tecnica non richiede particolari doti del linguaggio di programmazione, ma solo buon senso in chi coordina lo sviluppo, ció nonostante sono apparsi linguaggi specifici per la Programmazione Strutturata.

Il piú famoso é il Pascal del professore Nicholas Wirth, il quale desiderava creare un linguaggio che obbligasse i suoi allievi a strutturare il programma prima di realizzarlo. Infatti nel Pascal, prima di utilizzare una variabile o chiamare un subroutine (dette function o procedure a seconda che restituiscano piú o meno esplicitamente un risultato) é necessario che queste siano state dichiarate. Il fatto stesso di distinguere tra una subroutine che passa, alla chiamante, esplicitamente un risultato da una che non lo fa é significativo delle intenzioni del professore Wirth. Proprio questa estrema rigiditá lo rende antipatico a molti programmatori sia professionisti che dilettanti, spingendoli spesso verso il C, nato soli pochi anni dopo, ma che consente al programmatore di scegliere come organizzare il proprio lavoro, ovviamente i migliori risultati non si ottengono con l'improvvisazione. La diversa impostazione é dovuta al fatto che il linguaggio C era stato ideato da programmatori per programmatori.

Infatti nacque dalla specifica esigenza di riscrivere, in un linguaggio ad alto livello e portabile, il neonato sistema operativo Unix, in pecedenza integralmente scritto in Assembly. L'obbiettivo primario del linguaggio era di astrarre, ma anche di mantenere la possibilitá di agire a bassissimo livello come un Assembly piú evoluto.

Nelle prossime due puntate proseguiremo l'analisi delle varie tecniche di programmazione.

Francesco De Napoli