Pergunta

O Lei de Demeter indica que você só deve falar com objetos que você sabe sobre diretamente. Isto é, não execute método de encadeamento para falar com outros objetos. Quando você faz isso, você está estabelecendo ligações impróprias com os objetos intermediários, inadequadamente acoplamento seu código para outro código.

Isso é ruim.

A solução seria para a classe que você sabe sobre a essencialmente expor invólucros simples que delegar a responsabilidade para o objeto que tem o relacionamento com ele.

Isso é bom.

Mas, que parece resultar na classe baixa tendo coesão . Já não é simplesmente responsável por exatamente o que ele faz, mas também tem os delegados que, em certo sentido, tornando o código menos coesa duplicando partes da interface de seu objeto relacionado.

Isso é ruim.

Será que realmente resultar na redução de coesão? É o menor de dois males?

É este uma dessas áreas cinzentas de desenvolvimento, onde você pode debater onde a linha é, ou há maneiras fortes, baseada em princípios de tomar uma decisão de onde traçar a linha e quais os critérios que você pode usar para tomar essa decisão?

Foi útil?

Solução

Grady Booch em "Object Oriented Analysis and Design":

"A ideia de coesão também vem de projeto estruturado. Simplificando, a coesão mede o grau de conectividade entre os elementos de um único módulo (e para a concepção orientada para o objecto, uma única classe ou objecto). A forma menos desejável de coesão é a coesão coincidência, em que as captações inteiramente alheios são jogado na mesma classe ou módulo. Por exemplo, considere uma classe que compreende as abstrações de cães e naves espaciais, cujos comportamentos são bastante independentes. o a forma mais desejável de coesão é a coesão funcional, em que os elementos de uma classe ou módulo todos juntos trabalho para fornecer um comportamento bem limitada. Assim, a classe de cão é funcionalmente coesa se sua semântica abraçar o comportamento de um cão, todo o cão, e nada mas o cão ".

Dog Subsitute com o Cliente no exemplo acima e que poderia ser um pouco mais claro. Assim, o objetivo é realmente apenas para apontar para a coesão funcional e se afastar de coesão coincidência, tanto quanto possível. Dependendo de suas abstrações, isso pode ser simples ou pode exigir alguma refatoração.

Nota coesão se aplica tanto a um "módulo" do que a uma única classe, ou seja, um grupo de classes de trabalho em conjunto. Portanto, neste caso as classes pedido do cliente e ainda ter coesão decente porque eles têm essa relationshhip forte, os clientes criar ordens, ordens pertencem aos clientes.

Martin Fowler diz que ele estaria mais confortável chamando-o de "Sugestão de Demeter" (veja o artigo Mocks não são canhotos ):

"testadores com mock fazer falar mais sobre como evitar 'acidentes de trem' -... Cadeias de método de estilo de getThis () getThat () getTheOther () Evitar cadeias método também é conhecido como seguir a Lei de Demeter Embora as cadeias de método são. um cheiro, o problema oposto de homens de meia objetos inchado com métodos de encaminhamento é também um cheiro. (Eu sempre senti que eu seria mais confortável com a Lei de Demeter se fosse chamado Sugestão de Demeter ). "

Isso resume muito bem onde eu estou vindo: é perfeitamente aceitável e muitas vezes necessário ter um nível mais baixo de coesão que a adesão estrita à "lei" pode exigir. Evite coesão coincidência e apontar para a coesão funcional, mas não ficam penduradas sobre ajustes quando necessário para caber no mais naturalmente com o seu abstração design.

Outras dicas

Se você está violando a Lei de Demeter por ter

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

a solução não é criar um getOrderPrice () e transformar o código em

int price = customer.getOrderPrice();

mas ao invés de nota que este é um código cheiro e faça as alterações relevantes que esperamos tanto aumentar a coesão e acoplamento inferior. Infelizmente não há nenhuma simples refatoração aqui que sempre se aplica, mas você provavelmente deve aplicar dizer não pedir

Eu acho que você pode ter entendido mal o que significa coesão. Uma classe que é implementada em termos de várias outras classes não tem necessariamente de baixa coesão, desde que ele representa um conceito claro, e tem um propósito claro. Por exemplo, você pode ter um class Person, que é implementado em termos de classes Date (por data de nascimento), Address e Education (a lista de escolas a pessoa foi para). Você pode fornecer wrappers em Person para começar o ano de nascimento, a última escola a pessoa foi para, ou o estado onde vive, para evitar expor o fato de que Person é implementado em termos dessas outras classes. Isto reduziria o acoplamento, mas faria Person não menos coesa.

É uma área cinzenta. Estes princípios são destinadas a ajudá-lo em seu trabalho, se você achar que você está trabalhando para eles (ou seja, eles estão recebendo em seu caminho e / ou você achar que é mais complica seu código), então você está em conformidade muito difícil e você precisa a recuar.

fazer o trabalho para você, e não fazer o trabalho para ele.

Eu não sei se isso realmente diminui a coesão.

Aggregation / composição são todos sobre uma classe utilizando outras classes para atender o contrato ele expõe através de seus métodos públicos. A classe não precisa de duplicar a interface de seu objetos relacionados. É realmente escondendo qualquer knwowledge sobre essas classes agregadas do chamador método.

Para obedecer à lei de Deméter no caso de vários níveis de dependência classe, você só precisa aplicar a agregação / composição e bom encapsulamento em cada nível.

Em outras palavras, cada classe tem um ou mais dependências em outras classes, no entanto estes são sempre apenas dependências na classe referenciada e não em todos os objetos retornados do properies / métodos.

Nas situações em que parece haver uma troca entre acoplamento e coesão, eu provavelmente me perguntar "se alguém já tinha escrito essa lógica, e eu estava procurando por um bug na mesma, onde eu olhar primeiro? ", e escrever o código dessa forma.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top