Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

3 วิธีในการปะลิงโดยไม่ทำให้ยุ่งเหยิง

การปะลิง. เมื่อคุณลองใช้ 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 :

lib/core_extensions/hash/merging.rb
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 คุณต้องระมัดระวังเป็นพิเศษเมื่อใช้มัน

หากคุณรวมแพทช์ไว้ด้วยกัน จัดกลุ่มเป็นโมดูล และจัดการกับสิ่งที่ไม่คาดคิด แพทช์ลิงของคุณจะปลอดภัยที่สุด

อะไรคือแพทช์ลิงที่ดีที่สุด คุณ เคยเขียน (หรือเคยเห็น)? แสดงความคิดเห็นและบอกฉันเกี่ยวกับเรื่องนี้!