たとえば、次のようなタイプと値を指定すると特定の処理をしてくれるメソッドがあったとします。
def sortMethod(type,val) case type when :name then val.upcase when :val then val.next end end sortMethod(:name, "name") #>> "NAME" sortMethod(:val, 12) #>> 13
これをリファクタリング……というか、別の方法で実装してみます。
別実装
Hashとlambda記法
値にlambdaをもつハッシュに置き換えてあげる事もできます。
動作はこんな感じ
altCase = {name: ->(x){ x.upcase}, val: ->(x){x.next} } altCase[:name].call("name") #>> "NAME" altCase[:val].call(12) #>> 13
見た目短いです。再帰なんか使う局面では有効そう?
クラスをつくる
まぁ、オブジェクト指向言語なんですから、クラスでかき分けるのがいいでしょね。
リファクタリング:Rubyエディションにもそう書いてある。
class SortMethodClass def self.name(x); x.upcase; end def self.val(x); x.next; end end SortMethodClass.name("name") #>> "NAME"
速度比較
Benchmark.ips do |x| x.report( "Method" ) { sortMethod(:name, "name") } x.report( "HashWithProc" ) { altCase[:name].call("name") } x.report( "Class" ) { SortMethodClass.name("name") } x.compare! end
というベンチマークでみると
Calculating ------------------------------------- Method 68.134k i/100ms HashWithProc 73.034k i/100ms Class 82.339k i/100ms ------------------------------------------------- Method 2.597M (±13.8%) i/s - 12.605M HashWithProc 1.930M (±20.2%) i/s - 9.056M Class 2.790M (±17.2%) i/s - 13.257M Comparison: Class: 2789970.3 i/s Method: 2597019.6 i/s - 1.07x slower HashWithProc: 1929799.9 i/s - 1.45x slower
……クラスの方が早いじゃないか(憤怒)
可視性も拡張性も段違いなので、残念ながら今回は王道のクラス実装に軍配があがりますね。