2

私はおそらく、遅延インスタンス化されたメソッド/属性を最もルビーな方法で書いているわけではないと思います。例として、次の方法を取り上げます。

def tax
  @tax ||= Proc.new do
    if flat_tax > commission_plan.tax_max
      return commission_plan.tax_max
    end if commission_plan.tax_max
    if flat_tax < commission_plan.tax_min
      return commission_plan.tax_min
    end if commission_plan.tax_min
    flat_tax
  end.call
end

このメソッドをリファクタリングするためのよりルビーのような方法はありますか?

4

4 に答える 4

6
def tax
  @tax ||= calc_tax
end

private

def calc_tax
  min, max = commission_plan.tax_min, commission_plan.tax_max
  if (min..max).include? flat_tax
    flat_tax
  else
    flat_tax > max ? max : min
  end
end
于 2012-06-27T20:38:58.047 に答える
2

あなたがそれについて尋ねているのは、メモ化と呼ばれるものです。Yuri が示唆するように、これに Proc を使用しているのは厄介です。

これが私の簡単なリファクタリングです。私はおそらくこれをさらにリファクタリングするでしょう...しかし、それは単純なリファクタリングであり、よりRubyに似ています。

def tax
  @tax ||= calculate_tax
end

def calculate_tax
  if commission_plan.tax_max && flat_tax > commission_plan.tax_max
    commission_plan.tax_max
  elsif commission_plan.tax_min && flat_tax < commission_plan.tax_min
    commission_plan.tax_min
  else 
    flat_tax
  end
end

また、いくつかの外部依存関係を含めることを気にしない場合は、ActiveSupport::Memoizableを確認してください。そして、これがメモ化について語る記事です。

于 2012-06-27T20:33:11.197 に答える
2

外部ライブラリに依存関係を追加したくない場合は、独自の「メモ化」ヘルパーを簡単に追加できます。次のようなもの:

class Class
  def memoize(method)
    original_method = instance_method(method)
    instance_var = "@__#{method}__".to_sym
    define_method(method) do |*a,&b|
      cached = instance_variable_get(instance_var)
      unless cached
        cached = old_method.bind(self).call(*a,&b)
        instance_variable_set(instance_var, cached)
      end
      cached
    end
  end
end

そして、使用法は次のようになります。

def tax
  # expensive calculation here
end
memoize :tax

このインターフェイスが気に入らない場合は、好きなmemoizeものに変更できます。これはルビーです、ベイビー!風船ガムのようにひねったり、曲げたり、伸ばしたりできる言葉。たぶん、このようなインターフェースがいいでしょう:

def_memoized :tax do
  # expensive calculation here
end

プロジェクトごとの拡張機能を Ruby のコアに というファイルに入れるのが好きですlib/core_extensions.rb。これはそこに入るようなものです。

于 2012-06-27T20:52:35.560 に答える
1

この匿名関数を作成する理由がわかりません。それは...冗長です。これは、はるかに優れたクリーンなコードです。

def tax
    return commission_plan.tax_max if commission_plan.tax_max &&
        flat_tax > commission_plan.tax_max
    return commission_plan.tax_min if commission_plan.tax_min &&
        flat_tax > commission_plan.tax_min
    return flat_tax
end

それを実装する他の方法がありますが、これはあなたが持っているものと比較して大幅に改善されています.

于 2012-06-27T20:23:04.793 に答える