Estou lendo um livro chamado Rails AntiPatterns e eles falam sobre o uso de delegação para evitar violar a Lei de Demeter. Aqui está o seu exemplo principal:
Eles acreditam que chamar algo assim no controlador é ruim (e eu concordo)
@street = @invoice.customer.address.street
A solução proposta é fazer o seguinte:
class Customer
has_one :address
belongs_to :invoice
def street
address.street
end
end
class Invoice
has_one :customer
def customer_street
customer.street
end
end
@street = @invoice.customer_street
Eles estão afirmando que, como você usa apenas um ponto, não está violando a Lei de Deméter aqui. Acho que isso está incorreto, porque você ainda está passando pelo cliente para passar pelo endereço e obter a rua da fatura. Eu obtive essa ideia principalmente de uma postagem de blog que li:
http://www.dan-manges.com/blog/37
Na postagem do blog, o principal exemplo é
class Wallet
attr_accessor :cash
end
class Customer
has_one :wallet
# attribute delegation
def cash
@wallet.cash
end
end
class Paperboy
def collect_money(customer, due_amount)
if customer.cash < due_ammount
raise InsufficientFundsError
else
customer.cash -= due_amount
@collected_amount += due_amount
end
end
end
Os estados postagem no blog que apenas um, embora haja pontilham customer.cash
em vez de customer.wallet.cash
, este código ainda viola a Lei de Demeter.
Agora, no método Paperboy collect_money, não temos dois pontos, apenas um em "customer.cash". Esta delegação resolveu o nosso problema? De modo nenhum. Se observarmos o comportamento, um entregador de jornal ainda está chegando diretamente na carteira de um cliente para sacar dinheiro.
EDITAR
Entendo e concordo completamente que isso ainda é uma violação e preciso criar um método Wallet
chamado de retirada que lide com o pagamento e que eu deva chamar esse método dentro da Customer
classe. O que não entendo é que, de acordo com esse processo, meu primeiro exemplo ainda viola a Lei de Deméter, porque Invoice
ainda está alcançando diretamente Customer
a rua.
Alguém pode me ajudar a esclarecer a confusão. Eu tenho procurado nos últimos 2 dias tentando deixar este tópico afundar, mas ainda é confuso.