概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Flag arguments are a code smell
- 原文公開日: 2017/05/04
- 著者: Jeroen Weeink
- サイト: Crafting Ruby
Ruby: フラグ引数は「コードの臭い」(翻訳)
フラグ引数は、メソッドの振る舞いを変更するbooleanです。フラグ引数があるということは、このコードが外的要素に応じていくつものシナリオを演じていることを示しています。高度なレベルのコード片が、低レベルメソッドひとつで右往左往しているのです。
次の簡単なコード例で考えてみましょう。
def create_task(description, priority, preview: true, email: true)
task = Task.new
task.status = "open"
task.description = description
task.priority = priority
unless preview
task.save!
index_in_search_engine(task)
send_task_created_email_notification(task) if email
end
task
end
preview
とemail
がこのメソッドのフラグ引数です。このメソッドは、必要に応じてさまざまな形で呼び出されることになります。このフラグ引数は、メソッド呼び出しに何らかの混乱をもたらします。
# タスクを1件作成してメール通知を1件送付
create_task("Read the newspaper", "low", preview: false)
# タスクを1件作成するがメール通知は送信しない
create_task("Read the newspaper", "low", preview: false, email: false)
# プレビュー用のタスクを作成する
create_task("Read the newspaper", "low", preview: true)
さまざまなシナリオで使われるロジックがcreate_task
に相乗りしているため、メソッドが少々読みづらくなっています。あるシナリオを理解するためには他のシナリオを除外して考えなければならなくなるので、余分な集中力を求められます。フラグ引数の数が増えれば、あっという間に複雑化して手に負えなくなるでしょう。
普通のメソッドはこのようにして生まれたりしません。ロジックで小さな変更を求められたときに、フラグ引数で済ませてしまうと、すぐにでもそうなります。
コードの臭いを消すには、メソッドをもっと小さい複数のメソッドに分割します。
def create_task_and_send_notification(description, priority)
create_task(description, priority).tap do |task|
send_task_created_email_notification(task)
end
end
def create_task(description, priority)
build_task(description, priority).tap do |task|
task.save!
index_in_search_engine(task)
end
end
def build_task(description, priority)
Task.new.tap do |task|
task.status = "open"
task.description = description
task.priority = priority
end
end
これなら、それぞれのメソッドは異なるシナリオで実行されますし、ほぼ何の苦労もなく読めます。フラグ引数でメソッドの振る舞いを変えるのではなく、シナリオに応じて呼ぶメソッドを変えれば済みます。
# タスクを1件作成してメール通知を1件送付
create_task_and_send_notification("Read the newspaper", "low")
# タスクを1件作成するがメール通知は送信しない
create_task("Read the newspaper", "low")
# プレビュー用のタスクを作成する
build_task("Read the newspaper", "low")