Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

書籍 リファクタリング−プログラマーの体質改善 | オブジェクト間での特性の移動 | 外部メソッドの導入

内容

適用ケース要約

利用中のサーバクラスにメソッドを追加する必要があるが、そのクラスを変更できない

適用内容要約

クライアントクラスに、サーバクラスのインスタンスを第一引数に取るメソッドを作る

適用詳細

事情により、ソースコードを編集することが出来ないクラスに対して機能を追加したい場合、
クライアント側にサーバサーバクラスのインスタンスを第一引数にとるメソッドを追加します。
※あくまでJavaの書籍を基準にした内容なので、この前提で進めますがRubyの場合は
 オープンクラスにより既存コードに影響を与えることなく処理を追加できます。
 そのため、Javaのみで有効となるリファクタリング手法です。

サンプル

ある文章を「諸見里」語に変換します。
前提としてこのプログラムの作成者はStringクラスに諸見里語への翻訳機能を追加するのが妥当だと
思っています。

ここでの定義
諸見里語=「さ、す、せ、そ」が「しゃ、しゅ、しぇ、しょ」に変わる

しかし、JavaのStringクラスを変更することはできないため、自分のクラスに変換用のメソッドを追加します。
※諸見里については以下を参照
http://ja.wikipedia.org/wiki/%E8%AB%B8%E8%A6%8B%E9%87%8C%E5%A4%A7%E4%BB%8B

サンプルコード

リファクタリング

class Moromizato
  def talk(message)
    moromizato_change_word_list={""=>"しゃ",""=>"しゅ",""=>"しぇ",""=>"しょ"}
    moromizato_message=message
    moromizato_change_word_list.each{|before,after|
      moromizato_message=moromizato_message.gsub(before,after)
    }
    return moromizato_message
  end
end

moromizato=Moromizato.new
message="せたがやのさかな屋さんのそばにしらない人がいた。すごい。"
puts "原文:#{message}"
puts "諸見里:#{moromizato.talk(message)}"

リファクタリング

class Moromizato
  def talk(message)
    return to_moromizato message
  end
  
  def to_moromizato(message)
    moromizato_change_word_list={""=>"しゃ",""=>"しゅ",""=>"しぇ",""=>"しょ"}
    moromizato_message=message
    moromizato_change_word_list.each{|before,after|
      moromizato_message=moromizato_message.gsub(before,after)
    }
    return moromizato_message
  end
end

moromizato=Moromizato.new
message="せたがやのさかな屋さんのそばにしらない人がいた。すごい。"
puts "原文:#{message}"
puts "諸見里:#{moromizato.talk(message)}"

▼出力結果(共通)

原文:せたがやのさかな屋さんのそばにしらない人がいた。すごい。
諸見里:しぇたがやのしゃかな屋しゃんのしょばにしらない人がいた。しゅごい。
解説

諸見里語への変換機能をメソッドとして抽出したことで、
変換機能がクラス内で再利用可能となりました。

おまけ

RubyのオープンメソッドでStringクラスを拡張した場合。
あたかもStringクラスに組み込まれている機能であるかのように
諸見里語変換機能が利用できます。

class String
  def to_moromizato()
    moromizato_change_word_list={""=>"しゃ",""=>"しゅ",""=>"しぇ",""=>"しょ"}

    moromizato_message=self
    moromizato_change_word_list.each{|before,after|
      moromizato_message=moromizato_message.gsub(before,after)
    }
    return moromizato_message
  end
end

message="せたがやのさかな屋さんのそばにしらない人がいた。すごい。"
puts "原文:#{message}"
puts "諸見里:#{message.to_moromizato}"