Secondo la legge di Demetra, una classe può restituire uno dei suoi membri?
Sì, lo è sicuramente.
Diamo un'occhiata ai punti principali :
- Ogni unità dovrebbe avere una conoscenza limitata delle altre unità: solo le unità "strettamente" correlate all'unità corrente.
- Ogni unità dovrebbe parlare solo con i suoi amici; non parlare con estranei.
- Parla solo con i tuoi amici immediati.
Tutti e tre i quali ti lasciano fare una domanda: chi è un amico?
Quando si decide cosa restituire, La Legge di Demetra o il principio della minima conoscenza (LoD) non impone che si difenda dai programmatori che insistono nel violarlo. Determina che non costringi i programmatori a violarlo.
Essere confusi è esattamente il motivo per cui così tanti pensano che un setter debba sempre restituire il vuoto. No. È necessario consentire un modo per eseguire query (getter) che non modificano lo stato del sistema. Questa è la separazione delle query dei comandi di base .
Questo significa che sei libero di approfondire una base di codice concatenando tutto ciò che vuoi? No. Incatena solo ciò che doveva essere incatenato insieme. Altrimenti la catena potrebbe cambiare e improvvisamente le tue cose verranno rotte. Questo è ciò che si intende per amici.
Le catene lunghe possono essere progettate per. Interfacce fluide, iDSL, gran parte di Java8 e il buon vecchio StringBuilder sono tutti pensati per farti costruire catene lunghe. Non violano il LoD perché tutto nella catena è pensato per lavorare insieme e ha promesso di continuare a lavorare insieme. Violi demeter quando concatenate cose che non si sono mai sentite. Gli amici sono quelli che hanno promesso di far funzionare la tua catena. Friends of Friends no.
A parte le classi che sono state appositamente designate per restituire oggetti - come le classi factory e builder - va bene per un metodo restituire un oggetto, ad esempio un oggetto detenuto da una delle proprietà della classe o che viola la legge di demeter (1) ?
Questo crea solo un'opportunità per violare Demeter. Questa non è una violazione. Questo non è nemmeno necessariamente negativo.
E se viola la legge di demeter, importerebbe se l'oggetto restituito è un oggetto immutabile che rappresenta un pezzo di dati e non contiene altro che getter per questi dati (2)?
Immutabile è buono ma irrilevante qui. Arrivare a cose attraverso una catena più lunga non lo rende migliore. Ciò che lo rende migliore è separare l'ottenere dall'uso. Se stai usando, chiedi quello che ti serve come parametro. Non andare a caccia di esso scavando nei getter di estranei.
In pseudo codice:
Sospetto che la legge di Demetra proibisca un modello come quello sopra. Cosa posso fare per garantire che doSomethingElse () possa essere chiamato senza violare la legge (3)?
Prima di parlare di x.doSomethingElse(a)
capire che hai sostanzialmente scritto
b.getA().doSomething()
Ora, LoD non è un esercizio di conteggio dei punti . Ma quando crei una catena stai dicendo che sai come ottenere un A
(usando B
) e sai come usare un A
. Bene, ora A
e B
meglio essere amici intimi perché basta loro accoppiati.
Se avessi appena chiesto qualcosa per consegnarti una A
cosa simile che potresti usare A
e non ti sarebbe importato da dove venisse e B
potresti vivere una vita felice e libera dalla tua ossessione per arrivare A
da B
.
Per quanto riguarda x.doSomethingElse(a)
senza dettagli da dove x
proviene, LoD non ha nulla da dire al riguardo.
LoD può incoraggiare a separare l'uso dalla costruzione . Ma farò notare che se trattate religiosamente ogni oggetto come non amichevole, sarete bloccati a scrivere codice con metodi statici. In questo modo puoi costruire un grafico a oggetti meravigliosamente complesso, ma alla fine devi chiamare un metodo per iniziare a funzionare. Devi semplicemente decidere chi sono i tuoi amici. Non c'è modo di evitarlo.
Quindi sì, una classe è autorizzata a restituire uno dei suoi membri in LoD. Quando lo fai dovresti chiarire se quel membro è amichevole con la tua classe perché se non lo è, alcuni client potrebbero provare ad associarti a quella classe usando te per ottenerla prima di usarla. Questo è importante perché ora ciò che ritorni deve sempre supportare quell'uso.
Ci sono molti casi in cui questo non è semplicemente un problema. Le collezioni possono ignorarlo semplicemente perché sono pensate per essere amiche di tutto ciò che le utilizza. Allo stesso modo gli oggetti di valore sono amichevoli con tutti. Ma se hai scritto un indirizzo che convalida l'utilità che ha richiesto un oggetto dipendente da cui ha estratto un indirizzo, piuttosto che semplicemente chiedere l'indirizzo, è meglio sperare che il dipendente e l'indirizzo provengano entrambi dalla stessa libreria.