La dura legge di Demetra

La legge di Demetra (Law of Demeter o LoD o Principle of Least Knowledge) è una regola alla base della programmazione ad oggetti che consiglia di far conoscere ad un dato oggetto il minor numero di informazioni riguardo la struttura o le proprietà degli altri oggetti.

Ad esempio la seguente classe viola questa regola:

class WordDocument {
private String title;

WordDocument(HtmlDocument htmlDocument){
this.title = htmlDocument.getTitle();
}

}

Mentre il seguente esempio la rispetta:


class WordDocument {
private String title;

WordDocument(String title){
this.title = title;
}

}

Perchè WordDocument deve conoscere HtmlDocument? Il vantaggio potrebbe essere quello di convertire facilmente un documento Word in uno Html, ma non è questo il caso perchè l’unica informazione che realmente serve è il titolo del documento. Gli svantaggi invece sono tanti:

  • posso costruire un documento Word solo a partire da un documento html, qualcuno potrebbe suggerire l’inserimento di due costruttori nella classe, ma in tal caso assegnerei una responsabilità impropria a WordDocument, una soluzione potrebbe essere l’utilizzo del pattern Factory.
  • non è chiaro all’utilizzatore della mia classe di cosa veramente abbia bisogno un documento word per essere inizializzato.
  • la complessità nella creazione di test unitari in isolamento aumenta perchè abbiamo a che con un altro oggetto di cui potremmo non conoscere il comportamento e per avere un test in isolamento dovremmo ricorrere a oggetti mock, ammesso che HtmlDocument sia una interfaccia.
  • il livello di accoppiamento nel codice aumenta e tutti noi sappiamo che non è cosa buona: vero?

Qualcuno potrebbe obiettare che questo esempio non è attendibile perchè troppo semplice. Ad esempio per la costruzione di un WordDocument potrei avere bisogno di altre informazioni:

class WordDocument {
private String title;
private String subtitle;
private String authorName;
private String authorSurname;
private String description;
private  int pageNumber;

WordDocument(String title, String subtitle, String authorName, String authorSurname String description, int pageNumber){
this.title = title;
this.subtitle = subtitle;
this.authorName = authorName;
this.authorSurname = authorSurame;
this.description = description;
this.pagenumber = pagenumber;
}

}

E’ facile notare che il costruttore è cresciuto non poco e utilizzare una istanza di HtmlDocument avrebbe semplificato notevolmente il codice.
Una soluzione consigliata da Craig Larman nel libro “Applicare UML e pattern” è l’utilizzo delle “classi descrizione” che trai vari vantaggi hanno quello di ridurre informazioni ridondanti o ripetute, infatti il costruttore simile a quello di WordDocument potrebbe essere presente in HtmlDocument, quindi:

class DocumentInfo {
private String title;
private String subtitle;
private String authorName;
private String authorSurname;
private String description;
private  int pageNumber;

DocumentInfo(String title, String subtitle, String authorName, String authorSurname String description, int pageNumber){
this.title = title;
this.subtitle = subtitle;
this.authorName = authorName;
this.authorSurname = authorSurame;
this.description = description;
this.pagenumber = pagenumber;
}

}

e WordDocument diventa:

class WordDocument {
private DocumentInfo documentInfo;
WordDocument(DocumentInfo documentInfo){
this.documentInfo = documentInfo;
}
}

Ora sono quasi soddisfatto, ma la legge di Demetra è ancora violata dall’utilizzo di authorName e authorSurname per descrivere le informazioni relative all’autore del documento. Questo proprio non va perchè stiamo rappresentando con dei semplici attributi una classe concettuale, cioè la classe Author:

class DocumentInfo {

DocumentInfo(String title, String subtitle, Author author, String description, int pageNumber){
this.title = title;
this.subtitle = subtitle;
this.author = author;
this.description = description;
this.pagenumber = pagenumber;
}

}

In questo caso la creazione di una classe porta al rispetto della legge di Demetra perchè al documento non interessa conoscere il nome e cognome dell’autore ma l’entità autore. Questo avviene perchè se nel mondo reale non pensiamo a una determinata classe concettuale X come a un numero o a un testo, allora probabilmente X è una classe concettuale, non un attributo (sempre grazie a Larman per questa linea guida).

E se ancora non avete capito bene la legge di Demetra pensate a questo:

“Se in un negozio comprate qualcosa e dovete pagare €20. Date al commesso €20 o gli date il portafogli e gli dite di prendere €20?”

Bibliografia:

Annunci

~ di jesty su novembre 18, 2008.

Una Risposta to “La dura legge di Demetra”

  1. ciao, nel primo esempio, in cui dici che la legge è violata, in realtà quello snippet non la viola. In effetti la legge permette ad un metodo di richiamare metodi dei suoi parametri, ed è proprio quel caso 🙂

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

 
%d blogger hanno fatto clic su Mi Piace per questo: