Je lis un livre intitulé Rails AntiPatterns et ils parlent d'utiliser la délégation pour éviter d'enfreindre la loi de Demeter. Voici leur premier exemple:
Ils croient qu'appeler quelque chose comme ça dans le contrôleur est mauvais (et je suis d'accord)
@street = @invoice.customer.address.street
La solution proposée consiste à procéder comme suit:
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
Ils affirment que puisque vous n'utilisez qu'un seul point, vous n'enfreignez pas la loi de Déméter ici. Je pense que c'est incorrect, car vous passez toujours par le client pour passer par l'adresse pour obtenir la rue de la facture. J'ai principalement eu cette idée dans un article de blog que j'ai lu:
http://www.dan-manges.com/blog/37
Dans le billet de blog, le premier exemple est
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
Le blog indique que bien qu'il n'y ait qu'un seul point customer.cashau lieu de customer.wallet.cash, ce code viole toujours la loi de Demeter.
Maintenant, dans la méthode Paperboy collect_money, nous n'avons pas deux points, nous en avons juste un dans "customer.cash". Cette délégation a-t-elle résolu notre problème? Pas du tout. Si nous examinons le comportement, un paperboy atteint toujours directement le portefeuille d'un client pour retirer de l'argent.
ÉDITER
Je comprends parfaitement et je suis d'accord que c'est toujours une violation et je dois créer une méthode Walletappelée appelée qui gère le paiement pour moi et que je devrais appeler cette méthode à l'intérieur de la Customerclasse. Ce que je ne comprends pas, c'est que selon ce processus, mon premier exemple viole toujours la loi de Déméter, car il cherche Invoicetoujours directement Customerà obtenir la rue.
Quelqu'un peut-il m'aider à dissiper la confusion? Je cherchais depuis 2 jours à essayer de laisser ce sujet pénétrer, mais c'est toujours déroutant.