• Non ci sono risultati.

Programmazione Modulare

N/A
N/A
Protected

Academic year: 2021

Condividi "Programmazione Modulare"

Copied!
25
0
0

Testo completo

(1)

G. Mecca – Università della Basilicata – mecca@unibas.it

Programmazione Procedurale in Linguaggio C++

Sottoprogrammi Parte 4

Programmazione Modulare

versione 2.2

Questo lavoro è concesso in uso secondo i termini di una licenza Creative Commons (vedi ultima pagina)

Sommario

m

Introduzione

m

Diagramma delle Chiamate

m

Regole di Visibilità

ðDati Locali e Dati Globali

m

Compilazione Separata

Sottoprogrammi: Programmazione Modulare >> Sommario

(2)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 3

Introduzione

m

Programmazione modulare

ðun’applicazione è fatta di una serie di moduli ðprogramma principale (main)

ðsottoprogrammi (procedure e funzioni)

m

Funzionamento

ðsi inizia con l’esecuzione del “main”

ði vari moduli si chiamano a vicenda ðcomunicando attraverso i parametri

Sottoprogrammi: Programmazione Modulare >> Introduzione

4

Introduzione

m

Nella lezione precedente

ðaspetti “tecnologici” della programmazione modulare

ðcosa offre la tecnologia dei sottoprogrammi

m

In questa lezione

ðaspetti “metodologici” legati alla programmazione modulare

ðcome è opportuno utilizzare i sottoprogrammi

Sottoprogrammi: Programmazione Modulare >> Introduzione

(3)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 5

Introduzione

m

Aspetti metodologici

ða) albero delle chiamate

ðb) regole di visibilità e utilizzo dei dati

ðc) compilazione separata e “riuso” del codice

m

Successivamente

ðd) metodologia di sviluppo per raffinamenti successivi

ðe) linee guida per la scrittura di codice di qualità

Sottoprogrammi: Programmazione Modulare >> Introduzione

Diagramma delle Chiamate

m

In un programma modulare

ði moduli dipendono gli uni dagli altri

ðper ogni chiamata il chiamante “dipende” dal chiamato

m

Diagramma delle chiamate

ðdiagramma che rappresenta le relazioni di dipendenza tra i moduli

ðogni modulo è un elemento

ðgli archi descrivono le dipendenze

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

(4)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 7

Esempio: Equazioni di II Grado

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

main

procedura leggiEquazione

funzione primaRadice

funzione discriminante

funzione secondaRadice

procedura stampaRadici

8

Diagramma delle Chiamate

m

Perché è importante

ðaiuta a ragionare sul livello di

“accoppiamento” tra i moduli

ðe sulla logica applicativa del programma

m

Livello di accoppiamento di un modulo

ðnumero di moduli del programma da cui il

modulo dipende

ðcioè che chiama direttamente o indirettamente

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

(5)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 9

Esempio: La Morra Cinese

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

main

inizioGioco gioca

schermo MenuPrincipale

schermoFinale

schermoIniziale nuovaPartita schermoVittorie

schermo

MenuPartita nuovaMano schermo EsitoPartita

genera

GiocataComputer controllaEsito schermo EsitoMano

Diagramma delle Chiamate

m

Attenzione al livello di accoppiamento

ðtanto più è alto il livello di accoppiamento di

un modulo, tanto più il modulo dipende da altri moduli

ðse uno o più degli altri moduli è scorretto, il modulo si comporta scorrettamente

ðse uno o più degli altri moduli cambiano prototipo, bisogna cambiare anche il modulo ðsi tratta di fenomeni negativi

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

(6)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 11

Diagramma delle Chiamate

m

Tipicamente

ðil main dipende da tutti gli altri moduli

m

In generale, però

ðè importante che il diagramma sia

organizzato per livelli (vedi metodologia) ði moduli a livello più alto dipendono da quelli

a livello più basso

ðai livelli più bassi l’accoppiamento deve diminuire progressivamente

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

12

Diagramma delle Chiamate

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

main

modulo A

modulo B

modulo C

modulo D

modulo E In questo caso il diagramma delle chiamate

è molto “disordinato”, e i moduli sono tutti fortemente accoppiati; è un sintomo di logica applicativa confusa

(7)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 13

Diagramma delle Chiamate

m

Inoltre

ðsi tratta di un ottimo strumento per studiare il funzionamento di un programma scritto da altri

m

Metodo

ðcostruire il diagramma (specificando anche i parametri dei sottoprogrammi)

ðseguire il diagramma per studiare il funzionamento

Sottoprogrammi: Programmazione Modulare >> Diagramma delle Chiamate

Regole di Visibilità

m

A questo punto

ðpossiamo descrivere le regole di visibilità complete del linguaggio

m

Regole di visibilità

ðinsieme di regole che stabiliscono cosa può essere utilizzato in ciascun modulo

ðquali dati possono essere utilizzati

ðquali altri moduli possono essere utilizzati

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

(8)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 15

Regole di Visibilità

m

Utilizzare un dato

ðutilizzare una costante, una variabile o un parametro in una istruzione

ðovvero effettuare un’operazione sul corrispondente spazio nella memoria

m

Utilizzare un sottoprogramma

ðutilizzare una funzione o una procedura ðovvero chiamare il sottoprogramma

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

16

Regole di Visibilità

m

Regola di visibilità n.1

ð“prima dichiarare e poi usare”

ðun dato o un sottoprogramma può essere utilizzato solo se è stato precedentemente dichiarato

m

Significato di “precedentemente”

ðnelle istruzioni che precedono il punto in cui l’oggetto deve essere usato

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

(9)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 17

Regole di Visibilità

m

In altri termini

ðil compilatore ha bisogno di conoscere informazioni su cosa viene usato per verificare la correttezza dell’uso

m

Esempio: variabile

ðè necessario verificarne il nome ðè necessario verificarne il tipo

ðla regola enunciata era già scontata

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

Regole di Visibilità

m

Per quanto riguarda i sottoprogrammi

ðil compilatore deve verificare che la chiamata sia corretta

ðdeve verificare il nome

ðdeve verificare il numero ed il tipo dei parametri

ðdeve verificare la natura dei parametri (standard o per riferimento)

ðdeve verificare l’eventuale tipo del risultato

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

(10)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 19

Regole di Visibilità

m

Soluzione n. 1

ðl’ordine in cui sono definiti i sottoprogrammi rispecchia l’ordine delle chiamate

m

Soluzione sgradevole

ðobbliga a preoccuparsi dell’ordine di valutazione

ðè innaturale (non rispecchia l’organizzazione del metodo e del diagramma delle chiamate, dal più generale al più particolare)

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

>> equazioni1.cpp

20

Regole di Visibilità

m

Soluzione n. 2

ðle informazioni necessarie sono tutte contenute nell’intestazione (o prototipo) ðviene usato il prototipo per “annunciare” il

sottoprogramma

ðla definizione viene fornita successivamente

m

In questo modo

ðposso organizzare i sottoprogrammi più liberamente

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

>> equazioni2.cpp

(11)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 21

Regole di Visibilità

m

Prototipo di un sottoprogramma

ðintestazione del sottoprogramma seguita da ; ðserve ad annunciare l’esistenza del

sottoprogramma al compilatore

ðdescrive il modo in cui può essere utilizzato

m

ATTENZIONE

ðdeve esserci il ; finale

ðsuccessivamente deve comparire la definizione completa del sottoprogramma

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

ATTENZIONE alla sintassi per la definizione dei prototipi

Regole di Visibilità

m

La seconda regola di visibilità

ðriguarda i dati visibili in ciascun modulo di programma

m

Prima di enunciarla

ðdettagli sulle dichiarazioni dei dati ðdati “locali”

ðdati “globali”

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

(12)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 23

Dati Locali e Dati Globali

m

Dati locali

ðdati dichiarati all’interno di un modulo ðcorrispondono ad uno spazio di memoria ðcostanti simboliche, variabili, parametri

m

Ogni modulo ha i suoi dati locali

ði dati sono “indipendenti”: i dati di un modulo non sono visibili all’interno di un altro

ðpossono avere nomi uguali

ðcorrispondono a spazi di memoria diversi

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

24

Dati Locali e Dati Globali

void leggiEquazione (float &a, float &b, float &c) { cout << "Inserisci i coefficienti dell'equazione \n";

cin >> a;

cin >> b;

cin >> c;

return;

}

float primaRadice (float a, float b, float c){

float x;

x=(-b+sqrt(discriminante(a,b,c)))/(2*a);

return x;

}

float secondaRadice (float a, float b, float c){

float x;

x=(-b-sqrt(discriminante(a,b,c)))/(2*a);

return x;

}

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

Dati locali -3 parametri per riferimento (a,b,c) Dati locali

-3 parametri standard (a,b,c)

-1 variabile (x)

Dati locali

-3 parametri standard (a,b,c)

-1 variabile (x) Spazi diversi nella memoria

Spazi diversi nella memoria

(13)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 25

Dati Locali e Dati Globali

m

Dati globali

ðcostanti e variabili dichiarate al di fuori di tutti i moduli (dichiarate “a livello di file”)

ðsono comuni a tutti i moduli

m

Utilizzo tipico

ðcostanti utilizzate da molti moduli

ðè utile poterle definire una volta per tutte

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

Dati Locali e Dati Globali

const int MANI = 3;

void main() { string nome;

inizioGioco(nome);

gioca(nome);

schermoFinale(nome);

}

void inizioGioco(string& nome) { int seme = time(NULL);

srand(seme);

schermoIniziale(nome);

return;

}

int generaGiocataComputer() { int giocata;

giocata = rand()/100%3 + 1;

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

Dati locali

- 1 variabile (nome) Dati globali - 1 costante (MANI) Dati locali

- 1 parametro per riferimento (nome) - 1 variabile (seme) Dati globali - 1 costante (MANI) Dati locali

- 1 variabile (giocata) Dati globali

(14)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 27

Dati Locali e Dati Globali

m

A questo punto

ðè possibile enunciare la regola generale

m

Regola di visibilità n. 2

ðin ciascun modulo sono sempre visibili tutti i dati locali

ði dati globali sono visibili a meno che nel modulo non sia dichiarato un dato locale con lo stesso nome

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

ATTENZIONE alle regole di

visibilità

28

Dati Locali e Dati Globali

const int n = 1000;

float cubo(float numero);

void main() { int numero;

cin >> numero;

if (numero <= n)

cout << cubo(numero);

}

float cubo (float numero) { float n;

n = numero * numero * numero;

return n;

}

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

Dati locali

- 1 variabile intera (numero)

Dati globali

- 1 costante intera (n)

Dati locali

- 1 parametro standard (numero)

- 1 variabile reale (n) In questo modulo NON è visibile la costante n

(15)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 29

Dati Locali e Dati Globali

m Variabili globali

ðè possibile definire anche variabili globali, ovvero spazi della memoria utilizzabili in tutti i moduli del programma

m Attenzione, questo fatto ha delle conseguenze

ðconsente ai moduli del programma di comunicare attraverso le variabili globali

ðoltre che attraverso il passaggio dei parametri

ðun modulo può cambiare il valore di una var globale e questo cambiamento è visibile negli altri moduli

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

Dati Locali e Dati Globali

m

Un esempio

ðil parametro “nome” della morra cinese ðne viene acquisito il valore all’inizio

dell’applicazione, e poi viene passato a moltissimi dei sottoprogrammi

ðsembrerebbe un ottimo candidato a diventare una variabile globale

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

>> morraCinese4.cpp

(16)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 31

Dati Locali e Dati Globali

m

In questo modo però

ðintroduco un livello molto più alto di accoppiamento tra i sottoprogrammi

ðmodifiche alla variabile globale fatte in un sottoprogramma influenzano il

funzionamento di tutti gli altri

ðesempio: generaGiocataComputer() e i vari schermi in cui viene stampato il nome

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

32

Esempio: La Morra Cinese

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

main

inizioGioco gioca

schermo MenuPrincipale

schermoFinale

schermoIniziale nuovaPartita schermoVittorie

schermo

MenuPartita nuovaMano schermo EsitoPartita

genera

GiocataComputer controllaEsito schermo EsitoMano

>> morraCinese5.cpp generaGiocataComputer

(17)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 33

Dati Locali e Dati Globali

m

In sintesi

ðsi tratta di una forma di comunicazione tra i moduli che non usa i parametri

ðaumenta molto il livello di accoppiamento ðse usata sistematicamente rende di difficile

comprensione il codice

m

Metodologicamente

ðnon utilizzeremo MAI variabili globali

ðè opportuno invece utilizzare costanti globali

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

Dati Locali e Dati Globali

m

Riassumendo le linee guida sui dati

ði sottoprogrammi possono utilizzare costanti e variabili locali

ðle funzioni è opportuno che abbiano solo parametri standard

ðle procedure possono avere sia parametri standard che per riferimento

ðè possibile utilizzare costanti globali

ðnon è opportuno utilizzare variabili globali

Sottoprogrammi: Programmazione Modulare >> Regole di Visibilità

(18)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 35

Compilazione Separata

m

Organizzazione del codice sorgente

ðpuò essere organizzato in vari file ði file possono essere compilati

separatamente

ðe poi collegati assieme successivamente

m

Esempio tipico

ðun file per i sottoprogrammi

ðun file per il programma principale

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

36

Compilazione Separata

m

Per effettuare la compilazione separata

ðnel file del programma devono esserci i

prototipi dei sottoprogrammi chiamati

ðsoluzione tipica: definire un file di intestazioni

m

File di intestazioni (“header file”)

ðfile contenente i prototipi dei sottoprogrammi ðtipicamente il file ha estensione .h

ðviene incluso nel programma principale per effettuare correttamente la compilazione

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

>> morraCinese6.cpp

(19)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 37

Compilazione Separata

m Attenzione alla sintassi della #include

m Per le librerie di sistema: parentesi acute

ð #include <iostream.h>

#include <fstream.h>

ðil file .h viene cercato tra le cartelle di sistema (specificate nel file di configurazione)

m Per le librerie dell’utente: virgolette

ð #include “morraCinese6Lib.h”

ðil file .h deve essere nella stessa cartella in cui c’è il file in cui compare la include

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

Compilazione Separata

m

Semantica della #include

ðha l’effetto di includere letteralmente il contenuto del file specificato all’interno del file in cui compare

ðistruzione per istruzione

m

Esempio: morraCinese6.cpp

ð#include “morraCinese6Lib.h”

ðè come se il file morraCinese6.cpp

contenesse i prototipi dei sottoprogrammi

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

(20)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 39

Compilazione Separata

m

In effetti, nel caso della Morra Cinese

ðquesto meccanismo è del tutto inutile ðuso più interessante: creazione di “librerie”

m

Libreria

ðcollezione di sottoprogrammi ðutilizzabili in applicazioni diverse

m

Esempio

ðlibreria per l’analisi di equazioni di II grado

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

>> equazioni3Lib.cpp

>> equazioni3Lib.h

40

Compilazione Separata

m

Esempio: equazioni3.cpp

ðun’applicazione su equazioni di II grado (main più eventuali altri sottoprogrammi) ðutilizza la libreria equazioni3Lib.cpp

ðinclude il file di intestazioni equazioni3Lib.h ðpuò essere compilato indipendentemente

dalla libreria usando l’opzione –c di bcc32 ðal termine deve essere collegato con il

codice oggetto della libreria

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

(21)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 41

Compilazione Separata

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

Compilazione programma principale

equazioni3.cpp

Collegamento codice oggetto equazioni3.obj

codice eseguibile equazioni3.exe

#include<iostream.h>

#include”equazioni3Lib.h”

void main() { ...

}

equazioni3Lib.h

void leggiEquazione (float&a, float&b, float&c);

float discriminante (float a, float b, float c);

...

#include<iostream.h>

void leggiEquazione (float&a, float&b, float&c) {

cout << “Coefficienti: ”;

cin >> a;

...

equazioni3Lib.cpp

Compilazione

codice oggetto equazioni3Lib.obj bcc32 -c

bcc32 -c

ilink32 + opzioni complesse In alternativa: posso compilare e collegare contemporaneamente usando solo bcc32

Compilazione Separata

m

Utilizzo del collegatore della Borland

ðcompilo i due file di codice sorgente

bcc32 –c equazioni3Lib.cpp bcc32 –c equazioni3.cpp

ðcollego con il comando (complesso !)

ilink32 /Tpe c0x32 equazioni3.obj equazioni3Lib.obj,

equazioni3.exe,,import32 cw32 m

Una soluzione molto più semplice

ðbcc32 equazioni3.cpp equazioni3Lib.cpp

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

(22)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 43

Compilazione Separata

m

Concludendo

ðuna libreria C/C++ è fatta normalmente di due file

ðun file con le intestazioni dei sottoprogrammi ðun file con le definizioni dei sottoprogrammi

m

Terminologia

ðfile di intestazioni: “interfaccia” della libreria ðfile di definizioni: “implementazione” della lib.

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

44

Compilazione Separata

m

Interfaccia della libreria

ðtutte le informazioni che è necessario conoscere per chiamare i sottoprogrammi

m

Implementazione della libreria

ðtutte le informazioni che è necessario conoscere per eseguire i sottoprogrammi

m

Il programmatore

ðdeve conoscere necessariamente la prima e non la seconda

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

ATTENZIONE alla differenza tra

interfaccia e implementazione

(23)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 45

Compilazione Separata

m

Idealmente

ðun programmatore scrive un’applicazione sulla libreria basandosi sull’interfaccia ðutilizza inizialmente una specifica

implementazione

ðsuccessivamente l’implementazione può essere cambiata (migliorata, corretta) senza che sia necessario cambiare il codice

dell’applicazione scritta (basta ricompilare)

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

Compilazione Separata

m

Idea alla base di questo meccanismo

ð“riuso” del codice (un “mito” informatico) ðsviluppare il codice è costoso

ðper quanto possibile, bisognerebbe evitare di sviluppare di nuovo soluzioni già esistenti

m

Utilità delle librerie

ðcollezione di sottoprogrammi di utilizzo sufficientemente generale

ðdi correttezza verificata

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

(24)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 47

Compilazione Separata

m

In generale

ðè importante puntare al riuso del codice

ðè una “filosofia” a cui deve essere improntata tutta l’attività di programmazione

m

In realtà, però

ðil principale limite dei linguaggi procedurali è che non consentono un riuso adeguato

ðanche per questo sono stati soppiantati dai linguaggi orientati agli oggetti

Sottoprogrammi: Programmazione Modulare >> Compilazione Separata

48

Riassumendo

m

Programmazione Modulare

ðapplicazione fatta di moduli che si chiamano a vicenda

m

Aspetti Metodologici

ðdiagramma delle chiamate ðdati locali e globali

ðcompilazione separata ðlibrerie

ðinterfaccia e implementazione

Sottoprogrammi: Programmazione Modulare >> Sommario

(25)

G. Mecca - Programmazione Procedurale in Linguaggio C++ 49

Termini della Licenza

m This work is licensed under the Creative Commons Attribution- ShareAlike License. To view a copy of this license, visit

http://creativecommons.org/licenses/by-sa/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

Termini della Licenza

m Questo lavoro viene concesso in uso secondo i termini della licenza “Attribution-ShareAlike” di Creative Commons. Per ottenere una copia della licenza, è possibile visitare

http://creativecommons.org/licenses/by-sa/1.0/ oppure inviare una lettera all’indirizzo Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

Riferimenti

Documenti correlati

Concetti Introduttivi: Linguaggi &gt;&gt; Ciclo di Vita di un Programma.. Mecca - Programmazione Procedurale in Linguaggio

Sottoprogrammi: Metodologia di Sviluppo &gt;&gt; Tecniche di Test e

Sottoprogrammi: Conclusioni &gt;&gt; Errori Frequenti. giocataComputer

ðDefinizione di Funzioni ðDefinizione di Procedure ðChiamata di Funzioni ðChiamata di Procedure ðPassaggio dei Parametri ðProgrammazione Modulare. Termini

ði riferimenti sono “tipati”: ogni riferimento può essere intermediario per dati di un solo tipo ðes: riferimento a intero, riferimento a

Strutture di Dati: Lista &gt;&gt; Rappresentazione con Record e Array. ATTENZIONE ai

Strutture di Dati: Lista &gt;&gt; Inserimenti e Cancellazioni. Mecca - Programmazione Procedurale in Linguaggio

Strutture di Dati: Lista &gt;&gt; Gestione dei File. i conta il numero di valori prelevati dal