概要
Return Status Object
前提
Confident Rubyではメソッド内の処理を次のように分類しています。
・Collecting Inputs(引数チェック、変換など)
・Performing Work(主処理)
・Delivering Output(戻り値に関わる処理)
・Handling Failure(例外処理)
当記事は上記のうち、Delivering Outputに関する話です。
詳細
状況
コマンドメソッドが成功・失敗以上の成果物を欲しがるかもしれない。
概要
Statusオブジェクトでメソッドの成果を表す
理由
Statusオブジェクトは単純な成功・失敗より微妙な差異を表すことができる。
サンプルコード仕様
信号を表すクラスSignalを作成します。
Signal#signal_statusでランダムに信号の状態を返却します。
サンプル1
Signal#signal_statusの戻り値を赤=:red, 青=:green, 消灯=:vanishedで返却します。
この場合、利用側は戻り値のシンボルのつづりを正確に知っている必要があります。
サンプル2
SignalStatusクラスを作成します。信号の状態を保持するとともに、
・信号の状態確認用メソッド(SignalStatus#red?, SignalStatus#green?, SignalStatus#vanished?)
・信号の状態別用インスタンス取得メソッド(SignalStatus.red, SignalStatus.green, SignalStatus.vanished)
を持ちます。
Signal#signal_statusの戻り値をSignalStatusクラスの各状態別インスタンスで返却します。
この場合、利用側はSignalStatusが外部公開している振る舞いを元に条件を記述することができます。
サンプルコードその1
module Traffic class Signal def self.signal_status begin case signal_random when 1 :red when 2 :green end rescue :vanished end end def self.signal_random ret = rand(3).to_i + 1 raise 'invalid' if ret == 3 ret end end end 10.times do color = Traffic::Signal.signal_status case color when :green puts "信号が青なので渡ります" when :red puts "信号が赤なので待ちます" when :vanished puts "信号がついていないが渡ります" end end
出力(ランダム)
信号が青なので渡ります 信号が赤なので待ちます 信号が青なので渡ります 信号が青なので渡ります 信号が赤なので待ちます 信号が青なので渡ります 信号が青なので渡ります 信号が赤なので待ちます 信号がついていないが渡ります 信号が赤なので待ちます
サンプルコードその2
require 'pp' module Traffic class SignalStatus RED = "赤" GREEN = "青" VANISHED = "消灯" attr_reader :color def self.green new(GREEN) end def self.red new(RED) end def self.vanished new(VANISHED) end def initialize(color) @color = color end def green? @color == GREEN end def red? @color == RED end def vanished? @color == VANISHED end end class Signal def self.signal_status begin case signal_random when 1 SignalStatus.red when 2 SignalStatus.green end rescue => e return SignalStatus.vanished end end def self.signal_random ret = rand(3).to_i + 1 raise 'invalid' if ret == 3 ret end end end 10.times do signal_status = Traffic::Signal.signal_status if signal_status.green? puts "信号が青なので渡ります" elsif signal_status.red? puts "信号が赤なので待ちます" elsif signal_status.vanished? puts "信号がついていないが渡ります" end end
出力(ランダム)
信号が赤なので待ちます 信号が赤なので待ちます 信号がついていないが渡ります 信号が赤なので待ちます 信号が赤なので待ちます 信号がついていないが渡ります 信号が赤なので待ちます 信号が赤なので待ちます 信号が青なので渡ります 信号が赤なので待ちます