Tbpgr Blog

Ruby プログラマ tbpgr(てぃーびー) のブログ

書籍 リファクタリング−プログラマーの体質改善 | メソッドの構成 | メソッドの抽出:Extract Method

内容

リファクタリング

メソッドの抽出:Extract Method

適用ケース要約

1つにまとめられるコードの断片がある

適用内容要約

コードの断片をメソッドにして、その目的を説明する名前をつける

適用詳細

長すぎるメソッドなどに対して、ひとかたまりの処理をメソッドとして抽出します。
良いメソッド名をつけ、処理を短くすればメソッド名自体がコメントの役割を果たします。

メソッドを細かく分けることで以下の利点があります
・問題の局所化
・再利用性の向上
・可読性の向上
・保守性の向上

サンプル

あるメッセージを5回表示する機能を実装します。
メッセージの表示前には現在時刻を「YYYY年MM月DD日HH時MM分SS秒」形式の日付と区切り線を表示します。
メッセージの表示後には区切り線と「実行を終了しました」を表示します。

サンプルコード

※便宜上変更前と変更後でメソッド名が変わってますが本来は同じです。
 サンプルコードはRubyで実装してあります

リファクタリング

def output_message_before(message)
  raise 'nil' if message.nil?
  raise 'empty' if message.empty?
  
  date = Time.new
  print "#{date.year}"
  print "#{date.month}"
  print "#{date.day}"
  print "#{date.hour}"
  print "#{date.min}"
  print "#{date.sec}"
  puts "\n----------------------------------------"
  
  strong_message = "#{message}"
  
  (1..5).each {|number|
    puts "#{strong_message}#{number}"
  }

  puts "----------------------------------------"
  puts "実行を終了しました"
end

output_message_before("メソッドの抽出:リファクタリング前")

▼出力結果

2012年3月20日22時49分17秒
----------------------------------------
【メソッドの抽出:リファクタリング前】1
【メソッドの抽出:リファクタリング前】2
【メソッドの抽出:リファクタリング前】3
【メソッドの抽出:リファクタリング前】4
【メソッドの抽出:リファクタリング前】5
----------------------------------------
実行を終了しました


リファクタリング

def output_message_after(message)
  check_message message
  output_current_datetime
  strong_message = get_strong_message message
  (1..5).each {|number|
    puts "#{strong_message}#{number}"
  }
  output_finish_message
end

private
def check_message(message)
  raise 'nil' if message.nil?
  raise 'empty' if message.empty?
end

private
def output_current_datetime()
  # メソッド内でしか使用しない変数date
  date = Time.new
  print "#{date.year}"
  print "#{date.month}"
  print "#{date.day}"
  print "#{date.hour}"
  print "#{date.min}"
  print "#{date.sec}"
  puts "\n----------------------------------------"  
end

private
def get_strong_message(message)
  return "#{message}"
end

private
def output_finish_message()
  puts "----------------------------------------"
  puts "実行を終了しました"
end

output_message_after("メソッドの抽出:リファクタリング後")

▼出力結果

2012年3月20日22時51分22秒
----------------------------------------
【メソッドの抽出:リファクタリング後】1
【メソッドの抽出:リファクタリング後】2
【メソッドの抽出:リファクタリング後】3
【メソッドの抽出:リファクタリング後】4
【メソッドの抽出:リファクタリング後】5
----------------------------------------
実行を終了しました
解説

リファクタリング後の各メソッドについて。

▼output_finish_message
最後に表示するメッセージの表示処理のみを抽出したメソッドです。
引数も一時変数もないため単純に処理の一部をコピーして新しいメソッドに移動するだけです。

▼output_current_datetime
最初に表示するカレント日付の表示処理のみを抽出したメソッドです。
日付の処理で使用するdate変数が一時変数にありましたが、
メソッド内部でしか利用されないため呼び元の一時変数は削除できます。

▼check_message
メッセージが正しいかどうかチェックする処理を抽出するメソッドです。
他の箇所でも利用する変数であるmessageを使用するため、引数にmessageを追加しています。

▼get_strong_message
メッセージを墨付き括弧で強調するメソッドです。
引数に元のメッセージであるmessageを追加、
戻り値として強調後のmessageを返却します。