Ruby の静的解析ツール一式をまとめて実行できる RubyCritic を使って静的解析をしていたところ、
Reek の Long Parameter List の警告がでてきて怒られました。
Long Parameter List Smell
Reekのドキュメントにおける Long Parameter List の臭いの説明は以下です。
A Long Parameter List occurs when a method has a lot of parameters.
Long Parameter List - docs - troessner/reek
問題点
引数が多ければ多いほど、関数(メソッド)内部の構造は複雑になる。
原因
ケース1
呼び出し先のメソッド内で計算可能なパラメーターを引き渡している
Before
class Person
attr_reader :first_name, :last_name, :age
def initialize(first_name, last_name, age)
@first_name, @last_name, @age = first_name, last_name, age
end
def display_name
"#{first_name} #{last_name}"
end
def display_age
"(#{age})"
end
def show_name_age
name = display_name
age = display_age
puts display_name_age(name, age)
end
def display_name_age(name, age)
"#{name} #{age}"
end
end
tanaka = Person.new('kazuya', 'tanaka', 34)
tanaka.show_name_age # => kazuya tanaka (34)
After
class Person
attr_reader :first_name, :last_name, :age
def initialize(first_name, last_name, age)
@first_name, @last_name, @age = first_name, last_name, age
end
def display_name
"#{first_name} #{last_name}"
end
def display_age
"(#{age})"
end
def show_name_age
puts display_name_age
end
def display_name_age
"#{display_name} #{display_age}"
end
end
tanaka = Person.new('kazuya', 'tanaka', 34)
tanaka.show_name_age # => kazuya tanaka (34)
ケース2
オブジェクトを渡せばいいところを、バラバラに渡している
Before
class Person
attr_reader :name, :age
def initialize(name, age)
@name,@age = name, age
end
end
def show_name_age(name, age)
puts "#{name} (#{age})"
end
tanaka = Person.new('tanaka', 34)
show_name_age(tanaka.name, tanaka.age) # => tanaka (34)
After
個別のパラメータの代わりにオブジェクトを渡します
class Person
attr_reader :name, :age
def initialize(name, age)
@name,@age = name, age
end
end
def show_name_age(person)
puts "#{person.name} (#{person.age})"
end
tanaka = Person.new('tanaka', 34)
show_name_age(tanaka) # => tanaka (34)
ケース3
まとめたほうがいいパラメータをバラバラに扱っている
Before
def show_name_age(name, age)
puts "#{name} (#{age})"
end
show_name_age("tanaka", 34) # => tanaka (34)
After
class Person
attr_reader :name, :age
def initialize(name, age)
@name,@age = name, age
end
end
def show_name_age(person)
puts "#{person.name} (#{person.age})"
end
tanaka = Person.new('tanaka', 34)
show_name_age(tanaka) # => tanaka (34)