発生している問題
Ruby(2.5.1)の勉強の一環として、計算機を作ってみようと思いました。空白区切りで数値と演算子を与え、答えを出力する簡単なものです。
in
11 + 1
out
12
足し算、引き算、掛け算に関しては特に詰まることなく実装できたのですが、第二数が0となった場合の割り算についてどのように実装するべきか戸惑いました。
考えたこと
特に別の処理をしない
最初に考えたのは、特に他の演算と別の処理を行わないことです。第二数に0が指定された場合、ZeroDivisionErrorが発生してプログラムは停止します。
calc.rb
1def calc(a, op, b) 2 case op 3 # 他演算子の処理、中略 4 when "/" 5 return a / b 6 end 7end
in
11 / 0
out
1divided by 0 (ZeroDivisionError)
先に判別し、nilを返す
次に考えたのは、先に第二数が0であるかどうか判別し、0であった場合はnilを返すことです。nilが返ってきた場合は呼び出し元でエラーメッセージを出力することを想定しています。
calc.rb
1 when "/" 2 if b == 0 then return nil end 3 return a / b 4 end
in
11 / 0
out
1ゼロで割ることは出来ません
質問
このような場合、特に触らずに例外を投げるのと先に弾くのだと、どちらのほうが良いのでしょうか。今までC++を書いていたので、予測でき回避できる例外はプログラム側で弾いたほうがいいのではと思っているのですが、言語側が詳細なエラーを投げてくれるならそのままにしたほうがいいのかなというような気もして迷っている次第です。Rubyの慣習としてこうするよ、だったり例外とreturn nilはこう使い分けるよ、だったりという意見をいただければ幸いです。
長文をお読みいただきありがとうございました。よろしくお願いします。
解決しました!
いくつもの回答を参考にさせていただいたので、質問への追記という形で回答の要約と私が取った解決法を共有させていただきます。今回、
- Rubyでは、例外はそんなに怖がらなくて大丈夫
- むしろ、nilを返すほうが何が起こったのかわからなくてまずい
- 例外を投げる場合は、プログラムのバグなのかユーザー側の問題なのかわかるようにする (たとえば、例外クラスを作る)
- 想定内の入力によって投げられた例外でプログラムが終了するのを避ける。例外をキャッチして、エラーメッセージを出す
- 操作をする前に例外が発生することが予見できるなら、先に判別して例外を投げる
- (異常な値を返すにせよ例外を投げるにせよ) 妥当性の確認は仕様に従い、穴がないように作る
というアドバイスをいただきました。
今回は期待する入力は数字二個の間に演算子、という仕様を想定していたので、
- 入力が変なものじゃないかを正規表現で確認する。変なものだったら独自エラークラスを作成して投げる
- ゼロ除算が発生するときにはreturn nilを避け、例外を投げる。計算前に、raise ZeroDivisionError if b == 0を行う
- 例外を入出力を行っているメソッド (私の場合はトップレベルでした) で捕捉し、種別に合ったエラーメッセージを出す
といった実装にしようと思います。
最後に、回答いただいた皆様にお礼を申し上げて締めさせていただきます。皆様にご回答いただいたおかげで知見がとても広がりました。また機会があればよろしくお願いします。ありがとうございました!

回答6件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/08/29 23:54
2018/08/30 17:55
2018/08/31 13:34