Sto leggendo un libro chiamato Rails AntiPatterns e parlano di usare la delega per evitare di infrangere la legge di Demeter. Ecco il loro primo esempio:
Credono che chiamare qualcosa di simile nel controller sia sbagliato (e sono d'accordo)
@street = @invoice.customer.address.street
La loro soluzione proposta è di fare quanto segue:
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
Stanno affermando che dal momento che usi solo un punto, non stai infrangendo la Legge di Demetra qui. Penso che questo non sia corretto, perché stai ancora passando attraverso il cliente per passare attraverso l'indirizzo per ottenere la via della fattura. Principalmente ho avuto questa idea da un post sul blog che ho letto:
Nel post del blog l'esempio principale è
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
Il post del blog afferma che, sebbene esista solo un punto customer.cash
invece di customer.wallet.cash
, questo codice viola ancora la legge di Demeter.
Now in the Paperboy collect_money method, we don't have two dots, we just have one in "customer.cash". Has this delegation solved our problem? Not at all. If we look at the behavior, a paperboy is still reaching directly into a customer's wallet to get cash out.
Modifica
Comprendo e accetto completamente che si tratta ancora di una violazione e ho bisogno di creare un metodo in Wallet
chiamato withdraw che gestisce il pagamento per me e che dovrei chiamare tale metodo all'interno della classe Customer
. Quello che non capisco è che, secondo questo processo, il mio primo esempio viola ancora la legge di Demeter perché Invoice
sta ancora raggiungendo direttamente in Customer
per ottenere la strada.
Qualcuno può aiutarmi a chiarire la confusione. Ho cercato gli ultimi 2 giorni cercando di far affondare questo argomento, ma è ancora confuso.