การปะลิง. เมื่อคุณลองใช้ Ruby ครั้งแรก มันวิเศษมาก คุณสามารถเพิ่มวิธีการลงในคลาสหลักได้! ไม่ต้องโทร Time.now.advance(days: -1)
คุณสามารถเขียน 1.day.ago
! ทำให้ Ruby มีความสุขในการอ่านและเขียน จนกระทั่ง…
คุณพบจุดบกพร่องแปลก ๆ เนื่องจากแพตช์เปลี่ยน Hash
.
คุณสับสนว่าโค้ดใดที่รันจริง ดังนั้นคุณจึงไม่สามารถดีบักเมื่อโค้ดขัดข้อง
และในที่สุดคุณก็พบว่าปัญหาทั้งหมดของคุณเกิดขึ้นเมื่อหกเดือนก่อน เมื่อคุณได้แก้ไข Enumerable
เพื่อทำให้โค้ดหนึ่งบรรทัดสั้นลง 5 อักขระ
แต่ทางเลือกคืออะไร? ไม่สะดวกเลย? รหัสที่ดูเหมือน GroupableArray.new([1, 2, 3, 4]).in_groups_of(2)
? กำลังรอ blank?
เพื่อให้เป็น Core Ruby ก่อนที่คุณจะได้รับอนุญาตให้มีการจัดการอินพุตของผู้ใช้ที่ดี?
คุณไม่ต้องการที่จะยอมแพ้กับแพทช์ลิงทั้งหมด แต่คุณจะเขียนแพทช์ลิงได้อย่างไรว่า ไม่ ทำให้อยากยิงตัวเองไร้ความสามารถในครั้งต่อไปที่เห็นพวกเขาไหม
ใส่ไว้ในโมดูล
เมื่อคุณ Monkey patch ของคลาส อย่าเพิ่งเปิดคลาสขึ้นมาใหม่และใส่ patch ลงไป:
class DateTime
def weekday?
!sunday? && !saturday?
end
end
ทำไมไม่?
-
ถ้าไลบรารี่สองไลบรารีแก้ไขวิธีเดียวกัน คุณจะไม่สามารถบอกได้
แพทช์ลิงตัวแรกจะถูกเขียนทับและหายไปตลอดกาล
-
หากมีข้อผิดพลาด จะดูเหมือนว่าเกิดข้อผิดพลาดภายใน
DateTime
.แม้ว่าในทางเทคนิคจะจริง แต่ก็ไม่มีประโยชน์นัก
-
การปิดแพทช์ลิงของคุณยากขึ้น
คุณต้องแสดงความคิดเห็นในแพตช์ทั้งหมดของคุณ หรือข้ามการขอไฟล์ Monkey patch หากคุณต้องการรันโค้ดที่ไม่มีไฟล์ดังกล่าว
-
ถ้าคุณว่าลืม
require 'date'
ก่อนเรียกใช้โปรแกรมแก้ไขลิงนี้ คุณจะกำหนดใหม่โดยไม่ได้ตั้งใจDateTime
แทนการแพตช์มัน
ให้ใส่แพทช์ลิงของคุณลงในโมดูลแทน:
module CoreExtensions
module DateTime
module BusinessDays
def weekday?
!sunday? && !saturday?
end
end
end
end
ด้วยวิธีนี้ คุณสามารถจัดระเบียบแพทช์ลิงที่เกี่ยวข้องกัน เมื่อมีข้อผิดพลาด จะเห็นได้ชัดว่ารหัสปัญหามาจากไหน และคุณสามารถรวมไว้ทีละกลุ่ม:
# Actually monkey-patch DateTime
DateTime.include CoreExtensions::DateTime::BusinessDays
หากคุณไม่ต้องการแพตช์อีกต่อไป เพียงแสดงความคิดเห็นในบรรทัดนั้น
เก็บไว้ด้วยกัน
เมื่อคุณเชื่อมโยงคลาสของแพตช์หลัก คุณจะเพิ่มไปยัง API ของ Ruby หลัก ทุกแอปที่มีแพตช์หลักให้ความรู้สึกที่แตกต่างกันเล็กน้อย ดังนั้น คุณต้องมีวิธีที่จะเรียนรู้การเปลี่ยนแปลงเหล่านั้นอย่างรวดเร็วเมื่อคุณเข้าสู่ฐานโค้ดใหม่ คุณต้องรู้ว่าแพทช์ลิงของคุณอาศัยอยู่ที่ไหน
ฉันส่วนใหญ่ปฏิบัติตามอนุสัญญาการปะลิงของ Rails แพทช์ไปที่ lib/core_extensions/class_name/group.rb
. ดังนั้นแพตช์นี้:
module CoreExtensions
module DateTime
module BusinessDays
def weekday?
!sunday? && !saturday?
end
end
end
end
จะเข้าไปที่ lib/core_extensions/date_time/business_days.rb
.
นักพัฒนาใหม่ทุกคนสามารถเรียกดูไฟล์ Ruby ได้ใน lib/core_extensions
และเรียนรู้สิ่งที่คุณเพิ่มลงใน Ruby และพวกเขาจะ ใช้ วิธีการใหม่ที่สะดวกสบายที่คุณเขียน แทนที่จะเป็นวิธีการที่เพิ่งเข้ามาขวางทาง
คิดให้ถ้วนถี่
ฉันไม่รู้ว่าทำไม Enumerable
ไม่มี sum
กระบวนการ. บ่อยครั้ง ฉันหวังว่าจะได้เขียน [1, 2, 3].sum
หรือ ["a", "b", "c"].sum
, หรือ [Article.new, Article.new, Article.new].sum
… อ้อ.
เมื่อคุณ Monkey patch ชั้นเรียน คุณมักจะคิดถึงสิ่งหนึ่งที่คุณต้องการทำให้ง่ายขึ้น คุณต้องการคำนวณผลรวมของตัวเลข แต่ลืมไปว่า Array สามารถเก็บสิ่งอื่นได้
ตอนนี้มันสมเหตุสมผลแล้ว คุณต้องการ อย่าพยายามคำนวณค่าเฉลี่ยของแฮชจำนวนมาก แต่เมื่อคุณแนบเมธอดกับออบเจ็กต์ที่ล้มเหลวในบางครั้งเมื่อคุณเรียกใช้เมธอด คุณจะสับสนในภายหลัง
คุณสามารถจัดการกับสิ่งนี้ได้หลายวิธี จากดีที่สุดไปหาแย่ที่สุด:
-
จัดการกับอินพุตที่ไม่คาดคิดอย่างสมเหตุสมผล
วิธีนี้ใช้ได้ผลดีหากโปรแกรมแก้ไขของคุณทำงานกับสตริงได้ คุณสามารถรับสิ่งที่สมเหตุสมผลได้จากเกือบทุกอย่างหากคุณเรียก
to_s
กับมันก่อน และ Confident Ruby จะสอนวิธีจัดการกับข้อมูลประเภทต่างๆ มากมาย -
จัดการข้อผิดพลาดให้ชัดเจนยิ่งขึ้น
มันอาจจะง่ายเหมือนการโยน
ArgumentError
พร้อมข้อความดีๆ เมื่อคุณเห็นข้อมูลที่คุณไม่คาดคิด อย่าพึ่งคนอื่นที่เข้าใจแบบสุ่มNoMethodError
ส. -
บันทึกประเภทของข้อมูลที่คุณคาดหวังในความคิดเห็น
อีกสองตัวเลือกจะดีกว่าถ้าคุณสามารถใช้ได้ แต่ถ้าคุณตรวจไม่พบเคสขอบในแพตช์ของคุณ อย่างน้อยก็บันทึกมันไว้ ด้วยวิธีนี้ เมื่อผู้โทรรู้ว่าแพตช์ของคุณเป็นสาเหตุของปัญหา พวกเขาจะมีแนวคิดว่าคุณกำลังพยายามทำอะไร
แพทช์ลิงที่ฉันโปรดปรานตลอดกาล
สุดท้ายนี้ ฉันต้องการให้คุณมีโปรแกรมแก้ไขลิงที่ฉันโปรดปรานตลอดกาล:Hash#string_merge
:
module CoreExtensions
module Hash
module Merging
def string_merge(other_hash, separator = " ")
merge(other_hash) {|key, old, new| old.to_s + separator + new.to_s}
end
end
end
end
{}.string_merge({:class => "btn"}) # => {:class=>"btn"}
h = {:class => "btn"} # => {:class=>"btn"}
h.string_merge({:class => "btn-primary"}) # => {:class=>"btn btn-primary"}
มันทำให้แนบคลาส CSS กับองค์ประกอบ HTML ดังนั้น ดีกว่ามาก
การปะลิงที่สมเหตุสมผล
คลาสหลักของ Monkey-patching core ไม่ได้เลวร้ายไปทั้งหมด เมื่อคุณทำได้ดี มันจะทำให้โค้ดของคุณรู้สึกเหมือนกับ Ruby มากขึ้น แต่เช่นเดียวกับคมอื่นๆ ของ Ruby คุณต้องระมัดระวังเป็นพิเศษเมื่อใช้มัน
หากคุณรวมแพทช์ไว้ด้วยกัน จัดกลุ่มเป็นโมดูล และจัดการกับสิ่งที่ไม่คาดคิด แพทช์ลิงของคุณจะปลอดภัยที่สุด
อะไรคือแพทช์ลิงที่ดีที่สุด คุณ เคยเขียน (หรือเคยเห็น)? แสดงความคิดเห็นและบอกฉันเกี่ยวกับเรื่องนี้!