厳密なMVCについて書こうかと思ったが、そもそも厳密なMVCはSmallTalkのMVCで自分はそれを知らない、ということに気がついた。つまり、MVCと名前の付く派生としてはrobotlegsとPureMVCくらいしか知らないので、自分の解釈は間違っているのかもしれない、という不安はある。よって、今回の話はそれらの派生MVCの話として、話半分に読んでほしい。
前回はMediatorがMVCとMCVの明暗を分けるとか何とか。Mediatorについては、MVCの細かい機能分けの話が絡むので、今回の話で。
厳密なMVCの機能分け
MVCは制約をつけること(例えばpublicやprivate)で、誰もがわかりやすくて保守性の高いプログラムを書きましょう、という認識を持っている。これは、つまり、Model層、Controller層、View層に分けるということだ。
MVCをもっと仕分けすると色々出てくる。2位じゃいけないんですか?
・Controller
・Command
・Model
・Proxy
・Service
・Delegate
・VO
・View
・Component, UI
・Mediator
このほかに
・Event
・Facade
あたりがその辺をうろつく。
これらの機能分けについて説明していく。MCVではなくMVC的な説明になるのでよろしく。
それぞれの役割
Component, UI
最近のIDE(統合開発環境)では、GUIもコピペーで簡単に構成することができる。これぞデザイナー向き機能。コピペーで作られた画面というものは、XML系(MXML,XAML)だったり、バイナリ系だったり。基本的には、プログラムコードは混入しない方がデザイナーに壊されないので都合が良い。
多少複雑な部品だと、それ1つでMVCの系を持っていたりする。自身で完結するMVCを持つなんてComponentくらいのもの。小さな宇宙。一見、FlexやC#なんぞに触れると一番お世話になる部分だったりする。それがComponent。
Mediatorさん
インターフェースをまとめる。
Componentにコード書きたくないので、代わりに必要な人。Viewに関わる色々なことをする。Viewで完結する(ControllerとModelが関係ない)ような動作はMediator内に収めた方がいい(ような気がする)。
あとは、Modelの値が変わった場合に監視する役もMediator。どの値を見に行くの?みたいな。Viewが叩かれてControllerにチクりにいくのもMediator。つまり、UI Componentに直接さわらせないぞ、という役の人がMediatorさん。
Commandさん
Controllerさんのお仕事。一連の作業に名前をつけてまとめる。
叩くのは、主にModelさん。Modelさんのインターフェースをどんな風に叩くのか、どんな順番で叩くのかを持つ。
時に大事な仕事は、外部のサービスから取得したデータをModel(メモリ空間、もしくはDB)に格納するとき。Model(Service)でデータを取得したときにイベント箱が届けられるのだが、その箱の中のデータを別のModel(Proxy)に入れたりする簡単なお仕事です。
Modelさんがメタボになると仕事が無くなる。というか、だんだんControllerって自動生成でいいんじゃね?という気分になってくる。でもModelとModelの橋渡しをするときには必要な人。
VOさん
ValueObjectの略。なぜか略されることが多い。
構造体のクラスバージョン。入れ物だけ用意。時々仕事するけれど、VOのメソッドで自身が変化するのはNG。変化したい場合は、分身してください。
Modelさんと、Eventさんの持ち物であるが、時にMediatorさんが開けることもある。
Proxyさん、Serviceさん、Delegateさん
この3つの呼ばれ方をするModelが多い。
Proxyさんは代理人さん。Mediatorさんも代理人さんっぽいけれど、Proxyさんの名前がつくと主にModelの仕事に就くことが多い。この3つの呼び名は、外部のサービスを呼ぶModelの名前。例えばFlickrService.getFlickr(keyword)とかメソッドが存在すると、ちょっとFlickrまで行ってくる…という作業を行う。Flickrからブツを持って帰ってくると、イベント投げてCommandを発令して、仕事は終わる。
失敗すると、Mediatorに「失敗したよ!てへ☆」といって死ぬ。市
外部にクエリを投げないModelさんは、素直にModelさんと呼ぶことが多い。そういうModelさんはVOをたくさん持っている。
Event箱
箱にしたくない箱。夢と希望と絶望が詰まってる。MVCのそれぞれをつなぐ線。
MediatorやModelの中にはEventDispatcherさん(イヴェントディスパッチャ・タイ人か?)という人がいる。この人がEvent箱を川にぶん投げる。
Facadeさん
ModelとControllerとViewの管理者。
EventDispatcherさんがぶん投げたEvent箱を、郵便局勤務10年の手さばきのごとく、パスする。Serviceの例だと、Flickrから取得が成功するとFlickrEvent.成功したよ、が帰ってくるが、それをShowPicturesCommandに投げる。ここで、投げるリストに登録しなくて、動かなくて涙目になることがある。
概観
順番的には、以下の感じ。
ユーザ操作で外部APIを叩く
Mediatorさん→EventDispatcherさん→Facadeさん→Commandさん→Modelさん(ユーザ操作)
(1)ユーザ操作がUIからMediatorに伝わり、MediatorはFacadeに投げる
(2)FacadeはEvent内容を見てCommandに投げる
(3)CommandはModel[Service]を操作する(外部サービスからのデータ取得を依頼する)
外部APIの結果を格納する
Modelさん→EventDispatcherさん→Facadeさん→Commandさん→Modelさん(外部からデータ取得)
(1)Model[Service]が取得した結果をFacadeへ
(2)FacadeはEvent内容に応じて指定のCommandに渡す
(3)CommandはModelを変化させる(取得した結果の格納を依頼)
外部APIの結果を表示する
Modelさん→Mediatorさん(値変更によるView変化)
(1)(結果の格納によって)ModelがMediatorに値が変わったことを教えて
(2)MediatorがModelに値をとりにいく
ちなみにユーザ操作で直接Modelの書き換えもあり。単純なので今回は略。
Mediatorのお仕事
ということで、UIとその他Controller, Modelとの橋渡しを行うのがMediatorなのだが、この仕事はM=C=V形式のCの仕事に該当するような気がしてならない。
今回のフレームワークではCommandは一連の作業を行うデザインパターンであるが、この作業は実はModel内のビジネスロジックに含まれるべきもので、実質はModel間のデータ受け渡しくらいしかControllerはすることがない(ような気がする)。このデータの受け渡しは、Model間の依存関係を気にしなければ、Model組み込みで行ってもかまわない。そうなると、ほとんどContollerはする仕事がない。
ということで、Controllerには他の仕事をさせないで、Controller≒Mediatorという扱いにしたのがMCVなのだろうかなぁという印象がある。
というところまでが、今回のMVCについての話。余力があったら、CoCとMVCの関係について書くかも。