MOVEとはどのようにして生まれた子なのか? MVCとMOVEの違い

  • 関連記事

MVCがそもそもわからないという方はまずこちらをどうぞ
プログラマーが意識するべきUI設計指針 3つのMVCモデル - GeekなNooblog
http://d.hatena.ne.jp/sona-zip/20110817/p1

  • 本題

下記の翻訳記事により、MVCに変わる?MOVEという概念が登場しています。

[翻訳]MVCは死んだ。MOVEするときがきた - きしだのはてな
http://d.hatena.ne.jp/nowokay/20120704

またそれに対する反対意見も盛り上がっています。

MOVEは望まれなかった子 - the sea of fertility
http://ugaya40.net/architecture/dis_mov.html

反対意見は納得なのですが、何かしっくりきません・・・
何がしっくりこないのかと思ったら、反対意見にしっくりこないのではなくそもそもMOVEがなんなのかよくわからないのです。


ということで改めてMOVEとはMVCと比べて何が違うのか?どういう経緯で生まれものなのか?ということを勝手に考察してみました。

MVCとMOVEの違い その1 イベントが違う?

まず名称の違いからCがなくなりOとEが増えていることがわかります。


このような点から、ネット上ではMVCのCをOとEに分割したものがMOVEだ」という意見が見かけれます。
本当でしょうか?


まず翻訳記事のE(イベント)の説明を見てましょう。

イベント

「loginAttempt」イベントはユーザーが「ログイン」ボタンを押したときにビューから発せられる。加えて、ログインオペレーションが完了したときに、「currentUser」モデルはそれが変更されたことをアプリケーションに伝えるイベントを発する。

イベントの受けつけは、IoC、制御の逆転をMOVEに与え、モデルに直接どのビューを更新するか気づかせることなしに、そのモデルにビューの更新を可能にする。これは、強力な抽象化技術で、互いに妨げることなくコンポーネントを結び合わせる。

MVCのイベントと違いはないように読めてしまいます。


おかしいなぁと思いMOVEの原文を読んでみると・・・

Events

The "loginAttempt" event is emitted by the view when the user clicks login. Additionally, when the login operation completes, the "currentUser" model will emit an event to notify your application that it has changed.
Listening on events is what gives MOVE (and MVC) the inversion of control that you need to allow models to update views without the models being directly aware of which views they are updating. This is a powerful abstraction technique, allowing components to be coupled together without interfering with each other.

MVC is dead, it's time to MOVE on.


なんと!イベントはMOVEもMVC違いはないようです。
※現在は翻訳先では修正いただいています。

MOVEをMVCと同様に表記するのならMOVが正しいということになりますね。
きっと語呂がいいからEventも付け足してしまったんだろうなぁ・・・


では、MVCとMOVEの違いはなんでしょうか?

MVCとMOVEの違い その2 ControllerとOperationの違い

まずは図で確認してみましょう。

  • MOVE

  • Operationを上に持ってきたMOVE(自分の解釈追加)



MVCとMOVEの違いは、C(Controller)がO(Operation)に変更されたことだけだとわかります。


ではCとOは何が違うのでしょうか?


呼び出し関係

これは寸分違わず同じです。
図の矢印の関係性を見てみましょう。
イベントと実行の関係がまったく同一であることを確認できます。

役割

これは大きく違います。

ViewからOperationにイベントが飛んでいるということは、イベントハンドリングをOperationで行うことはMVCのControllerと同様です。
しかしMOVEでは更にOperationでアプリケーションの責務も負うと説明されています。
具体的にはパスワードが正しいかどうかのチェックを実装するようです。

アプリケーション間で共通のオペレーションといえば、ユーザーのログインである。これは実際は二つのサブオペレーションを組み合わせたものだ。最初の1つはユーザーからメールアドレスとパスワードを得る。2番目は「ユーザー」モデルをデータベースから読み込んで、パスワードが正しいかチェックする。

イベントハンドリングはプレゼンテーションに関する振る舞いであり、アプリケーションの責務はドメインに関する振る舞いです。
このようにOperationではPDSに違反してしまっています。



以下Javaでそれっぽいコードを書いてみました。

  • MOVE実装例

パスワードチェックをOperationに実装した場合

public class Operation implements ActionListener {
	private View view;
	private Model model;

	public Operation(View view, Model model) {
		this.view = view;
		this.model = model;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		JButton pushedButton = (JButton) e.getSource();
		// 押されたボタンがログインボタンだったらログイン処理
		if (view.isLoginButtonn(pushedButton) == true) {
			// パスワードのチェック
			/* 引用 最初の1つはユーザーからメールアドレスとパスワードを得る。 */
			if (checkAccount(view.getId(), view.getPassword()) == true) {
				// 正しい場合ウィンドウを閉じる
				view.close();
			} else {
				// 間違っている場合再入力を求める
				view.setMessage("何か間違ってるから再入力してね");
			}
		}

	}

	public boolean checkAccount(String id, String password) {
		// 2番目は「ユーザー」モデルをデータベースから読み込んで
		for (User user : model.getUsers()) {
			// パスワードが正しいかチェックする。
			if (user.check(id, password) == true)
				return true;
		}
		return false;
	}
}


以下がMOVEではすべてOperationの役割のようですが、MVCでは黒太字の部分までがControllerの役割であり、赤文字のパスワードが正しいかチェックするのはModelの役割です。

アプリケーション間で共通のオペレーションといえば、ユーザーのログインである。これは実際は二つのサブオペレーションを組み合わせたものだ。最初の1つはユーザーからメールアドレスとパスワードを得る。2番目は「ユーザー」モデルをデータベースから読み込んでパスワードが正しいかチェックする。

public class Controller implements ActionListener {
	private View view;
	private Model model;

	public Controller(View view, Model model) {
		this.view = view;
		this.model = model;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		JButton pushedButton = (JButton) e.getSource();
		// 押されたボタンがログインボタンだったらログイン処理
		if (view.isLoginButtonn(pushedButton) == true) {
			// パスワードのチェック 実装はModelにある
			if (model.checkAccount(view.getId(), view.getPassword()) == true) {
				// 正しい場合ウィンドウを閉じる
				view.close();
			} else {
				// 間違っている場合再入力を求める
				view.setMessage("何か間違ってるから再入力してね");
			}
		}
	}
}

PDS違反を犯してしまうと何が困るのでしょうか?


MOVEのコード例ではパスワードチェックなどがOperationで実装しています。
これではイベントハンドリングとパスワードチェックという機能がOperationで結びついてしまっているために、パスワードチェック処理を再利用したいと思ったときとても不便です。


MOVE提案者は何故このようなことをしたのでしょうか?それは以下の文から推測することができます。

MVCはすばらしいアイデアだ。モデルを持ち、モデルは内部に少しの状態をもつ。ビューは内部に少しのUIをもつ。そして、コントローラは内部に少しの・・・

何を持つ?

このようにMOVE提案者はControllerの役割がないと考えたため、それならControllerの名前をOperationに変えて役割を与えよう!と考えたのではないでしょうか


しかしそもそも「Controllerの役割がない」ということがMVCを誤解してしまっています。
上記のControllerのコードのようにしっかりとプレゼンテーションにおける振る舞いとして、イベントハンドリングや複数の画面に跨がる処理を行うという明確な役割を担っています。

まとめ

では改めて批判記事を見て見ましょう。


まさにこの通りでした。

このMOVEが前提としているMVCにはPDSの視点が欠けすぎです。そして代替提案であるMOVEは、PDSを意識しないでMVC的な実装をほじくり返した結果にしか見えません。

MOVEには、PDSに違反したとしても従来の概念にとらわれない、より良いメリットがあるのかもしれません。が私には今のところ見つけることができていません。
もしくは私がOperationの捉え方を間違っているのかもしれませんので、MOVEのメリットを把握できた方はコメントにてお知らせください。


次回は何故MVCはこのような誤解をされてしまうことが多いのかを考察していきたいと思います。