@ledsun blog

Hのキーがhellで、Sのキーがslaveだ、と彼は思った。そしてYのキーがyouだ。

えぇー!MVCのContollerはプレゼンテーションロジックのinput担当だったのかい!?

この話はMVC(Model-View-Controller)の話です。 特にクライアントMVCの話です。WebMVCの話ではありません。

事前

ViewとModelを分けるためにControllerを挟むのだと思っていました。

事後

Contollerはプレゼンテーションロジックのinput担当でした。

参考文献

The Model-View-Controller (MVC) Its Past and Present を読んでください。すべてが書いてあります。

本題

WebMVCから考えた俺のコントローラー

そんなことより聞いてくださいよ。 WebMVCからMVCに入った口としてはViewとControllerの分け方なんて考えたこともないんですよ。 分かれてて当たり前ジャンと思ってたんですよ。

ところがJavaScriptで3000行くらいあるDOMをゴリゴリするアプリケーションをいじってたんですよ。 やっぱりプレゼンテーションロジックとビジネスロジックは分けたいじゃないですか。 それが何かはよく分からないですけど、名前的に格好いいじゃないですか。

ここでは仮に

  • プレゼンテーションロジック:DOMをゴリゴリするもの
  • ビジネスロジック:データをゴリゴリするもの

とします。

ユーザーが画面を操作したら、データを修正してDOMに反映するためにプレゼンテーションロジック呼びたいじゃないですか。 プレゼンテーションロジックとビジネスロジックを分けるものがコントローラーだと思うじゃないですか。

ははぁ、さてはオブザーバーパターンを使って、プレゼンテーションがコントローラを監視するようにして

ビジネスロジック =メソッド呼び出し=> コントローラー =イベント通知=> プレゼンテーションロジック

って、やったらクソかっこよくねえ?って思うじゃないですか。

原始MVCのコントローラー

やっぱり格好良さには歴史的裏づけによるブランド価値が必要じゃないですか。 そこでMVCを調べるわけですよ。 MVCはTrygve Reenskaugて、ノルウェイのコンピュータ科学者の人がXEROXのパロアルト研究所に居た時にまとめたっていうじゃないですか。 2003年に本人がMVCについて説明した文献があるじゃないですか*1

もちろん読むじゃないですか。 MVCが必要な背景とかMVCの説明とかパターン形式で書いてあるじゃないですか。 ざっくり書くとこんな感じなんですよ。*2

ヒント:大事なのは7

  1. 1つのアプリで全業務に対応するのは無理だからアプリケーションを分けましょう
  2. 部門ごとに必要な機能が違うのでコンポーネントに分けましょう
  3. ユーザに分かるメンタルモデルを作りましょう
  4. ユーザ毎に必要十分な機能を提供したらパフォーマンス最強
  5. ドメインユーザマトリックスを使ってユーザの必要な機能を絞り込みましょう
  6. ユーザごとにアプリケーション全部作り直してたら大変、エディタ(プレゼンテーションとユーザ操作)と(メンタル)モデルを分けましょう
  7. エディタのインプットとアプトプットのロジックは大抵無関係だから(コントローラーとビューに)分けましょう
  8. 複数のビューを組み合わせてタスク毎のツールを作りましょう
  9. ユーザにあわせて多層的にビューを組みあわせましょう(原始MVC
  10. ビュー間の通信はツール経由でやりましょう
  11. モデルからビューに変更を通知しましょう

「エディタのインプットとアプトプットのロジックは大抵無関係だから(コントローラーとビューに)分けましょう」 だと!?

冒頭ような誤解をしてたわけですから、あまりの衝撃にのげぞり過ぎて座っていた椅子ごと300mぐらい後退して窓から飛び出してしまったわけです。

だって、原始MVCでは先にプレゼンテーションロジックとビジネスロジックが分かれているわけですよ。 それに加えてプレゼンテーションロジックを二つに

  • ユーザー操作のインプットを担当するのがコントローラー
  • プレゼンテーションの更新を担当するのがビュー

に分けなさいって、

f:id:ledsun:20131120180345p:plain

しかも理由が「分けやすいから」。

JavaScriptで言ったら、DOMのイベントハンドラとそのバインドですよ。

$("body").on("click", ".doneButton", funciton(e){model.doneTask(e.target.id);});

コントローラーって↑のことだったんです!*3 いやー、びっくりしましたねー、感動です。

落ち

単に11で出てくる二番目のオブザーバーパターンと混同していただけの話です。

*1:冒頭の参考文献です

*2:ものすごいざっくりなので間違っていても知りません。なんかおかしいなと思ったら原文を読んでくさい。それで何か分かったら教えてください。

*3:jQueryを使っています。