LoginSignup
3
1

More than 3 years have passed since last update.

`return "エラーメッセージ"` はやめてくれ

Last updated at Posted at 2019-09-10

戻り値としてエラーメッセージを返す関数・メソッドはやめてください。

例えば、こんなファイルの内容をチェックする関数です。

# ファイルの内容が正しいかチェックする関数
def check_file_format(path)
  return 'ファイルが存在しません' unless File.exist?(path)
  contents = File.read(path)
  return 'ファイルが長すぎます' if contents.lines.size > 500
  return 'シバンを書いてください' if contents.lines.first.starts_with('#!')
  return '行末に空白があります' if contents.lines.any? { |l| l.ends_with?(' \n') }
  # 以下チェックが続く
end

# 関数を使う側(WEB版)
class FileController < ApplicationController
  def check
    @error_message = check_file_format(params[:path])
  end
end

# 関数を使う側(CLI版)
def main
  error_message = check_file_format(params[:path])
  puts(error_message)
end

こういった関数は、以下のような要望が出てきた時点で破綻します。

「ファイルが長すぎます」と指摘されて直した後、「行末に空白があります」と指摘されるのは面倒です。初めから両方を出すことはできませんか?

戻り値を「エラーメッセージ」から、「エラーメッセージのリスト」に変えればいいって? ええ、あなたがこの関数を呼び出している、200か所を全部直してくれるなら。

どうするべきだったのか?

エラーメッセージは、生文字列ではなく、クラスでラップして返しましょう。
クラスになっていれば、コンストラクタの引数を増やしたり、メソッドを足したりして、将来の変更に耐えることができます。

class Result
  def initialize(message)
    @nessage = message
  end

  def message
    @message
  end
end

def check_file_format(path)
  return Result.new('ファイルが存在しません') unless File.exist?(path)
  contents = File.read(path)
  return Result.new('ファイルが長すぎます') if contents.lines.size > 500
  return Result.new('シバンを書いてください') if contents.lines.first.starts_with('#!')
  return Result.new('行末に空白があります') if contents.lines.any? { |l| l.ends_with?(' \n') }
  # 以下チェックが続く
end
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1