Chossing Message
会社の先輩から『Smalltalkベストプラクティスパターン』って本を借りたのでおっ(^ω^)と思ったパターンをメモっていく。
Chossing Message
さまざまな選択肢のうちのひとつを実行させるにはどうしますか?
Rubyで書くとこういうケースのことだと思う。
class Factory def food(type) if(type == 'cat') 'CatFood' elsif(type == 'dog') 'DogFood' elsif(type == 'person') 'カレー' end end end f = Factory.new p f.food('cat') p f.food('dog')
Factory#foodに文字列を渡すと引数に一致する処理を実行する。
こういうハードコーディングだと問題があって、
既存のロジックをいじらずにバリエーションを追加することがとても難しくなる。増殖する傾向にある。
本では以下のようにするとよいと書いている。
class Cat def food "CatFood" end end class Dog def food "DogFood" end end class Factory def food(obj) obj.food end end tama = Cat.new poti = Dog.new f = Factory.new p f.food(tama) p f.food(poti)
条件文がなくなった!
クラスが増えていくけどMVCフレームワークでは普通に使えそうだと思った。
いくつかのオブジェクトを用意して、そのうちの1つにメッセージを送り、各オブジェクトがひとつの選択肢を実行するようにしましょう。
Railsで使ってみた
このRailsアプリはソーシャルネットワーキングサービスを作っている。イメージはmixiみたいな感じ。
機能
ユーザは記事、辞典、写真、コミュニティを公開できる。
それぞれのコンテンツは非公開状態にすることができ、非公開状態の場合は作成者のみが閲覧できる。
公開の制御するコードをChoosing Messageを使わないで自分なりに書くと
class BaseController < ApplicationController def can_not_access_to_private_content if not owner? render_404 if @article.try(:private?) render_404 if @dic.try(:private?) render_404 if @photo.try(:private?) render_404 if @comunitie.try(:private?) end end end
ArticlesController < BaseController def show @article = Article.find(params[:id]) can_not_access_to_draft end end DictionariesController < BaseController def show @dic = Dictionary.find(params[:id]) can_not_access_to_draft end end . . .
となってモデルが増える度に同じこと書かないといけない。漏れがでてきそう。
Chossing Messageっぽく書く
class BaseController < ApplicationController before_action :set_item, only: [:show] def set_item item_constant = params[:controller].singularize.capitalize.constantize @item = item_constant.find(params[:id]) can_not_access_to_draft end def can_not_access_to_private_content if not logged_in? render_404 if @item.private? end end end
ArticlesController < BaseController def show end end DictionariesController < BaseController def show end end . . .