De acordo com a lei de Demeter, é permitido a uma classe devolver um de seus membros?
Sim, certamente é.
Vejamos os principais pontos :
- Cada unidade deve ter apenas conhecimento limitado sobre outras unidades: somente unidades "estreitamente" relacionadas à unidade atual.
- Cada unidade deve conversar apenas com seus amigos; não fale com estranhos.
- Fale apenas com seus amigos imediatos.
Todos os três permitem que você faça uma pergunta: Quem é um amigo?
Ao decidir o que retornar, a Lei de Demeter ou o princípio do mínimo conhecimento (LoD) não determina que você se defenda contra codificadores que insistem em violá-lo. Ele determina que você não força os codificadores a violá-lo.
Confundir isso é exatamente o motivo pelo qual muitos acham que um levantador deve sempre retornar vazio. Não. Você deve permitir uma maneira de fazer consultas (getters) que não alterem o estado do sistema. Essa é a separação básica da consulta de comando .
Isso significa que você é livre para se aprofundar em uma base de código encadeando o que quiser? Não. Encadeie apenas o que deveria ser encadeado. Caso contrário, a corrente poderá mudar e, de repente, seu material será quebrado. É isso que os amigos querem dizer.
Podem ser projetadas cadeias longas. Interfaces fluentes, iDSL, grande parte do Java8 e o bom e antigo StringBuilder destinam-se a permitir que você construa longas cadeias. Eles não violam o LoD porque tudo na cadeia deve trabalhar juntos e promete continuar trabalhando juntos. Você viola o desmonte quando encadeia coisas que nunca ouviram falar um do outro. Amigos são aqueles que prometeram manter sua rede funcionando. Amigos de amigos não.
Além das classes que foram especificamente designadas para retornar objetos - como as classes factory e builder -, é aceitável que um método retorne um objeto, por exemplo, um objeto mantido por uma das propriedades da classe ou que viole a lei do demeter (1) ?
Isso cria apenas uma oportunidade de violar o demeter. Isto não é uma violação. Isso nem é necessariamente ruim.
E se viola a lei do demeter, importaria se o objeto retornado fosse um objeto imutável que represente um dado e não contenha nada além de getters para esses dados (2)?
Imutável é bom, mas irrelevante aqui. Chegar às coisas através de uma cadeia mais longa não a torna melhor. O que o torna melhor é separar a obtenção do uso. Se você estiver usando, peça o que você precisa como parâmetro. Não vá procurá-lo, mergulhando nos caçadores de estranhos.
No pseudo-código:
Suspeito que a lei de Deméter proíba um padrão como o acima. O que posso fazer para garantir que doSomethingElse () possa ser chamado sem violar a lei (3)?
Antes de falar sobre x.doSomethingElse(a)
entender que você escreveu basicamente
b.getA().doSomething()
Agora, LoD não é um exercício de contagem de pontos . Mas quando você cria uma cadeia, está dizendo que sabe como obter um A
(usando B
) e sabe como usar um A
. Bem agora A
eB
melhor ter amigos íntimos, porque você os juntou.
Se você tivesse acabado de pedir algo para lhe entregar uma A
coisa semelhante, você poderia usar A
e não se importaria de onde veio e B
poderia viver uma vida feliz e livre de sua obsessão por sair A
deB
.
Quanto x.doSomethingElse(a)
sem detalhes de ondex
veio, o LoD não tem nada a dizer sobre isso.
O LoD pode incentivar a separação do uso da construção . Mas vou apontar que se você tratar religiosamente todos os objetos como não amigáveis, ficará preso escrevendo código em métodos estáticos. Você pode construir um gráfico de objeto maravilhosamente complexo dessa maneira, mas eventualmente precisará chamar um método para começar a trabalhar. Você simplesmente tem que decidir quem são seus amigos. Não há como fugir disso.
Então, sim, uma classe tem permissão para retornar um de seus membros sob LoD. Ao fazê-lo, você deve deixar claro se esse membro é amigável com sua classe, porque, se não for, algum cliente pode tentar acoplá-lo a essa classe usando você para obtê-la antes de usá-la. Isso é importante porque agora o que você retorna sempre deve suportar esse uso.
Existem muitos casos em que isso simplesmente não é uma preocupação. As coleções podem ignorar isso simplesmente porque são feitas para serem amigas de tudo que as usa. Da mesma forma, objetos de valor são amigáveis com todos. Mas se você escreveu um utilitário de validação de endereço que exigia um objeto de funcionário do qual ele extraiu um endereço, em vez de apenas solicitar o endereço, é melhor esperar que o funcionário e o endereço sejam da mesma biblioteca.