Estoy leyendo un libro llamado Rails AntiPatterns y hablan sobre el uso de la delegación para evitar infringir la Ley de Demeter. Aquí está su primer ejemplo:
Creen que llamar a algo así en el controlador es malo (y estoy de acuerdo)
@street = @invoice.customer.address.street
Su solución propuesta es hacer lo siguiente:
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
Afirman que dado que solo usa un punto, no está violando la Ley de Deméter aquí. Creo que esto es incorrecto, porque todavía está pasando por el cliente para ir a través de la dirección para obtener la calle de la factura. Principalmente obtuve esta idea de una publicación de blog que leí:
http://www.dan-manges.com/blog/37
En la publicación del blog, el mejor ejemplo es
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
La publicación del blog indica que aunque solo hay un punto en customer.cash
lugar de customer.wallet.cash
este, este código aún viola la Ley de Demeter.
Ahora en el método Paperboy collect_money, no tenemos dos puntos, solo tenemos uno en "customer.cash". ¿Esta delegación ha resuelto nuestro problema? De ningún modo. Si observamos el comportamiento, un repartidor de periódicos todavía está buscando directamente en la billetera de un cliente para sacar dinero.
EDITAR
Entiendo completamente y acepto que esto sigue siendo una violación y que necesito crear un método Wallet
llamado retiro que maneja el pago por mí y que debería llamar a ese método dentro de la Customer
clase. Lo que no entiendo es que, de acuerdo con este proceso, mi primer ejemplo todavía viola la Ley de Deméter porque Invoice
todavía está llegando directamente Customer
a la calle.
¿Alguien puede ayudarme a aclarar la confusión? He estado buscando durante los últimos 2 días tratando de dejar que este tema se hunda, pero aún es confuso.