[idpsg] - Factory Method
BarraGialla.gif (2134 bytes)

Aggiornamento: 6 giugno 1999

domanda.gif (1131 bytes) Domanda di inizio

Factory Method: "In che modo il metodo Factory promuove un codice in cui è basso l'accoppiamento?"

(How does Factory Method promote loosely coupled code?)
Domanda posta il 12 maggio 1999 da M.Planchestainer su base NYDPSG

Alcuni interventi dalle prime email (12-14 maggio):

U.Landini: L'obiettivo principale del design (visto ad un basso livello) è comunque sempre quello di minimizzare l'accoppiamento (Low Coupling) e aumentare la coesione (High Cohesion).
L'accoppiamento è il grado di interdipendenza fra un metodo e l'ambiente circostante, dunque altri metodi, oggetti e classi, mentre la coesione è il grado di uniformità che ha lo scopo del metodo.

M.Planchestainer: E' vero, e non vale solo per i metodi, che sono operazioni associate a classi/oggetti, ma in genere per tutte le funzioni/procedure/operazioni che ci possono essere in un programma. E non solo. Si può parlare di basso accoppiamento anche tra moduli o package, quando le funzioni interne di ogni modulo non presentano dipendenze da dati o funzioni presenti in un altro modulo. La regola di mantenere basso l'accoppiamento vale dunque anche per il design dei moduli.
Idem per la coesione, dove essa esprime la capacità di una parte di un programma (funzione, procedura, modulo, package) di avere uno scopo definito il più possibile. Equivale a creare funzioni che fanno una cosa ben precisa, moduli che riuniscono funzionalità omogenee, ... e via così.

U.Landini:
ACCOPPIAMENTO
Minimizzare l'accoppiamento di un metodo vuol dire quindi renderlo più facilmente riusabile in un contesto diverso. Naturalmente questo deve esprimere una tendenza, perchè non è possibile scrivere tutti metodi disaccoppiati, o il programma non farebbe nulla!
Posto che lo stato di un'oggetto è la "fotografia" dei suoi attributi in un preciso istante, tutti i metodi si possono dividere in tre grandi classi diverse:

Utility: non usa nè modifica lo stato dell'oggetto per es: Integer.toString(int), Math.cos(double)
State View: usa lo stato dell'oggetto per es: TextField.getText(), Object.toString()
State Change: modifica lo stato dell'oggetto per es: Vector.addElement(..), Hashtable.clear()

Ognuno di questi tipi di metodi tratta l'input e l'output in uno o più dei seguenti modi:

INPUT
può prendere parametri d'ingresso
può prendere dati da attributi e metodi "statici" (di classe)
può prendere dati da attributi e metodi (d'istanza)
OUTPUT
può tornare un valore, di tipo primitivo o "handle"
può alterare oggetti passati come parametro
può alterare attibuti "statici" direttamente o attraverso metodi "statici"
può alterare attibuti direttamente o attraverso metodi
può lanciare un'eccezione

Un metodo "utility" è quello che può raggiungere il minimo accoppiamento possibile:
INPUT
prende solo parametri d'ingresso e solo dati di cui ha effettivamente bisogno per produrre output
OUTPUT
ritorna un valore, di tipo primitivo o "handle", oppure altera oggetti passati come parametro i dati in output sono tutti prodotti da lui stesso (non chiama altri metodi)

Un metodo "State/View" con il minimo accoppiamento invece:
INPUT
prende parametri d'ingresso e usa attributi o metodi (sia di classe che di istanza) appartenenti alla sua classe (cioè da dovunque tranne che da variabili di classe di altre classi, escluse le costanti)
OUTPUT
torna un valore, altera parametri oppure lancia un'eccezione

Un metodo "State/Change" con il minimo accoppiamento invece:
INPUT
prende parametri d'ingresso e usa attributi o metodi (sia di classe che di istanza) appartenenti alla sua classe (cioè da dovunque tranne che da variabili di classe di altre classi, escluse le costanti)
OUTPUT
torna un valore, altera parametri, lancia un'eccezione, oppure lo esprime attraverso attributi e metodi (sia di classe che di istanza) appartenenti alla sua classe (in qualunque maniera tranne che con variabili di classe di altre classi)


COESIONE
Un metodo è coesivo qundo fa una sola, precisa cosa, ma a livello concettuale, non fisico. Un modo di vedere se un metodo è poco coesivo è quando non si riesce a dargli un nome, oppure il nome è troppo generico (nome di metodo -> verbo). Se passiamo un parameto ad un metodo e questo fa cose diverse a seconda del parametro, stiamo abbassando la coesività. E' comunque in alcuni casi controproducente massimizzare la coesività:

handleKey(char c){
switch (c){
...
}
}

è molto meglio di handleAkey(), handleBKey, handleCKey(), ecc.

Essenzialmente, queste sono le linee guida:
un metodo deve fare una sola cosa (a livello concettuale)
un metodo non deve demandare ad un parametro il suo comportamento
bisogna trovare un bilanciamento fra l'esplosione del numero dei metodi e la coesione, usando ... esperienza e buon senso

.......

.......