Back to home

Il sito per chi vuole studiare meglio

Gli anni '90

Gli anni '90 hanno visto l'affermarsi della OOP.
La Object Oriented Programming non consiste nello scrivere codice in un linguaggio diverso, ma nel pensare il programma in modo differente. Con la OOP i costrutti di programmazione rimangono inalterati, ma la loro combinazione è radicalmente diversa. L'ordine di scrittura del codice usato fino ad allora, muta. Non esiste più un programma principale, anche se oggi viene mantenuto per motivi di compatibilità e comodità, ma si focalizza l'attenzione marggiormente sulla soluzione pulita e corretta del problema, e non alla sua implementazione.
La OOP inoltre, apre la strada ai moderni linguaggi di programmazione: i cosiddetti linguaggi ad altissimo livello. Esempi di questi linguaggi sono Python, Perl. Gli stessi linguaggi di sviluppo in matematica come Matlab. Anche Arduino prevede la scrittura di classi per realizzare librerie che descrivono il comportamento di nuovi shield da collegare alla scheda.

Strutture Dati

L'uso di un linguaggio di programmagione ha sempre comportato una serie di problemi che, ad oggi, non sono stati del tutto risolti. Questi argomenti sono legati quella disciplina che va sotto il nome di Sviluppo del Software ovvero tutti gli strumenti messi in campo per realizzare un codice corretto senza errori. La complessità dei programmi oggi, è così elevata che non è pensabile produrre un software composto da migliaia, se non milioni di righe di codice, senza avere delle metodologie o protocolli, che garantiscano un rilascio sul mercato, di un programma corretto almeno per il 90%
Ciò che più colpisce nella scrittura di un programma in OOP, è il peso che assume la struttura dati all'interno del codice. L'esempio mostrato di seguito vuole mostrare il passaggio da una programmazione "tradizionale" a quella dove cominciano ad essere presenti i primi concetti della OOP. L'esempio inoltre pone l'attenzione sul problema descritto in precedenza. La OOP è la soluzione a molti dei problemi descritti e costituisce il nucleo per lo sviluppo del software in modo facile e rapido

Dalle struct alle Classi

Si consideri il seguente codice

struct PROVA
{
	char cognome[250];
	unsigned int eta;
}

void leggi (PROVA v[])
{
	unsigned int i;
	srand((unsigned)time(NULL));
	for (i=0; i<10; i++)
	{
		strcpy(v[i].cognome,"pippo");
		v[i].eta = rand()%100;
	}
}

double media (PROVA v[])
{
	double m=0.0; unsigned int i, somma=0;
	
	for (i=0; i<10; i++)
		somma +=v[i].eta;
	return m=(double)somma/N;
}


int _tmain(int argc, _TCHAR* argv[])
{
	PROVA p[N];
	PROVA prova;

	leggi(p);
	cout << "Età media = " << media(p);

	_getch();

	return 0;
}
   

Per un normale programmatore il codice risulta molto semplice. La struttura dati dichiarata rappresenta una variabile globale All'interno del file del programma, la sua visibilità è completa: la struttura può essere letta o scritta da qualunque funzione o anche dal main. Nella OOP significa che la struttura è dichiarata di tipo public. Non si dimentichi questa osservazione perchè le variabili pubbliche, insieme alla gestione della memoria tramite puntatori, hanno creato non pochi problemi ai programmatori in fase di correzione del codice ovvero in fase di debug. Si tenga presente che, in genere, la dimensione di un programma reale, raggiunge facilmente le migliaia di righe di codce. La fase di test e correzione del programma per queste dimensioni consuma molto tempo, ritardando il rilascio sul mercato del prodotto.

Per ovviare a queste ed altri svantaggi della programmazione imperativa "tradizionale" sono state formulate una serie di regole che ridefiniscono la struttura stessa del programma senza cambiare la sintassi. Tra le altre cose sono stati introdotti meccanismi di controllo del codice scritto, durante la fase di compilazione, in modo che il programma rispetti le regole della OOP ed evitare che nell'eseguibile finale siano presenti molti degli errori che il programmatore è solito compiere.

Dopo questa brevissiam descrizione di alcune carattristiche della OOP si consideri lo stesso codice ma riscritto in questo modo


struct PROVA 
{
	char cognome[250];
	unsigned int eta;

	void leggi (PROVA v[])
	{
		unsigned int i;
		srand((unsigned)time(NULL));
		for (i=0; i<10; i++)
		{
			strcpy(v[i].cognome,"pippo");
			v[i].eta = rand()%100;
		}
	}

	double media (PROVA v[])
	{
		double m=0.0; unsigned int i, somma=0;
		
		for (i=0; i<10; i++)
			somma +=v[i].eta;
		return m=(double)somma/N;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	PROVA p[N];
	PROVA prova;

	prova.leggi(p);
	cout << "Età media = " << prova.media(p);

	_getch();
		
	return 0;
}   
Il programma esegue le stesse funzioni, ma questa volta è presente una differenza sostanziale: le funzioni sono state inserite all'interno della struttura dati. Il programma è affetto dagli stessi problemi descritti in precedenza, ma basta una semplice modifca per passare dalla struttura dati classica ad una nuova e molto più potente, robusta e sicura struttura dati che è la classe La sintassi cambia veramente di poco, ma dopo la compilazione del codice, tutto cambia nella programmazione

      //struct PROVA {
class PROVA{
public:
	char cognome[K];
	unsigned int eta;

	void leggi (PROVA v[])
	{
		unsigned int i;
		srand((unsigned)time(NULL));
		for (i=0; i<10; i++)
		{
			strcpy(v[i].cognome,"pippo");
			v[i].eta = rand()%100;
		}
	}

	double media (PROVA v[])
	{
		double m=0.0; unsigned int i, somma=0;
		
		for (i=0; i<10; i++)
			somma +=v[i].eta;
		return m=(double)somma/N;
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	PROVA p[N];
	PROVA prova;

	prova.leggi(p);
	cout << "Età media = " << prova.media(p);

	_getch();
		
	return 0;
}