DCI を考える
追記
まじで鳩さんのスライドでDCIについて理解したつもりになるの危険だからやめた方がいいです。せめて d.hatena.ne.jp/digitalsoul/20… を読みましょう。DCIはエンドユーザのメンタルモデルを実装に落とし込むための設計パラダイムです
— Naoto Takai (@takai) December 27, 2012
ということで、以下の内容はすべて間違いである可能性が高いです。
元記事
Data - Context - Interaction いわゆる DCI が最近の人気らしい。 DCI そのものの説明をこのエントリでする気はないので、 Sapporo Ruby Kaigi の角谷さんのプレゼンなどを見るとよい。
Rails の場合、 Data はまぁ ActiveRecord / Mongoid などのいわゆる MVC におけるモデル、であっていると思う。これについては何も違和感がなくて、 validation などがモデルに含まれていても僕は違和感がない。それはデータが正当かどうかを検証するロジックであり、それらはモデルが抱えるべきメソッドだからだ。
んで、 Interaction も多分普通の Module とかで問題ない。これを Role と捉える見方もあるし、Decorator Pattern の Decorator みたいなもんだろというのも聞いた。松田さんの ActiveDecorator なんかはまさに View の Context でのみ稼働する Interaction だと僕は捉えてる。
では、 Context とはなんなのか、どこにあるべきなのか、が目下の問題と懸念である。 DCI そのものは僕は概ね Strategy Pattern なんじゃないっすかねみたいな気持ちでいる(Strategy Pattern は正確には実装を取り替え可能にするもので、インターフェースが動的に変化するものではない)ので、試しに ActiveStrategy を作ってみた。なかなかうまく行ったとは思っていて、これによって実装を切り出すことができたのは有意義だなと思ったけれど、 ActiveStrategy は言ってみればすこし便利な include で、結局モデルに strategy :hoge
を書いてしまっているので、モデルが太っていくことに変わりはない。無念である。
僕が嬉しい DCI な場面ってのは、つまるところこんな感じだ。
ユーザーとカートとアイテムのモデルがある。
class User attr_reader :name, :id has_one :cart end class Cart belongs_to :user has_and_belongs_to_many :items end class Item has_and_belongs_to_many :cart end
アイテム画面のコントローラと、カート画面のコントローラがある。
class ItemsController def add_to_cart user.cart.items << item end end class CartsController def remove_item user.cart.items.delete(item) end end
今回はごく単純な例なので、普通に Array#push みたいなことをすれば気が済むのだけれど、これがもっと条件が複雑になる(たとえばチャージしているポイント以上はカートに積めないとか)と、途端にコントローラが太り、モデルに移して事無きを得る(とともにモデルが肥満児童みたいになっていく)。
こういうコンテキストをいかに解決するか、というのが話のキモで、いわばカートにアイテムを追加するロジックは ItemsController の add_to_cart メソッドの外では必要ないし、カートからアイテムを取り除くロジックも CartsController の remove_item の外では必要ない。今は。
将来的にはアイテム画面で『カートにそのアイテムがあった時だけ』はカートからそのアイテムを削除するようなユーザーフレンドリーな機能が搭載されるかもしれないし、カートに複数の商品が乗っているときの挙動などもこの例では未定義だ。今はシンプルに見えるけれど、これは仕様が詰まってくればより複雑で多様なケースで扱われるインタラクションになるだろう。
例えばログイン済みであるとか、例えば特定の URI クエリが来ているだとか、例えば特定の UA からのアクセスであるとか。
そういうもろもろの面倒なものをうまく面倒みてくれる Context を作ってくれる Gem があると、すごく便利なのかなぁ、ついでにモデルに動的に Interaction を extend してくれたりするといいよね。あれ、それって、 Chanko ...
というようなことをぽつぽつ考えています。難しい。無念。