概要
Yield a parameter builder object
前提
Confident Rubyではメソッド内の処理を次のように分類しています。
・Collecting Inputs(引数チェック、変換など)
・Performing Work(主処理)
・Delivering Output(戻り値に関わる処理)
・Handling Failure(例外処理)
当記事は上記のうち、Collecting Inputsに関する話です。
詳細
状況
オブジェクトへのパラメータのバインドの結果として、
クライアントは多くの異なるクラス利用のAPIを知らなければならない。
概要
パラメータオブジェクトの初期化を隠ぺいし、
parameter objectやparameter builder objectをyieldする。
理由
builder-baseのインターフェースは複雑なオブジェクト生成のために親しみやすいフロントエンドを提供する。
同時に、安定しているAPIを保つために実装とインターフェースを分けられる。
サンプルコード仕様
色と濃さを指定して文字を書くメソッド(write_by_pencil)を実装します。
引数は、
・色・文字
・ペンスタイルオブジェクト(PencilStyle)
のどちらかを受け取ります。
仕様追加によりペンスタイルオブジェクトがペン種別(シャーペン、ボールペン、サインペンなど)を持てるようになりました。
可能なら write_by_pencil のインターフェースを変更するのが利用ですが、このメソッドはすでに広く利用されており
デグレードの可能性も大きいことからインターフェースを変更したくありません。
そこで、本処理の直前でペンスタイルオブジェクト(PencilStyle)をyieldすることで、
インターフェースを変えないままペン種別を利用可能にします。
サンプルコード(その1)
仕様追加前。
class PencilStyle attr_reader :color, :deapth def initialize(color, deapth) @color, @deapth = color, deapth end end def write_by_pencil(color_or_pencil_style, deapth = :not_use_deapth) pencil_style = color_or_pencil_style.is_a?(String) ? PencilStyle.new(color_or_pencil_style, deapth) : color_or_pencil_style "#{pencil_style.color}色、濃さ#{pencil_style.deapth}で文字を書きました。" end pencil_style1 = PencilStyle.new("赤", "B") pencil_style2 = PencilStyle.new("緑", "HB") puts write_by_pencil("黄", "3B") puts write_by_pencil(pencil_style1) puts write_by_pencil(pencil_style2)
出力
黄色、濃さ3Bで文字を書きました。 赤色、濃さBで文字を書きました。 緑色、濃さHBで文字を書きました。
サンプルコード(その2)
仕様追加後。引数は変更せずブロックによって新規パラメータを設定可能にしています。
class PencilStyle attr_reader :color, :deapth def initialize(color, deapth, type = "鉛筆") @color, @deapth, @type = color, deapth, type end def type @type end def type=(type) @type = type end end def write_by_pencil(color_or_pencil_style, deapth = :not_use_deapth) pencil_style = color_or_pencil_style.is_a?(String) ? PencilStyle.new(color_or_pencil_style, deapth) : color_or_pencil_style yield(pencil_style) if block_given? "#{pencil_style.color}色の#{pencil_style.type}で濃さ#{pencil_style.deapth}の文字を書きました。" end pencil_style1 = PencilStyle.new("赤", "B") pencil_style2 = PencilStyle.new("緑", "HB", "ボールペン") ret = write_by_pencil("黄", "3B") do |pencil_style| pencil_style.type = "筆" end puts ret ret = write_by_pencil(pencil_style1) puts ret ret = write_by_pencil(pencil_style1) do |pencil_style| pencil_style.type = "シャーペン" end puts ret ret = write_by_pencil(pencil_style2) puts ret ret = write_by_pencil(pencil_style2) do |pencil_style| pencil_style.type = "蛍光ペン" end puts ret
出力
黄色の筆で濃さ3Bの文字を書きました。 赤色の鉛筆で濃さBの文字を書きました。 赤色のシャーペンで濃さBの文字を書きました。 緑色のボールペンで濃さHBの文字を書きました。 緑色の蛍光ペンで濃さHBの文字を書きました。