Como resolver o problema de propriedades “train wreck” que viola Law Of Demeter?

5

Eu tenho lido sobre o Law of Demeter e gostaria de saber como resolver este problema de propriedades do modelo que eu vejo muito em Objective-C. Eu sei que há um semelhante questionar mas neste caso não estou chamando um método da última propriedade que faz alguns cálculos, ao invés disso, estou apenas definindo valores (Ok, eu sei que getter são métodos mas minha intenção aqui é apenas para obter o valor, não para alterar o estado de algum objeto).

Por exemplo:

self.priceLabel.text = self.media.ad.price.value;

Devo mudar isso para algo como:

self.priceLabel.text = [self.media adPriceValue];

e dentro do Media.m

- (NSString *)adPriceValue {
    return [self.ad priceValue];
}

e dentro do Ad.m

- (NSString *)priceValue {
    return [self.price value];
}

Isso é uma boa solução? Ou estou criando métodos desnecessários?

    
por Raphael Oliveira 12.09.2013 / 17:04
fonte

2 respostas

4

Depois de ler o artigo muito interessante postado por Robert Harvey, eu sugiro que se você ainda está preocupado com o LoD, faça isso (me perdoe por não usar a sintaxe do ObjC aqui, não tenho ideia de como isso funciona):

/* Old code: */
void update() {
  this.priceLabel.text = this.media.ad.price.value;
}

/* New code: */
void update() {
  updateAdInfo(this.media.ad);
}
void updateAdInfo(Ad ad) {
  // Can dive a level deeper here if you want to.
  this.priceLabel.text = ad.price.value;
}
Justificativa: Introduzindo getters adicionais para subpropriedades, você está achatando seu modelo de domínio, e isso é simplesmente horrível: você perde toda a estrutura e aumenta o acoplamento. (E se você adicionar uma propriedade ao anúncio? Agora você acessa todas as classes que incorporam um anúncio e adicionam getters à nova propriedade?)

No entanto, se você tiver uma hierarquia de objetos e uma pseudo-hierarquia (parcial) correspondente de elementos de visualização para exibi-los, faz sentido organizar suas funções de atualização em uma hierarquia também.

    
por 12.09.2013 / 17:30
fonte
3

Sugiro que você considere o seguinte.

  1. Será que self precisa de uma referência a media e ad ou só usa price ? Se você usa apenas price , não precisa passar por toda a cadeia.

  2. Se media.ad.price for principalmente uma estrutura de dados (pouco ou nenhum comportamento / métodos), provavelmente você não precisa se preocupar com Demeter.

  3. Se self usar media , ad e price , self poderá ser complexo o suficiente para justificar a divisão de self em classes menores.

  4. Há compensações para ocultar ou expor delegados. Você deve escolher o que acha que funciona melhor para você e é possível alterar sua implementação mais tarde.

    Ocultar o representante obriga você a escrever métodos de delegação, mas encapsula as alterações na estrutura. Por exemplo, se você adicionar outra camada, como media.ad.timeSlot.price , só precisará alterar o método delegado, não todas as classes que usam o delegado. Por outro lado, como mencionado por Sebastian, se você quiser adicionar uma nova propriedade ou método de preço, você tem que escrever um método de delegação.

  5. Você pode escolher uma solução intermediária. Por exemplo, pode fazer sentido que self obtenha uma referência a ad , mas adicione um método a ad para retornar o valor do preço, para que self não precise navegar pelo restante da estrutura .

por 12.09.2013 / 20:33
fonte

Tags