Tbpgr Blog

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

不揃いな粒度の処理をComposedメソッドで統一する

臭い名

不揃いな粒度の処理

臭い英名

Irregularity Granularity

リファクタリング

Composedメソッドパターンで処理の粒度を統一

リファクタリング英名

Apply Composed Method Pattern

改善理由

・処理の粒度がばらばらだと可読性が下がる
・粒度を合わせてメソッドを細かく分割すると、別のリファクタリングの元ネタになる事が多い

対応

・粒度に合わせてprivateメソッドを作成して処理を分割する

サンプルコード

要件

ファイル内の文字列に含まれる母音の数をカウントして標準出力します。
引数の数1つではない場合、ファイルパスではない場合はエラーとして処理を即終了します。

リファクタリング
# encoding: utf-8
class VowelCounter
  def count_vowel()
    raise "error" unless $*.size == 1
    raise "error" unless FileTest.exist?($*[0])
    
    contents = ""
    File.open($*[0]) do |f|
      contents = f.read
    end

    ret = contents.scan(/[aiueo]/)
    return ret.size
  end
end

ecc = VowelCounter.new
puts ecc.count_vowel
リファクタリング
# encoding: utf-8

class String
  def count_vowel()
    self.scan(/[aiueo]/).size
  end
end

class File
  def self.read_all(filename)
    File.open(filename) {|f|contents = f.read}
  end
end

class VowelCounter
  def count_vowel()
    validate_args_length 1
    validate_args_file 0
    
    filename = get_filename()
    text = File.read_all(filename)

    text.count_vowel
  end

  private
  def validate_args_length(len)
    raise "error" unless $*.size == len
  end

  def validate_args_file(index)
    raise "error" unless FileTest.exist?($*[index])
  end

  def get_filename
    $*[0]
  end
end

ecc = VowelCounter.new
puts ecc.count_vowel
出力
$cat hoge.txt
hoge
hage
hige
$ruby before.rb hoge.txt
6
$ruby after.rb hoge.txt
hoge.txt
6

備考

リファクタリング前はただ、ダラダラと書き連ねたコードになっています。
コードの意味はプログラム内容を把握するにはコードの意味を細かく読み取っていく必要があります。
「何をしているか」よりも「どうやっているか」が前面に出てしまい、可読性をそこねています。

リファクタリング後はメソッド名や変数名を見るだけで、処理内容を把握出来ます。
処理の実装の詳細が知りたければ各privateメソッドを確認すれば良いですし、
確認しなくてもやっていることはおおまかに読み取れます。
また、privateメソッドとして抽出した内容から更にオープンクラスへ2つのメソッドを移動しました。
このようにComposed Methodパターンは次なるリファクタリングの元になります。