オプションのための引数をどのような形で用意するか

前回の Ruby で Twitter/Facebook/はてなブックマーク等の各種カウント情報を取得する - Life like a clown に関連してですが,あるメソッドを定義する際に「このメソッド,多分そのうちオプションがいっぱい出てきそうなんだけど,引数の定義どうしよう?」みたいな事でよく悩みます.特に,ライブラリとして外部に公開する場合,メソッドの引数を変更してしまう事は(変更前のバージョンを利用しているユーザへの影響度的に)有名になればなるほどやりづらくなるため,初期段階でできるだけ納得のいく形で決めておきたいと言う要求があります.

一方で,「どんな情報を設定する事になるかなんて,いろいろなパターンで実際に使ってみないとわからないよ!」みたいな実情がありまして,本来であれば,いろいろなパターンで実際に使った(テストした)後に最終的な引数(を含むインターフェース)を決定して公開すると言う手順を踏むのが理想なのですが,まぁ個人の趣味レベルでやってる場合,そこまで厳格にやっていくのは時間的にもモチベーションの維持的にもなかなか難しく,「その辺は適当に手抜きして取りあえず公開してみたい」と言う誘惑が常について回ります.

そう言った 2 つの要求を満たすために,「取りあえず,メソッドの最後の引数に(例えば options と言う)連想配列を設定できるようにしておく」と言う形で手抜きするのが比較的うまくいくようです.

#!/usr/bin/ruby -Ku

def some_method(required_argument, options = {})
    main_operation(required_argument)
    
    # 新たなオプションを追加した場合,ここの内部コードを書き換える
    options.each { |key, value|
        case key
        when :foo
            operation_about_foo(value)
        when :bar
            operation_about_bar(value)
        else
            # よく分からないオプションが指定された場合は無視するようにしておく.
        end
    }
end

# main
some_method('hoge', { :foo => 'fuga', :bar => 1, :bas => 3.14 })

以上のような話を雑談でしゃべっていたところ,こう言った方法は既に「定石的な方法」として結構広まっているようで,そう言えば,RubyJavaScript のライブラリを使用するときに,こう言った形で指定させるものが多いなぁと今更ながらに気付いたと言うお話でした.まる.