According to Demeter's law, is a class allowed to return one of its members?
Sì, sicuramente lo è.
Diamo un'occhiata ai punti principali :
- Ogni unità dovrebbe avere solo 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 più stretti.
Tutti e tre dei quali ti lasciano una domanda: Chi è un amico?
Quando decidi cosa restituire, The Law of Demeter o il principio di minima conoscenza (LoD) non impone di difendere dai programmatori che insistono nel violentarla. Si impone di non forzare i programmatori a violarlo.
Ottenere questi confusi è esattamente il motivo per cui così tanti pensano che un setter debba sempre restituire il nulla. No. È necessario consentire un modo per creare query (getter) che non modificano lo stato del sistema. Questa è la separazione della query del comando di base.
Questo significa che sei libero di approfondire una base di codice concatenando ciò che vuoi? No. Unire insieme solo ciò che doveva essere incatenato insieme. Altrimenti la catena potrebbe cambiare e improvvisamente le tue cose sono rotte. Questo è ciò che si intende per amici.
Le catene lunghe possono essere progettate per. Interfacce fluenti, iDSL, gran parte di Java8 e il buon vecchio StringBuilder hanno tutte lo scopo di creare catene lunghe. Non violano LoD perché tutto nella catena è pensato per lavorare insieme e ha promesso di continuare a lavorare insieme. Tu infrangi Demeter quando leghi insieme cose che non si sono mai sentite. Gli amici sono quelli che hanno promesso di far funzionare la catena. Amici degli amici no.
Apart from classes which were specifically appointed to return objects - such as factory and builder classes - is it okay for a method to return an object, e.g. an object held by one of the class's properties or would that violate the law of demeter (1)?
Questo crea solo un'opportunità per violare Demeter. Questa non è una violazione. Questo non è nemmeno necessariamente male.
And if it violates the law of demeter, would it matter if the object returned is an immutable object that represents a piece of data and contains nothing but getters for this data (2)?
Immutabile è buono ma irrilevante qui. Ottenere cose attraverso una catena più lunga non lo rende migliore. Ciò che lo rende migliore è separare il recupero dall'uso. Se stai usando, chiedi quello che ti serve come parametro. Non andare a caccia di esso scavando nel gettare di estranei.
In pseudo code:
I suspect that Demeter's law forbids a pattern such as the above. What can I do to ensure that doSomethingElse() can be called while not violating the law (3)?
Prima di parlare di x.doSomethingElse(a)
comprendi che hai scritto in modo semplice
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
(utilizzando B
) e sai come usare A
. Bene, ora A
e B
farebbero meglio ad essere amici intimi perché li hai semplicemente accoppiati.
Se avessi appena chiesto qualcosa per consegnarti una cosa simile a A
potresti usare A
e non ti sarebbe importato da dove proviene e B
potrebbe vivere una vita felice e libera dalla tua ossessione per ottenendo A
da B
.
Per quanto riguarda x.doSomethingElse(a)
senza i dettagli di dove proviene x
, LoD non ha nulla da dire a riguardo.
LoD può incoraggiare separare l'uso dalla costruzione . Ma farò notare che se trattate religiosamente ogni oggetto come non amichevole, sarete bloccati a scrivere codice in metodi statici. Puoi costruire un grafo di oggetti meravigliosamente complesso in questo modo, ma alla fine devi chiamare un metodo su di esso per far funzionare la cosa. Devi semplicemente decidere chi sono i tuoi amici. Non c'è modo di scappare da quello.
Quindi sì, una classe può restituire uno dei suoi membri sotto LoD. Quando lo fai dovresti chiarire se quel membro è amichevole con la tua classe, perché se non lo è, alcuni clienti potrebbero provare ad abbinarti a quel corso usando te per averlo prima di usarlo. Questo è importante perché ora ciò che ritorni deve sempre supportare quell'uso.
Ci sono molti casi in cui questo non è semplicemente un problema. Le raccolte possono ignorarlo semplicemente perché sono intese per essere amici di tutto ciò che le utilizza. Allo stesso modo gli oggetti valore sono amichevoli con tutti. Ma se hai scritto un indirizzo che convalida l'utilità che richiedeva un oggetto dipendente dal quale estrasse un indirizzo, piuttosto che chiedere l'indirizzo, beh, spero che il dipendente e l'indirizzo provengano entrambi dalla stessa libreria.