La modellazione Object Oriented è una disciplina al confine tra l’arte e la scienza.
Come arte non può prescindere da fattori quali l’inventiva, la bellezza e l’innovazione; come scienza non può ignorare i principi fondamentali sui quali si basa.
L’OOAD è quindi la disciplina che consente di gestire questo mondo di confine, di padroneggiare i principi base e di allenare la mente ad un pensiero Object Oriented.
Il corso Object Oriented Analysis and Design di K-Tech è articolato in cinque moduli:
1. Origini e concetti fondamentali della OOP
2. Qualità del Software e Metodologie di Sviluppo
3. Pensare ad Oggetti e Modellazione
4. GRASP
5. Altri principi della OOD
Programma completo del corso:
http://www.k-tech.it/formazione/corso_object_oriented_analysis_design
1. Corso
Object Oriented Analysis and Design
Modulo 4: GRASP
Leggi il programma completo del corso
www.javaportal.it | www.k-tech.it corsi@k-tech.it
2. Obiettivi
● Comprendere le tecniche di programmazione
orientata agli oggetti
● Modellare e ‘pensare’ ad oggetti
● Riconoscere gli oggetti
● Identificare gli oggetti a cui delegare le
responsabilità
www.javaportal.it | www.k-tech.it corsi@k-tech.it 2
3. Agenda
Cap 1 - Origini e concetti fondamentali della OOP
Cap 2 - Qualità del software e metodologie di sviluppo
Cap 3 - Pensare ad Oggetti e Modellazione
►Cap 4 - GRASP◄
Cap 5 - Altri principi della OOD
www.javaportal.it | www.k-tech.it corsi@k-tech.it 3
4. GRASP
GRASP: General Responsibility Assignment Software Patterns
Usato nella modellazione OO, fornisce le guide linea per
l'assegnazione delle responsabilità a classi ed oggetti
● Creator
● Controller
● Expert
● Low Coupling
● High Coesion
● Polymorphism
● Indirection
● Pure Fabbrication
● Protected Variations
www.javaportal.it | www.k-tech.it corsi@k-tech.it 4
5. Creator...
Introdotto da Larman ‘98
Ci fornisce le regole in base alle quali decidere
quale oggetto deve creare un nuovo oggetto.
Problema
Chi crea oggetti B?
Soluzione
Assegna alla classe A la responsabilità di creare istanze della
classe B se una delle seguenti proprietà è vera:
1. A contiene B;
2. A compone B;
3. A possiede i dati per inizializzare B;
4. A registra B;
5. A è fortemente accoppiato con B.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 5
6. ...Creator...
Ci fornisce le regole in base alle quali decidere
quale oggetto deve creare un nuovo oggetto.
Vantaggi:
● è favorito il basso accoppiamento;
● la classe creata deve essere visibile alla classe
creatrice;
● il creator implica minori dipendenze da manutenzione
e maggiori opportunità di riuso.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 6
7. ...Creator
Esempio:
Table
Table TableRow
newRow()
-rows TableRow
1 1..n
+newRow()
Table.java TableRow.java
public class Table {
private List<TableRow> rows; public class TableRow {
public Table() { //…Attributi omessi…
this.rows = public TableRow(){
new LinkedList<TableRow>(); }
} }
public newRow(){
TableRow row = new TableRow();
this.addRows(row);
}
//…Getter e Setter Omessi…
}
Table myTable = new Table();
myTable.newRow();
www.javaportal.it | www.k-tech.it corsi@k-tech.it 7
8. Controller
Introdotto da Larman ‘98
Problema
Quale è il primo oggetto oltre lo strato UI che riceve, coordina e
controlla gli eventi di input principali in un sistema? Quale è l'oggetto
che ha la responsabilità di ricevere e/o gestire un messaggio di una
operazione di sistema?
Soluzione
Occorre assegnare la responsabilità ad una classe in uno dei due
seguenti modi:
● tramite un Façade Controller che rappresenta il sistema
complessivo o un "oggetto radice" o il dispositivo all'interno del
quale il software viene eseguito o ancora un sottosistema
principale;
● tramite uno Use Case Controller che rappresenta uno scenario di
un caso d'uso (per esempio un handler).
www.javaportal.it | www.k-tech.it corsi@k-tech.it 8
9. Expert
Introdotto da Larman ‘98
Problema
Quale è il principio di base per l’assegnazione di responsabilità
agli oggetti?
Soluzione
Assegnare le responsabilità all'esperto, cioè a chi possiede le
informazioni necessarie per portare a termine il lavoro.
Vantaggi:
● viene mantenuto l'incapsulamento, e
l'accoppiamento è ridotto al minimo indispensabile;
● viene incoraggiato lo sviluppo di classi “coese", che
eseguono solo i comportamenti attesi.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 9
10. Basso Accoppiamento (Low Coupling)...
Introdotto da Larman ‘98
L’accoppiamento è la misura di quanto due elementi sono
legati tra loro. Si riferisce non tanto alle classi quanto ai moduli
Un modulo è una entità in cui è possibile suddividere un
software (sia esso una classe, un metodo, un package o altro)
Problema
Come ridurre l’impatto dei cambiamenti?
Soluzione
Assegnare le responsabilità in modo tale che l’accoppiamento
(non necessario) rimanga basso. Usare questo principio per
valutare le alternative.
GoF correlati: Adapter, Commad, Composite, Proxy, Strategy
www.javaportal.it | www.k-tech.it corsi@k-tech.it 10
11. ...Basso Accoppiamento (Low Coupling)
Esempi di accoppiamento
● la classe A ha un membro di tipo B;
● la classe A referenzia una istanza di B;
● A usa servizi di B;
● A ha un metodo che possiede un elemento di tipo B;
● A ha un metodo che possiede un elemento che referenzia una
istanza di B;
● A è una classe derivata direttamente o indirettamente dalla
classe B;
● A implementa una interfaccia di tipo B.
GoF correlati: Adapter, Commad, Composite, Proxy, Strategy
www.javaportal.it | www.k-tech.it corsi@k-tech.it 11
12. ...Basso Accoppiamento (Low Coupling)
Problemi derivanti da un alto accoppiamento:
● aumenta il rischio di modificare continuamente il modulo;
● i moduli collegati sono più difficili da isolare;
● i moduli collegati sono più difficili da riusare.
GoF correlati: Adapter, Commad, Composite, Proxy, Strategy
www.javaportal.it | www.k-tech.it corsi@k-tech.it 12
13. Alta Coesione (High Coesion)...
Introdotto da Robert C. Martin, 1996
Anche noto come “Single Responsibility Principle”.
Una classe dovrebbe avere un solo motivo per cambiare !!!
La coesione è la misura di quanto fortemente siano correlate e
concentrate le responsabilità di un elemento quale una classe o
un sottosistema. Un elemento caratterizzato da una alta
coesione possiede responsabilità correlate senza eseguire una
quantità di lavoro eccessiva.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 13
14. ...Alta Coesione (High Coesion)...
● Coincidente: un modulo composto da molte parti indipendenti.
● Logica: un modulo si compone dalle parti logicamente relative, ma senza altre
interazioni fra loro.
● Temporale: gli elementi sono raggruppati in un modulo perché tutti sono eseguiti
durante lo stesso periodo limitato nel tempo.
● Procedurale: un modulo si compone dalle parti in cui il controllo passa da un’attività
alla successiva.
● Comunicativa: tutti gli elementi di un modulo funzionano sullo stesso insieme di dati di
input e/o redigono gli stessi dati dell’output.
● Sequenziale: le attività del modulo sono organizzate in modo che l’output di una serva
da input alla seguente.
● Informativa: le funzioni multiple dello stesso modulo hanno accesso alla stessa
struttura o risorsa di dati che è nascosta all’interno del modulo.
● Funzionale: il modulo realizza esattamente un’azione, o realizza un singolo obiettivo.
Tutte le parti del modulo contribuiscono ad una funzione, niente altro è presente nel
modulo e tutto il necessario per lo svolgimento della funzione è nel modulo.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 14
15. ...Alta Coesione (High Coesion)
Problemi derivanti da una bassa coesione.
Un modulo con bassa coesione ha troppi comportamenti non
correlati (ha troppe responsabilità).
Di conseguenza il modulo risulta essere:
● difficile da isolare (nell'insieme);
● difficile da riutilizzare;
● difficile da manutenere.
● delicato poiché risulta dipendente da troppi fattori esterni;
● difficile da comprendere ovvero è difficile capire cosa faccia.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 15
16. High Coesion...
Esempio
SendMessageManager.java
public class SendMessageManager{
private final int SMS =0;
private final int EMAIL = 1;
private final int FAX = 2;
private void send(Object o, int sendType){
MessageSender mS = new MessageSender(); SITUAZIONE SCONSIGLIATA
switch(sendType){
case SMS: Il metodo send() modifica il
mS.sendSMS(o); proprio comportamento in base
break; al valore di un suo parametro.
case EMAIL:
mS.sendEMAIL(o);
break;
case FAX:
mS.sendFAX(o);
break;
default:
//doSomething MessageSender.java
break;
public class MessageSender{
} public void sendSMS(Object o){
} //doSomething
} }
public void sendEMAIL(Object o){
//doSomething
}
public void sendFAX(Object o){
//doSomething
}
}
SITUAZIONE SCONSIGLIATA
Metodi fortemente coesi in
classi diverse.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 16
17. ...High Coesion
Esempio
SendMessageManager.java
public class SendMessageManager{
public void sendSMS(Object o){
//doSomething
}
public void sendEMAIL(Object o){
//doSomething
}
public void sendFAX(Object o){
//doSomething
}
}
ULTERIORI MIGLIORAMENTI
Identificare le parti comuni dei tre metodi ed eseguire un
refactoring di Extract Method,
utilizzare poi il pattern Template Method o la stessa ereditarietà
per gestire i differenti formati.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 17
18. Polymorphism...
Introdotto da Larman ‘98
Le variazioni condizionali basate su costrutti come if-then-
else rendono l'estensione di una applicazione difficoltosa,
in quanto le modifiche diventano necessarie in svariati
punti.
Problema
Come gestire alternative basate sul tipo?
Soluzione
Quando le alternative o i comportamenti correlati variano con la
classe (tipo), occorre assegnare la responsabilità del
comportamento ai tipi per i quali esso varia. Questo si può
ottenere utilizzando operazioni polimorfe, ovvero assegnando lo
stesso nome a servizi simili o correlati in oggetti diversi.
Inoltre si può ottenere evitando l'utilizzo della logica condizionale
per eseguire alternative che variano in base al tipo.
GoF correlati: Adapter, Commad, Composite, Proxy, State, Strategy
www.javaportal.it | www.k-tech.it corsi@k-tech.it 18
19. ...Polymorhism...
Esempio Employee.java
class Employee { EmployeeType.java
private int _monthlySalary; abstract class EmployeeType {
private int _commission; public static final int ENGINEER = 0;
private int _bonus; public static final int SALESMAN = 1;
private EmployeeType _type; public static final int MANAGER = 2;
public Employee(int _monthlySalary, int _commission, abstract int getTypeCode();
int _bonus, EmployeeType _type) { }
this._monthlySalary = _monthlySalary;
this._commission = _commission;
this._bonus = _bonus;
this._type = _type;
}
int payAmount() { Engineer.java
switch (getType()) { class Engineer extends EmployeeType {
case EmployeeType.ENGINEER: int getTypeCode() {
return _monthlySalary; return EmployeeType.ENGINEER;
case EmployeeType.SALESMAN: }
return _monthlySalary + _commission; }
case EmployeeType.MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}
int getType() {
return _type.getTypeCode(); Manager.java Salesman.java
} class Manager extends EmployeeType { class Salesman extends EmployeeType {
} int getTypeCode() { int getTypeCode() {
return EmployeeType.MANAGER; return EmployeeType.SALESMAN;
} }
} }
SITUAZIONE SCONSIGLIATA
Variazione condizionale basata sul tipo.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 19
20. ...Polymorhism
Esempio Employee.java
class Employee { EmployeeType.java
private int _monthlySalary; abstract class EmployeeType {
private int _commission; public static final int ENGINEER = 0;
private int _bonus; public static final int SALESMAN = 1;
private EmployeeType _type; public static final int MANAGER = 2;
public Employee(int _monthlySalary, int _commission, abstract int getTypeCode();
int _bonus, EmployeeType _type) { abstract int payAmount(Employee emp);
this._monthlySalary = _monthlySalary; }
this._commission = _commission;
this._bonus = _bonus;
this._type = _type;
}
int getType() { Engineer.java
return _type.getTypeCode(); class Engineer extends EmployeeType {
} int getTypeCode() {
int payAmount() { return EmployeeType.ENGINEER;
return _type.payAmount(this); }
} int payAmount(Employee emp) {
public int getMonthlySalary() { return emp.getMonthlySalary();
return _monthlySalary; }
} }
public int getCommission() {
return _commission;
}
public int getBonus() {
return _bonus; Manager.java Salesman.java
} class Manager extends EmployeeType { class Salesman extends EmployeeType {
} int getTypeCode() { int getTypeCode() {
return EmployeeType.MANAGER; return EmployeeType.SALESMAN;
} }
int payAmount(Employee emp) { int payAmount(Employee emp) {
return emp.getMonthlySalary() + return emp.getMonthlySalary() +
emp.getBonus(); emp.getCommission();
} }
} }
POLIMORFISMO
www.javaportal.it | www.k-tech.it corsi@k-tech.it 20
21. Indirection...
Problema Introdotto da Larman ‘98
Dove assegnare una responsabilità per evitare l’accoppiamento
diretto tra due (o più) elementi? Come disaccoppiare degli
oggetti in modo da sostenere un accoppiamento basso e
mantenere alto il potenziale di riuso?
Soluzione
Occorre assegnare la responsabilità ad un oggetto intermedio
che funga da mediatore tra gli elementi coinvolti evitando
l'accoppiamento diretto.
Vantaggi
• aumentare le possibilità di riuso;
• mantenere un basso accoppiamento.
GoF correlati: Adapter, Bridge, Facade, Observer, Mediator
www.javaportal.it | www.k-tech.it corsi@k-tech.it 21
22. ...Indirection...
Esempio
Dipendente.java
public class Dipendente {
Dipartimento dipartimento;
public Dipartimento getDipartimento() { return dipartimento; }
public void setDipartimento(Dipartimento dip) { this.dipartimento = dip; }
}
Dipartimento.java
public class Dipartimento {
private Societa societa;
public Dipartimento(Societa societa) { this.societa = societa; }
public Societa getSocieta() { return societa; }
}
Societa.java
public class Societa {
String tipologia;
public String getTipologia() { return tipologia; }
public void setTipologia(String tipologia) { this.tipologia = tipologia; }
}
societa = john.getDipartimento().getSocieta();
INDIRECTION
www.javaportal.it | www.k-tech.it corsi@k-tech.it 22
23. ...Indirection
Esempio
Dipendente.java
public class Dipendente {
Societa societa;
public Societa getSocieta() { return societa; }
public void setSocieta(Societa societa) { this.societa = societa; }
}
Dipartimento.java
public class Dipartimento {
private Societa societa;
public Dipartimento(Societa societa) { this.societa = societa; }
public Societa getSocieta() { return societa; }
}
Societa.java
public class Societa {
String tipologia;
public String getTipologia() { return tipologia; }
public void setTipologia(String tipologia) { this.tipologia = tipologia; }
}
societa = john.getSocieta();
NO INDIRECTION
www.javaportal.it | www.k-tech.it corsi@k-tech.it 23
24. Pure Fabrication...
Introdotto da Larman ‘98
Problema
Quale oggetto deve avere le responsabilità quando si vuole
mantenere alta coesione e basso l'accoppiamento, ma la
soluzione suggerita dal pattern Expert non è appropriata?
Soluzione
Si assegna un insieme coeso di responsabilità ad una classe
artificiale che non rappresenta un concetto del dominio del
problema, ma che è una pura invenzione, per limitare
l'accoppiamento e favorire la coesione ed il riuso.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 24
25. ...Pure Fabrication
Decomposizione
● Decomposizione rappresentazionale: un oggetto viene
inventato in quanto rappresentazione astratta di un concetto del
dominio del problema.
● Decomposizione comportamentale: l'oggetto viene
individuato in base ad aspetti legati ad uno specifico
comportamento o ad un insieme di comportamenti correlati.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 25
26. Protected Variations
Introdotto da Larman ‘98
Problema
Come progettare oggetti, sottoinsiemi e sistemi in modo tale che
le variazioni o l’instabilità in questi elementi non abbiano un
impatto indesiderato su altri elementi?
Soluzione
Occorre individuare i punti critici in cui siano previste possibili
variazioni e instabilità.
Occorre quindi assegnare le responsabilità in modo tale da
creare, attorno ad esse, una interfaccia stabile.
Vantaggi
• eventuali estensioni al sistema;
• nuove implementazioni di parti del sistema;
• basso accoppiamento;
• il costo dei cambiamenti è ridotto.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 26