ฉันกำลังอ่านหนังสือชื่อ Rails AntiPatterns และพวกเขาคุยกันเรื่องการใช้การมอบหมายเพื่อหลีกเลี่ยงการทำผิดกฎของ Demeter นี่คือตัวอย่างสำคัญของพวกเขา:
พวกเขาเชื่อว่าการโทรแบบนี้ในคอนโทรลเลอร์ไม่ดี (และฉันเห็นด้วย)
@street = @invoice.customer.address.street
ทางออกที่เสนอของพวกเขาคือทำสิ่งต่อไปนี้:
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
พวกเขากำลังระบุว่าเนื่องจากคุณใช้เพียงจุดเดียวคุณจะไม่ละเมิดกฎของ Demeter ที่นี่ ฉันคิดว่านี่ไม่ถูกต้องเพราะคุณยังคงต้องผ่านลูกค้าเพื่อผ่านที่อยู่เพื่อรับถนนใบแจ้งหนี้ ฉันได้รับแนวคิดนี้จากโพสต์บล็อกที่ฉันอ่านเป็นหลัก:
http://www.dan-manges.com/blog/37
ในบล็อกโพสต์ตัวอย่างสำคัญคือ
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
บล็อกโพสต์ระบุว่าแม้จะมีจุดเดียวcustomer.cash
แทนcustomer.wallet.cash
รหัสนี้ยังคงละเมิดกฎหมายของ Demeter
ตอนนี้ในวิธี Paperboy collect_money เราไม่มีจุดสองจุดเรามีเพียงจุดเดียวใน "customer.cash" การมอบหมายนี้แก้ไขปัญหาของเราได้หรือไม่? ไม่ใช่เลย. หากเราดูที่พฤติกรรมเด็กชายกระดาษยังคงเข้าถึงกระเป๋าเงินของลูกค้าโดยตรงเพื่อรับเงินสด
แก้ไข
ฉันเข้าใจและยอมรับอย่างสมบูรณ์ว่านี่เป็นการละเมิดและฉันจำเป็นต้องสร้างวิธีการในการWallet
ถอนเงินที่เรียกว่าจัดการการจ่ายเงินให้ฉันและฉันควรเรียกวิธีการนั้นในCustomer
ชั้นเรียน สิ่งที่ฉันไม่ได้รับก็คือตามกระบวนการนี้ตัวอย่างแรกของฉันยังคงละเมิดกฎหมายของ Demeter เพราะInvoice
ยังเข้าถึงโดยตรงCustomer
เพื่อไปตามถนน
ใครบางคนสามารถช่วยฉันล้างความสับสน ฉันค้นหามาตลอด 2 วันที่ผ่านมาพยายามปล่อยให้หัวข้อนี้จม แต่มันก็ยังสับสนอยู่