元編程

2018-02-24 16:10 更新
  • 避免無(wú)謂的元編程。

  • 寫(xiě)一個(gè)函數(shù)庫(kù)時(shí)不要使核心類(lèi)混亂(不要使用 monkey patch)。

  • 傾向使用區(qū)塊形式的?class_eval?而不是字符串插值(string-interpolated)的形式。

    • 當(dāng)你使用字符串插值形式時(shí),總是提供?__FILE__?及?__LINE__,使你的 backtrace 看起來(lái)有意義:

      class_eval "def use_relative_model_naming?; true; end", __FILE__, __LINE__
    • 傾向使用?define_method?而不是?class_eval{ def ... }
  • 當(dāng)使用?class_eval?(或其它的?eval)搭配字符串插值時(shí),添加一個(gè)注解區(qū)塊,來(lái)演示如果做了插值的樣子(我從 Rails 代碼學(xué)來(lái)的一個(gè)實(shí)踐):

    # activesupport/lib/active_support/core_ext/string/output_safety.rb
    UNSAFE_STRING_METHODS.each do |unsafe_method|
      if 'String'.respond_to?(unsafe_method)
        class_eval <<-EOT, __FILE__, __LINE__ + 1
          def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)
            to_str.#{unsafe_method}(*args, &block) # to_str.capitalize(*args, &block)
          end # end
    
          def #{unsafe_method}!(*args) # def capitalize!(*args)
            @dirty = true # @dirty = true
            super # super
          end # end
        EOT
      end
    end
  • 元編程避免使用?method_missing。會(huì)讓 Backtraces 變得很凌亂;行為沒(méi)有列在?#methods?里;拼錯(cuò)的方法調(diào)用可能默默的工作(nukes.launch_state = false)。考慮使用 delegation, proxy, 或是?define_method?來(lái)取代。如果你必須使用?method_missing

    • 確保?也定義了?respond_to_missing?
    • 僅捕捉字首定義良好的方法,像是?find_by_*——讓你的代碼愈肯定(assertive) 愈好。
    • 在語(yǔ)句的最后調(diào)用?super
    • delegate 到確定的、非魔法方法中:

      # 差
      def method_missing?(meth, *args, &block)
        if /^find_by_(?<prop>.*)/ =~ meth
          # ... lots of code to do a find_by
        else
          super
        end
      end
      
      # 好
      def method_missing?(meth, *args, &block)
        if /^find_by_(?<prop>.*)/ =~ meth
          find_by(prop, *args, &block)
        else
          super
        end
      end
      
      # 最好的方式,可能是每個(gè)可找到的屬性被聲明后,使用 define_method。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)