Domanda

La Law of Demeter indica che dovresti parlare solo con oggetti che conosci direttamente. Cioè, non eseguire il metodo concatenamento per parlare con altri oggetti. Quando lo fai, stai stabilendo collegamenti impropri con gli oggetti intermedi, in modo inappropriato accoppiamento tuo codice ad altro codice.

Questo è male.

La soluzione sarebbe per la classe che conosci per esporre essenzialmente semplici wrapper che delegano la responsabilità all'oggetto con cui ha la relazione.

Va ??bene.

Ma sembra che la classe abbia una coesione bassa . Non è più semplicemente responsabile di ciò che fa esattamente, ma ha anche i delegati che, in un certo senso, rendono il codice meno coeso duplicando parti dell'interfaccia del suo oggetto correlato.

Questo è male.

Si traduce davvero in una riduzione della coesione? È il minore dei due mali?

Questa è una di quelle aree grigie di sviluppo, in cui puoi discutere su dove si trova la linea, o ci sono modi forti e di principio per prendere una decisione su dove tracciare la linea e quali criteri puoi usare per prendere quella decisione?

È stato utile?

Soluzione

Grady Booch in " Object Oriented Analysis and Design " ;:

" L'idea di coesione deriva anche dal design strutturato. In poche parole, coesione misura il grado di connettività tra gli elementi di un singolo modulo (e per la progettazione orientata agli oggetti, una singola classe o oggetto). La forma meno desiderabile di la coesione è coesione casuale, in cui sono astrazioni completamente non correlate gettato nella stessa classe o modulo. Ad esempio, considera una classe che comprende le astrazioni di cani e veicoli spaziali, i cui comportamenti sono abbastanza indipendenti. Il la forma più desiderabile di coesione è la coesione funzionale, in cui gli elementi di una classe o un modulo lavorano tutti insieme per fornire un comportamento ben delimitato. Pertanto, la classe Dog è funzionalmente coesa se la sua semantica abbraccia il comportamento di un cane, l'intero cane e nient'altro che il cane. "

Sostituisci il cane con il cliente in precedenza e potrebbe essere un po 'più chiaro. Quindi l'obiettivo è proprio quello di puntare alla coesione funzionale e di allontanarsi il più possibile dalla coesione casuale. A seconda delle tue astrazioni, questo può essere semplice o richiedere alcuni refactoring.

Nota la coesione si applica tanto a un "modulo" che a una singola classe, ovvero a un gruppo di classi che lavorano insieme. Quindi in questo caso le classi di clienti e ordini hanno ancora una buona coesione perché hanno questa forte relazione, i clienti creano ordini, gli ordini appartengono ai clienti.

Martin Fowler afferma che sarebbe più a suo agio definendolo il "Suggerimento di Demetra". (vedi l'articolo I mock non sono stub ):

" I tester di Mockist parlano di più dell'evitare "i relitti del treno" - catene di metodi dello stile di getThis (). getThat (). getTheOther (). Evitare le catene di metodi è anche noto come seguendo la Legge di Demetra. Mentre le catene di metodi sono un odore, anche il problema opposto degli oggetti degli uomini di mezzo gonfiati con metodi di inoltro è un odore. (Ho sempre pensato che mi sarei sentito più a mio agio con la Legge di Demetra se fosse stata chiamata Suggerimento di Demetra .) & Quot;

Questo riassume bene da dove vengo: è perfettamente accettabile e spesso necessario avere un livello di coesione inferiore rispetto alla stretta aderenza alla "legge". potrebbe richiedere. Evita la coesione casuale e punta alla coesione funzionale, ma non rimanere impiccato a modificare laddove necessario per adattarti in modo più naturale all'astrazione del tuo design.

Altri suggerimenti

Se stai violando la Legge di Demetra avendo

int price = customer.getOrder().getPrice();

la soluzione non è creare un getOrderPrice () e trasformare il codice in

int price = customer.getOrderPrice();

ma invece notare che questo è un e apportare le modifiche pertinenti che si spera aumentino la coesione e riducano l'accoppiamento. Sfortunatamente non esiste un semplice refactoring qui che si applica sempre, ma probabilmente dovresti applicare dire no chiedere

Penso che potresti aver frainteso il significato di coesione. Una classe implementata in termini di diverse altre classi non ha necessariamente una bassa coesione, purché rappresenti un concetto chiaro e abbia uno scopo chiaro. Ad esempio, potresti avere un class Person , che è implementato in termini di classi Date (per data di nascita), Indirizzo e < code> Istruzione (un elenco di scuole a cui la persona è andata). Puoi fornire i wrapper in Persona per ottenere l'anno di nascita, l'ultima scuola in cui la persona è andata o lo stato in cui vive, per evitare di esporre il fatto che Person è implementato in termini di quelle altre classi. Ciò ridurrebbe l'accoppiamento, ma renderebbe Person non meno coerente.

È un'area grigia. Questi principi hanno lo scopo di aiutarti nel tuo lavoro, se ti accorgi che stai lavorando per loro (cioè ti stanno ostacolando e / o lo trovi complicato il tuo codice), allora sei & # 8217; ri conformarsi troppo e devi arretrare.

Fallo funzionare per te, non farlo per te.

Non so se questo effettivamente riduce la coesione.

Aggregazione / composizione riguardano una classe che utilizza altre classi per soddisfare il contratto che espone attraverso i suoi metodi pubblici. La classe non ha bisogno di duplicare l'interfaccia dei suoi oggetti correlati. In realtà sta nascondendo qualsiasi conoscenza di queste classi aggregate dal metodo chiamante.

Per obbedire alla legge di Demetra nel caso di più livelli di dipendenza di classe, devi solo applicare aggregazione / composizione e buona incapsulamento ad ogni livello.

In altre parole, ogni classe ha una o più dipendenze da altre classi, tuttavia queste sono sempre e comunque dipendenze dalla classe di riferimento e non da alcun oggetto restituito da proprietà / metodi.

Nelle situazioni in cui sembra esserci un compromesso tra accoppiamento e coesione, probabilmente mi chiederei "se qualcun altro avesse già scritto questa logica e stavo cercando un bug in essa, dove avrei cercato prima ? " ;, e scrivi il codice in questo modo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top