Rails AntiPatterns adlı bir kitap okuyorum ve Demeter Yasasını çiğnemekten kaçınmak için delegasyondan bahsediyorlar. İşte onların en iyi örneği:
Denetleyicide böyle bir şey çağırmanın kötü olduğuna inanıyorlar (ve katılıyorum)
@street = @invoice.customer.address.street
Önerilen çözümleri aşağıdakileri yapmaktır:
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
Sadece bir nokta kullandığınız için burada Demeter Yasasını çiğnemediğinizi belirtiyorlar. Bunun yanlış olduğunu düşünüyorum, çünkü hala faturayı sokmak için adres üzerinden gitmek için müşteriye gidiyorsunuz. Öncelikle bu fikri okuduğum bir blog gönderisinden aldım:
http://www.dan-manges.com/blog/37
Blog gönderisinde asıl örnek
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
Blog yazısı, customer.cash
bunun yerine sadece bir nokta olmasına rağmen customer.wallet.cash
, bu kodun Demeter Yasasını hala ihlal ettiğini belirtiyor .
Şimdi Paperboy collect_money yönteminde iki noktamız yok, sadece "customer.cash" de bir tane var. Bu delegasyon sorunumuzu çözdü mü? Bir şey değil. Davranışlara bakarsak, bir gazeteci nakit almak için hala doğrudan müşterinin cüzdanına ulaşıyor.
DÜZENLE
Bunun hala bir ihlal olduğunu tamamen anlıyorum ve kabul ediyorum ve benim Wallet
için ödemeyi işleyen ve Customer
sınıf içinde bu yöntemi çağırmam gerektiğini söyleyen bir para çekme yöntemi oluşturmam gerekiyor . Bu sürece göre, ilk örneğim Demeter Yasasını hala ihlal ediyor, çünkü Invoice
hala Customer
sokağa ulaşmak için doğrudan ulaşıyor .
Birisi karışıklığı gidermeme yardımcı olabilir. Son 2 gündür bu konunun batmasına izin vermeye çalışıyorum, ama yine de kafa karıştırıcı.