L’approccio di design che sta alla base delle architetture attuali è object oriented. Ciò non significa che tutti i componenti debbano essere costruiti con linguaggi object oriented, ma che i prìncipi generali della progettazione di applicazioni a componenti sono basati sull’orientamento agli oggetti.
Ma perché le architetture a componenti sono basate su prìncipi di progettazione object oriented?
Una diversa (e migliore) organizzazione del software.
L’attenzione e la progressiva diffusione dell’approccio object oriented sono legate al passaggio (avvenuto, all’incirca, nel decennio 1980-1990) dalle precedenti architetture monopiattaforma alle architetture distribuite, multipiattaforma. Questo cambiamento architetturale si è portato dietro alcune questioni concrete da risolvere: come distribuire i dati e le funzioni, che costituivano le vecchie applicazioni monolitiche, su una pluralità di processori cooperanti? Secondo quale logica? Come far colloquiare tra loro i diversi “pezzi applicativi”?
L’object oriented ha fornito a queste domande delle risposte innovative ed adeguate dal punto di vista tecnico, e soprattutto dal punto di vista dell’organizzazione del software.
Un’applicazione ad oggetti è costituita da un insieme di moduli software logicamente indipendenti, le classi, che incapsulano dati ed operazioni sui dati (risolvendo la distinzione tradizionale tra dati e funzioni), e che interagiscono tra loro tramite scambi di messaggi.
Rispetto ai moduli software tradizionali, le classi presentano alcuni vantaggi, sotto il profilo tecnico-organizzativo.
Elevata coesione interna, coupling limitato verso l’esterno.
Ogni classe è un componente coeso, che gestisce un insieme di dati omogenei e le operazioni che accedono a tali dati , e se necessario li modificano. Vantaggi:
- manutenibilità – le modifiche sui dati sono normalmente limitate all’ambito omogeneo della classe che li definisce, poiché i dati sono accessibili solo alle operazioni interne alle classi
- riusabilità – la classe fornisce tutte le operazioni significative per l’oggetto business, utilizzabili in contesti eterogenei
- distribuibilità – la classe è un elemento ideale per la distribuibilità, grazie alla sua coesione ed al sufficiente disaccoppiamento rispetto ad altre classi; nei casi in cui sia opportuno un livello di accorpamento maggiore, più classi accoppiate tra loro possono essere ricomprese in un unico componente distribuibile.
Separazione rigorosa di interfaccia ed implementazione.
Le richieste (messaggi) indirizzabili ad una classe sono definite esplicitamente (nome messaggio, parametri di input e di output): l’interfaccia della classe è costituita, precisamente, dall’insieme dei messaggi che un qualsiasi chiamante (client) può indirizzarle. L’implementazione della classe è invece inaccessibile ai client. Vantaggi:
- manutenibilità – ogni variazione all’implementazione di una classe non ha impatto sui client, se non si verificano variazioni a livello dell’interfaccia; è possibile sostituire completamente l’implementazione mantenendo la medesima interfaccia, senza impatti sui client.
- distribuibilità – le comunicazioni tra le classi avvengono esclusivamente tramite messaggi, indirizzabili sia in locale che in remoto.
Polimorfismo.
Classi diverse possono rispondere al medesimo messaggio, ciascuna in modo appropriato. Il client non ha necessità di conoscere la classe precisa a cui appartiene l’oggetto su cui sta lavorando, ma può inviare un messaggio generico la cui risposta dipenderà dalla classe a cui l’oggetto appartiene. Vantaggi:
- riduzione della complessità – la logica del client risulta semplificata, in quanto viene eliminata gran parte della logica condizionale legata al trattamento di oggetti di tipologia diversa
- manutenibilità – le modifiche ai comportamenti specifici, i quali implementano nelle diverse classi il modo specifico di rispondere ad un messaggio generico, sono localizzate nell’ambito delle singole classi, e non devono essere conosciute dai client.
Ereditarietà.
È possibile specializzare una classe esistente, ereditandone attributi
e comportamenti nella nuova classe, ed aggiungendo solo attributi ed
operazioni specifici per la nuova tipologia da gestire. Vantaggi:
- riusabilità – l’ereditarietà consente di distinguere in modo rigoroso gli aspetti comuni a più tipologie di oggetti da quelli specifici ad una tipologia particolare, riducendo il carico di programmazione e al tempo stesso garantendo una migliore organizzazione del codice.
- manutenibilità – le modifiche ad attributi ed operazioni comuni a più sottoclassi vengono localizzati al livello della sola superclasse, con una riduzione del carico di manutenzione.