Linguaggi e Metodologie Orientate agli Oggetti

OOA OOD Object Oriented Analysis, Object Oriented Design
Breve introduzione alle metodologie di analisi e progettazione orientate agli oggetti con riferimenti ai metodi Booch, OMT, UML
OOPL Object-Oriented Programming Languages
Panoramica sui principali linguaggi di programmazione orientati agli oggetti
Linguaggio Java
Stimoli e documentazione
Linguaggio C++
Alcune peculiarità spiegate attraverso esempi

Introduzione

In questa scheda sono affrontati argomenti molto vasti e complessi che prendono in rassegna un aspetto dell'ingegneria del software, cioè le metodologie Object Oriented per la progettazione dei programmi e vengono esaminati brevemente i principali linguaggi di programmazione orientata agli oggetti.

Le tecniche d'approccio ai vari argomenti, presentati nelle quattro sezioni di questa scheda, sono volutamente diversificate per ogni tipo di argomento: si va da una discorsiva digressione sugli aspetti della progettazione del software (OOA, OOD), per poi passare attraverso una elencazione dei linguaggi OO principali. Il linguaggio Java viene poi presentato attraverso un flash che evidenzia le principali caratteristiche utilizzando uno stile simile alla presentazione di slide con voci correlate; infine, del linguaggio C++ vengono presentati solo alcuni aspetti peculiari attraverso esempi.

Per tutti gli argomenti viene fornita un'ampia documentazione sotto forma di riferimenti bibliografici, link a siti internet, o riproduzione di documenti di libero utilizzo.

Per navigare attraverso gli argomenti di questa scheda, viene fornito un percorso schematico che riassume le parti fondamentali del presente lavoro.


1. OOA OOD: metodologie di analisi e progettazione orientate agli oggetti

Object Oriented Analysis e Object Oriented Design

Prima di affrontare i linguaggi veri e propri è interessante fare alcune brevi considerazioni su come si programma a livello professionale, cosa che può tornare utile sia al principiante sia all’esperto; cercheremo inoltre di rimarcare l’importanza del disegno nello sviluppo di un qualunque programma. Nelle schede "suggerimenti link e bibliografia", troverete molto materiale cui fare riferimento; ci limiteremo qui ad alcuni consigli e considerazioni generali.

La tecnologia ad oggetti è spesso adottata per le sue grandi promesse: classi riusabili, applicazioni estendibili, maggior manutenibilità, facilità di test. In conclusione, migliore qualità del prodotto finale.

Tuttavia, per ottenere realmente tali benefici è necessaria una notevole esperienza che si acquisisce solo attraverso il lavoro su grandi progetti. Non è quindi raro che l'introduzione della tecnologia ad oggetti nello sviluppo del software non sia seguita dai tanto attesi miglioramenti.

Molti programmatori affrontano il problema da risolvere semplicemente associando le classiche procedure o funzioni della programmazione strutturata ai metodi della programmazione orientata agli oggetti; associano le variabili globali della prima alle variabili di classe della seconda e via dicendo. Risultato: una programmazione procedurale incapsulata in una sintassi orientata agli oggetti. Evidentemente si tratta di un approccio sbagliato. Non per niente è più semplice per un principiante imparare a programmare ad oggetti, che per un vecchio programmatore procedurale. Quando programmiamo ad oggetti dobbiamo abbandonare il paradigma basato su azioni indipendenti. Non dobbiamo pensare in termini di cosa fare, ma di far lavorare insieme oggetti che si scambiano informazioni cioè messaggi [Conte96 - cap.1]. In pratica dobbiamo strutturare il nostro ambiente come un mondo virtuale in cui esseri di varia natura, chiamati oggetti, comunicano fra loro richiedendosi reciprocamente servizi e scambiandosi dati. 

Ogni oggetto appartiene ad una categoria, le cui responsabilità sono ben definite. Tali categorie si chiamano classi. Le capacità che ha ogni oggetto di comunicare e di compiere attività specifiche si chiamano metodi. Le informazioni gestite direttamente dall'oggetto e che sono parte integrante della sua definizione, sono le sue variabili interne, che determinano il suo stato. Esistono poi metodi e oggetti detti di classe perché tipici dell'intera categoria piuttosto che del singolo oggetto. Le classi possono essere poi organizzate secondo una gerarchia ereditaria del tipo: il gatto è un carnivoro, ma è anche, più in generale, un mammifero; e un mammifero è un animale.

La programmazione Object Oriented è diventata lo stile di programmazione nell'industria del software negli ultimi anni. La ragione di questo è da ricercare nella crescita di dimensione dei progetti software.

E' diventato estremamente difficile riuscire a capire un programma sviluppato con approccio procedurale una volta che esso raggiunge una certa dimensione. I programmi Object Oriented sono più semplici da scrivere, capire e mantenere.

Le ragioni fondamentali sono:

 i programmi OO tendono ad essere scritti in termini di oggetti del mondo reale; questo fa sì che siano più semplici da capire, ma rende più difficoltoso il loro progetto iniziale;

 i programmi OO incoraggiano l'incapsulamento: i dettagli dell'implementazione di un oggetto sono nascosti all'utilizzatore dell'oggetto (client);

 i programmi OO incoraggiano la modularità.

Questo significa che "porzioni" di programma non dipendono da altre porzioni del programma stesso. Queste porzioni possono essere riutilizzate in futuri progetti rendendo più semplice la realizzazione dei nuovi lavori.

La programmazione OO, confrontata con l'approccio procedurale, richiede un lavoro inizialmente più difficile, perché il compito di identificare gli oggetti e di individuare i messaggi, comporta una serie di operazioni complesse.

Il processo di disegno del software è tipicamente diviso in due fasi distinte: Object Oriented Analysis (OOA) e Object Oriented Design (OOD).

Nella fase OOA, le domande che ci porremo saranno: "Di che cosa il mio programma necessita?", "Quali classi saranno presenti nel mio programma?", "Qual è la responsabilità di ciascuna classe?".

Ci sono tre attività che si devono fare nella fase dell'analisi:

Una buona analisi ha queste caratteristiche: le classi sono relativamente piccole e molte di queste sono abbastanza generali da prevedere di poterle usare in futuri progetti; le responsabilità e il controllo sono distribuiti, in altre parole il progetto non ha un centro esplicito; ci sono poche assunzioni riguardo al linguaggio di programmazione da usare.

Nella fase OOD ci chiederemo: "Come gestirà la classe le sue responsabilità?", "Quali informazioni sono necessarie alla classe?", "Come comunicheranno le classi tra loro?", "Come le informazioni passano attraverso il nostro sistema?". In conclusione ci chiederemo: "Quali sono gli attributi e i metodi che ciascuna classe deve avere?".

Una classe raramente viene costruita senza metterla in relazione in qualche modo con altre classi. Per descrivere graficamente le relazioni tra un insieme di classi inserite in un progetto si usano dei simboli particolari. La simbologia e la nomenclatura adottata in questa presentazione si ispira a quella utilizzata nel testo [Booch 94, cap.5].

La relazione di ereditarietà, che denota una relazione di specializzazione (o generalizzazione), viene anche chiamata relazione isa (is-a = è un) oppure inheritance link e viene descritta graficamente da una freccia (oppure un triangolo in OMT) che va dalla classe derivata alla classe base.

Un'altra interdipendenza importante è la relazione di aggregazione (o composizione) detta relazione has (o composition link o consists-of), che esprime il contenimento da parte di una classe, detta classe aggregato, di altri oggetti o di puntatori ad altri oggetti. Di questi oggetti contenuti nella classe aggregato, si indica la classe di appartenenza. Gli oggetti contenti dipendono dalla vita della classe che li contiene. Il simbolo grafico che descrive questo tipo di relazione, è costituito da una doppia linea che congiunge le due classi in relazione ed un cerchio pieno (oppure un rombo in OMT) dal lato della classe aggregato o classe possessore.

L'ultimo tipo di legame è la relazione di "utilizzo" da parte di una classe di una o più classi (talvolta chiamata anche broadcast link), viene chiamata relazione using * e verrà descritta graficamente da una doppia linea che congiunge le classi in relazione con un cerchio vuoto dal lato dell'utilizzatore. In questo caso un oggetto necessita delle informazioni dell'altro oggetto, ma i due oggetti in relazione using hanno una vita indipendente.

Si possono inserire vicino alle linee di relazione dei numeri indicanti la cardinalità della relazione (l'autovettura possiede minimo quattro ruote e in generale 4+scorta).

Chiariamo i concetti esposti utilizzando un diagramma delle classi che si commenta da solo:

Un esempio di relazioni tra classi 


Altre metodologie di analisi usano simbolismi diversi e individuano diversamente taluni tipi di relazioni.

Nella metodologia Booch, ma anche il altre metodologie, oltre ai diagrammi di classi, come abbiamo visto, esistono altri tipi di diagrammi che specificano altri aspetti della analisi e progettazione del software.

Per esempio mella metodologia UML (che sta imponendoso come uno standard per la progettazione del software) esistono diversi tipi di diagrammi: diagramma delle classi, diagramma degli oggetti, diagramma dei casi d'uso, diagramma di sequenza, diagramma di collaborazione, diagramma di stato, diagramma di attività, diagramma delle componenti e diagramma di dislocazione.

La metodologia UML deriva dalle metodologie OMT e Booch, e risulta piuttosto complessa per essere affrontata in un corso di informatica delle scuole superiori; mentre invece OMT risulta un buon compromesso fra la semplicità e la completezza.

Chi prova ad avvicinarsi alla progettazione attraverso le metodologie del tipo Coad, Booch, OMT, UML, etc, si accorge rapidamente che l'enfasi viene posta sulla produzione di diagrammi.


*Il termine using viene utilizzato da Booch nei suoi primi testi, come pure il disegno della nuvoletta per indicare la classe.
Nelle specifiche UML si trova un più ricco e completo insieme di relazioni tra classi.


2. OOPL: linguaggi di programmazione orientati agli oggetti

Object-Oriented Programming Languages

Molte delle idee concernenti la OOP hanno le proprie radici nel Linguaggio SIMULA (Dahl & Nygaard, 1966), ma la prima sostanziale implementazione di Linguaggio Object- Oriented, interattiva e basata su un vero e proprio ambiente di sviluppo integrato, è stato SMALLTALK (Goldberg & Robson, 1983).

SIMULA aveva già in sé i concetti di oggetto, classe e sottoclasse, ma mancava del concetto di messaggio; è ancora usato per problemi di simulazione di sistemi, ma non si può considerare un linguaggio OOP.

Ci sono almeno una ventina di principali linguaggi orientati agli oggetti che vengono utilizzati dalle scuole e dalle software house, ma i principali linguaggi OO usati commercialmente si riducono a Smalltalk, C++ e Java.

Faremo una rapida carrellata sui più noti o curiosi linguaggi orientati agli oggetti, per ulteriori informazioni si rimanda alla ricca bibliografia allegata.

Scrivere qualcosa che confronti diversi linguaggi di programmazione porta spesso a dispute interminabili, che in gergo informatico vengono chiamate "guerre sante". I partecipanti a queste dispute cercano di spacciare motivazioni personali, di gusto o di tradizione culturale, come obiettive valutazioni tecniche. Noi abbiamo cercato di descrivere i vari linguaggi in modo da scontentare il minor numero di adetti ai lavori.


La programmazione OO offre un nuovo e potente modello per scrivere programmi: gli oggetti sono "black box" che mandano e ricevono messaggi (argomento trattato in altre schede).

Questo approccio velocizza lo sviluppo del software e rende migliore il mantenimento, la riusabilità e la modificabilità del codice, ma richiede un maggior sforzo iniziale per la progettazione della soluzione.

Il linguaggio C++ offre ai programmatori tradizionali di passare gradualmente dalla programmazione procedurale tradizionale alla programmazione ad oggetti, ma sovente il loro stile di programmazione rimane un ibrido tra i due paradigmi. Se ben utilizzato permette una potenza d'astrazione notevole, il suo difetto (o pregio per alcuni) è che non obbliga il programmatore ad un approccio alla soluzione OO pura.

Smalltalk offre un ambiente ad oggetti puro anche se i programmi non raggiungono l'efficienza di una soluzione C++.

Il linguaggio Java promette un ambiente ad oggetti puro, con l'innovazione di poter creare applicazioni per la rete. Lo tratteremo più diffusamente in seguito.

 


Riportiamo una lista di link alle informazioni essenziali di alcuni linguaggi di programmazione orientati agli oggetti.

Ada Smalltalk C++ Eiffel
Blue CLOS Java Schema linguaggi

    


3. Java: panoramica sul linguaggio

Java rappresenta probabilmente la più importante innovazione della telematica in generale, e di Internet in particolare, dopo la creazione di World Wide Web. Il linguaggio Java, che deve il suo nome a una varietà di caffè tropicale, è stato sviluppato dalla Sun Microsystem, una delle maggiori aziende informatiche del mondo, ed è stato inizialmente ideato per essere incorporato nei microchip che governano gli elettrodomestici.

Un programma scritto in Java può essere eseguito indifferentemente su ogni sistema operativo e su ogni piattaforma senza subire modifiche. In secondo luogo Java è progettato appositamente per lo sviluppo di applicazioni distribuite. Questo significa che un'applicazione Java può essere costituita da più moduli, residenti su diversi computer, in grado di interoperare attraverso una rete telematica. Un programma Java può essere inserito direttamente all'interno di una pagina Web. Queste versioni Web dei programmi Java si chiamano applet, e vengono incluse nei documenti Web attraverso uno speciale marcatore del linguaggio HTML: <APPLET> nelle specifiche precedenti a HTML 4.0, e <OBJECT> nelle specifiche HTML 4.0 (W3C Recommendation, 24-Apr-1998).

Ogni volta che il documento ospite viene richiesto da un browser, l'applet viene inviata dal server insieme a tutti gli altri file multimediali: se il browser è in grado di interpretare il linguaggio, il programma viene eseguito. In questo modo le pagine Web possono animarsi, integrare suoni in tempo reale, visualizzare video ed animazioni, presentare grafici dinamici, trasformarsi virtualmente in ogni tipo di applicazione interattiva.

In questa sezione faremo una breve presentazione del linguaggio Java, o meglio, di alcuni aspetti del linguaggio. Utilizzeremo una descrizione fatta di schemi riassuntivi, che si presta facilmente ad essere adattata a formare delle slide per le lezioni. Gli argomenti, che sono trattati in modo sintetico, sono solo uno stimolo per il lettore affinchè approfondisca l'argomento nei testi dedicati a questo linguaggio.

La principale fonte di informazioni sul linguaggio Java è senz'altro da ritenersi il pacchetto di Sun Microsystem Java Developers Kit (JDK) del quale forniamo (vedi in materiali) una versione stabile adatta alla didattica.

Della Sun Microsystem riportiamo i link ai siti da dove si può scaricare materiale interessante per lo studio del linguaggio, e dove troviamo un piccolo corso su Java.


4. C++: peculiarità

Questa sezione è sviluppata prendendo spunto dal testo [Conte 96] ed i riferimenti ai capitoli si riferiscono allo stesso libro.

Il linguaggio C ++ è abbastanza particolare. Esistono tre modalità fondamentali d'utilizzo:

 come un linguaggio procedurale simile al linguaggio C ma migliorato in molti aspetti: controllo sui tipi, uso dei riferimenti (Cap.4.4 e Cap.6), sovrapposizione delle funzioni (Cap.6.5), funzioni parametrizzate (Cap.6.6);

 come un linguaggio che supporta l'astrazione dei dati o, meglio, che permette la creazione di nuovi tipi e la definizione delle operazioni su questi nuovi tipi: è possibile la realizzazione di un oggetto la cui implementazione resti nascosta, e non permetta la modifica interna dello stato dell'oggetto se non tramite una opportuna funzione (metodo) definita appositamente (Cap.7);

 come un linguaggio orientato agli oggetti che permette cioè la definizione di classi, l'istanziazione di oggetti, la derivazione ed il polimorfismo (Cap 7.7) e permette di risolvere il problema interpretandolo come un'interrelazione tra oggetti.

Questi molteplici aspetti del linguaggio possono rappresentare un vantaggio per il programmatore che sceglierà lo stile di programmazione più appropriato ai problemi che dovrà risolvere.


In questa sezione tratteremo solamente la sovrapposizione degli operatori, le classi generiche (template), partendo da alcuni esempi; faremo inoltre un esempio introduttivo di definizione di una semplice classe.