A Lei de Demeter afirma o seguinte:
- 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.
O C # 6.0 introduziu um novo operador chamado operador nulo-condicional . IMHO, facilita a codificação e melhora a legibilidade. Mas também facilita escrever mais códigos acoplados, pois é mais fácil navegar pelos campos de classe, já verificando a nulidade (algo como var x = A?.B?.C?.D?.E?.F?
).
É correto afirmar que esse novo operador contraria a Lei de Demeter?
c#
design-patterns
object-oriented-design
Arthur Rizzo
fonte
fonte
A?.B?.C?.D?.E?.F?
iria violá-lo - LoD não é sobre quantos pontos e se o método de chamada tiver essas informações sobre a estrutura que não está violando seus pontos, essa chamada seria perfeitamente aceitável. Que tal código poderia violar LoD não é suficiente para dizer que todos os usos do que fazer violar LoD.X.Y.Z.W.U
é uma violação da "lei". Mas, na minha experiência em lidar com código, 90% das vezes é apenas um código acoplado feio..?
não mais viola LoD do que+
ou-
faz.Respostas:
Não *
* O operador condicional nulo é uma ferramenta na linguagem e na estrutura .NET. Qualquer ferramenta tem a capacidade de ser abusada e usada de maneiras que possam prejudicar a capacidade de manutenção de um determinado aplicativo.
Mas o fato de que uma ferramenta pode ser abusado, não significa necessariamente que ele tem de ser abusado, nem que a ferramenta viole qualquer princípio específico (s) que podem ser realizadas.
A Lei de Deméter e outras são diretrizes sobre como você deve escrever seu código. É direcionado para humanos, não para as ferramentas. Portanto, o fato de a linguagem C # 6.0 ter uma nova ferramenta nela não afeta necessariamente como você deve escrever e estruturar seu código.
Com qualquer nova ferramenta, é preciso avaliá-lo como ... se o cara que acaba mantendo o seu código será um psicopata violento ... . Observe novamente que essa é uma orientação para a pessoa que está escrevendo o código e não sobre as ferramentas que estão sendo usadas.
fonte
foo = new FiveDMatrix(); foo.get(0).get(0).get(0).get(0).set(0,1);
seria bom (e não é pior do quefoo[0][0][0][0][0] = 1
) ... e muitas outras situações em que isso não viola o LoD.Dom file = prase("some.xml"); file.get(tag1).getChild().get(tag2).getChild() ...
- é uma questão de processar a estrutura de algum código idiota. Não é um estranho ... é apenas burro. O.?
torna - se muito útil em tais estruturas.Tipo de.
Se você estiver acessando apenas um (
a?.Foo
), será equivalente a:o que a maioria das pessoas concorda que não é uma violação da Lei de Demeter. Nesse ponto, é apenas açúcar sintático para melhorar a legibilidade.
Qualquer coisa além disso, e provavelmente violaria a Lei de Demeter, e esse recurso tende a promover esse tipo de uso. Eu diria mesmo que o uso "bom" acima não é suficiente para justificar esse tipo de alteração no idioma, portanto, espero que ele tenha sido feito para oferecer suporte ao uso menos claramente bom.
Dito isto, vale lembrar que a Lei de Deméter não é uma lei em si, mas mais uma diretriz. Muitos códigos violam e funcionam bem. Às vezes, a simplicidade do design ou do código vale mais do que o risco representado pela violação da Lei de Demeter.
fonte
a?.Func1(x)?.Func2(y)
O operador nulo coalescentes é outra coisa.Não. Vamos considerar o operador por conta própria e o uso fortemente encadeado que você possui para ele.
Por si só,
.?A
depende da mesma quantidade de conhecimento da classe que o valor esquerdo é e do tipo retornado pelo método como.A != null
faz, viz. Ele precisa saber que aA
propriedade existe e retorna um valor que pode ser comparadonull
.Só podemos argumentar que isso viola a lei de Demeter se as propriedades digitadas o fizerem. Não somos obrigados a ter
A
um tipo concreto (seu valor pode ser de um tipo derivado). O acoplamento aqui é mínimo.Agora vamos considerar
var x = A?.B?.C?.D?.E?.F
.O que significa que
A
deve ser de um tipo que possa ser nulo ou que possa ter umaB
propriedade, que deve ser de um tipo que possa ser nulo ou que tenha umaC
propriedade, e assim por diante até que o tipo daE
propriedade seja algo que possa ser nulo ou poderia ter umaF
propriedade.Em outras palavras, precisamos fazer isso com uma linguagem de tipo estaticamente ou ter aplicado uma restrição nos tipos que podem ser retornados se a digitação estiver frouxa. O C # na maioria dos casos usa digitação estática, portanto não alteramos nada.
Se tivéssemos, o código a seguir também violaria a lei:
Qual é exatamente o mesmo . Esse código que está usando o acoplamento de diferentes elementos precisa "conhecer" a cadeia completa do acoplamento, mas está usando um código que não viola a Lei de Deméter para fazê-lo, com cada unidade tendo um acoplamento bem definido com nas próximas.
fonte
var x = A?.B?.C?.D?.E?.F
todos os outros, mesmo que sejam os mesmos no final.A?.B?.C?.D?.E?.F
porque há menos que pode estar errado; ou deveríamos estar tentando seguirF
esse caminho, ou não deveríamos, enquanto a forma mais longa poderia ter erros dentro dela e também o erro de não ser a coisa correta a fazer.A.B.C.D
. É muito mais simples para ter uma única coisa de olhar para fora (acesso à propriedade encadeado), em vez de duas coisas diferentes que dependem de um detalhe bastante irrelevante (null-checking)O objeto pode ser criado com a finalidade de encapsular comportamentos ou manter dados, e os objetos podem ser criados com a finalidade de serem compartilhados com códigos externos ou mantidos em sigilo por seus criadores.
Objetos criados com a finalidade de encapsular o comportamento (compartilhado ou não) ou para serem compartilhados com código externo (se eles encapsulam comportamento ou dados) geralmente devem ser acessados por meio de sua interface de superfície. Quando os objetos de retenção de dados são criados para uso exclusivo de seu criador, no entanto, os motivos normais da Lei de Demeter para evitar o acesso "profundo" não se aplicam. Se parte de uma classe que armazena ou manipula dados no objeto é alterada de maneira a exigir o ajuste de outro código, será possível garantir que todo esse código seja atualizado porque - como observado acima - o objeto foi criado para o uso exclusivo de uma classe.
Enquanto eu acho que o. Talvez o operador pudesse ter sido melhor projetado, há situações suficientes em que os objetos fazem uso de estruturas de dados aninhadas que o operador possui muitos casos de uso que não violariam os princípios expressos pela Lei de Demeter. O fato de poder ser usado para violar o LoD não deve ser tomado como argumento contra o operador, pois não é pior que o "." operador a esse respeito.
fonte