Sep 19, 2012

MVCパターンの適用限界を考える(1)

MVC(Model-View-Controller)パターンは、UIを持つアプリケーションのデザインパターンとして非常に有名であり、特にこれを参考にしたJ2EEやASP.NETを始めとするWebアプリのフレームワークが成功を収めてきたことから、その価値は誰もが認める所である。
しかし、これをローカルシステムのGUIアプリケーションの設計に適用しようとすると、妙に難しいと感じた人が少なくないのではないだろうか。

MVCパターンは、元々Smalltalk-80の開発において考案され実装されたものらしいが、MVCの考案者によると、


MVC was created as an obvious solution to the general problem of giving users control over their information as seen from multiple perspectives.
("The original MVC reports"より)すなわち、複数の視点で表現されたユーザー情報を制御することを可能にする、という一般的な問題に対する自明な解として考案したものとのことであり、Smalltalk専用に考案されたものではなく、ネットワークシステムの為に考案されたものでもない。実際、MVCの実績はSmalltalk以外の言語で上がっており、MVCのアイデアに通信ネットワークの存在を仮定するようなものは見当たらない。であればどんなGUIアプリケーションでも有用なはずだ、と推測するのは全く自然なことである。

筆者も、当然MVCはローカルシステムでも有効なはずだと10年前から信じており、MVCの適用がうまく行かないのはMVCの理解が間違っているからだ、と思ってきた。しかし、この10年間でたぶん4回くらい、仕事でMVCを取り入れようとしたソフトウェア開発のプロジェクトの様子を知る機会があったが、いずれもほとんど成果が上がっていないようだった。見た感じ、MVCの理解が間違っているような気がすることも多かったが、それにしてもそんなに効果が出ないものだろうか。
実は筆者も、プライベートで何回か、MVCパターンを意識してプログラムを作ってみたことがあるが、MVCの価値を感じたことは一度も無かった。そういえば、MVCパターンの利点というのは、根拠のあるもの、具体的で検証可能なものはほとんど聞いた覚えが無い。オブジェクト指向設計と同様、経験的にやりやすかったから、現実にうまく行ってるから、という理由で推奨されているような気がする。それなら、大規模システムに有効なオブジェクト指向設計がミッションクリティカルなシステムに適さないのと同様に、MVCパターンにも苦手な分野があるのではなかろうか。
…ということを最近になってやっと考え始めたので、調べたことや考えたことを少しずつここに書いてみることにした。

MVCを知っていれば、既存のMVCを応用したフレームワーク(アプリケーションの枠組み及びアプリケーションの開発を支援する環境)が使える、というのは現実的なMVCを知るメリットではあるが、そういったフレームワークを使わない場合、MVCパターンをアプリケーションの設計に取り入れるメリットは何だろうか。

まず、筆者がずっと、きっとあると信じてきた、MVCパターンの利点を挙げる。

  1. Modelが再利用可能なので、ViewやControllerが交換可能で、容易に追加できる
  2. システム分割方針が分かりやすくなり、担当者毎、モジュール毎の役割分担が明確になる
  3. ソフトウェア構造としてM,V,Cが分離しやすく、従って独立して設計しやすい
  4. M,V,Cそれぞれのプラットフォーム(実行環境)やコンポーネント(共通モジュール)を別々に設計することも容易である

しかし、実際にはそうはならないことも多い。

(1)については、UIが複雑に、またビジュアル(グラフィカル)で応答性を高めるほど、VはMに限らずCの状態も表示するためにCに依存するようになり、特にポインティングデバイスやタッチバネルの処理で顕著なように、ユーザー入力が表示状態に依存してCがVに依存するようになるため、VとCの結合が強くなり、VやCが単独で交換可能にならなくなる。V+Cのセットでなら交換可能な構造が保てても、そうなると既にV+Cの規模が巨大になっているので、もう1つ別のV+Cを作る労力が、もう1つアプリ全体を作るのと大して変わらないことになってしまう。

(2)については、上述のようにUIが高度になるほどV-Cの関係が密接になって境界がわかりにくくなる他に、元々M-Cの境界がはっきりしないという問題がある。
あるモデル(ユーザーデータとその操作手段)を制御(操作)するアプリケーションは多岐に渡り、極端に言うと無限のバリエーションがあり得るんだから、アプリケーション固有のロジックはCに置くべきだろうという考え方もあれば、有名な"Skinny Controller, Fat Model"のスローガンに代表されるように、ロジックはできるだけModelに置くべきだ、という考え方もあり、システムに機能追加する時にあるロジックをMに入れるべきかCに入れるべきかは、人によって判断が分かれるのである。

(3)は、例えばModelを含めてシステムに機能追加する場合、Modelに追加するI/FはViewを意識して設計せざるを得ないことは普通に起こる。何も考えずにModel内のあらゆるデータを参照可能にする為にI/Fを揃えようとすると開発量が多くなることもあるし、複雑な変換や抽出を必要とする巨大なデータをそのまま渡されるとViewの処理が大変になるので、ある程度ユーザーにとって意味のあるまとまりにして渡してくれ、と言われることもある。
VとCが独立に設計できなくなりがちであるのは上述の通りである。

(4)は、実際にJ2EEではModelのコンポーネントとしてJava Beans(EJB)、ViewのプラットフォームとしてJSP technology、ControllerのプラットフォームとしてServlet technologyがあると説明されることがあり(参考リンク:[@IT 1] [@IT 2] ["Multitiered Applications" in Java EE tutorial])、M/V/C別々にプラットフォームを構築しやすいように見えるが、よく見ると、EJB以外は汎用的すぎて、M,V,Cそれぞれに特化したプラットフォームとは言い難い。Java BeansはVでもCでも使われる仕組みであるし、JSPはMだけでなくCにもアクセスできるし、作ろうと思えばJava ServletだけでMもVもCも作れる。M,V,Cそれぞれのプラットフォームとしても向いている、用途が広いテクノロジーを使っているのである。
むしろ、M/V/Cそれぞれのプラットフォームを作ろうとすると、そこまで汎用的で高度に洗練されたものを作ることになるのだろうか、という疑念すら抱かせる。

大体、一般にソフトウェアのデザインパターンの価値は、設計のノウハウであることよりもむしろ、設計者間の共通言語として使われることにあるのである。大概のパターンは、それを知らなければそういう構造にならないような、思い付きにくいアイデアではない。また、シンプルで普遍的にまとめられているものが多いので、その構造をにすると直ちに多くのノウハウが取り込める訳でもない。デザインパターンのノウハウの本質はその構造にした理由にあるのである。ある設計の基本構造とその構造にする理由とを合わせて一言で伝えるためにデザインパターンはあるのである。理由はおろか、パターンの構造自体も設計者間に共通認識が無くて伝わらなければ、デザインパターンとしての価値が無い、印籠やブランドの類でしかないのである。

さらに考察を進める前に、MVCパターンをおさらいする。
上記MVCの考案者"MODELS-VIEWS-CONTROLLERS"によるModel, View, Controllerの定義は、次のようなものである。


Model
実世界における問題を、特定の視点で抜き出したものを表現するもの。言い換えると、実際の問題や事象をモデル(模式、模型)化するもの。("Models represent knowledge."の"knowledge"は問題や事象に関する知識のこと。)

View
Modelの視覚的な表現。1つのViewはModelに取り付けられ、Modelに対して問い合わせをすることにより必要なデータを取得する。Viewはそれが取り付けられるModelのことを良く知っており、Modelへの問い合わせは全てそのModelで使われる言葉を用いてされる。 ("It may also update the model by sending appropriate messages."についてはややこしくなるのでとりあえず保留。)

Controller
ユーザーとシステムとを繋ぐもの。画面上にそれとわかるように表示することにより、ユーザーに入力手段を提供する。また、ユーザーによって入力されたコマンドをメニュー等によって表示するためのメッセージをViewに送信する手段を提供する。
ControllerはViewを補完せず、Viewの表示に介入しない。同様に、Viewはマウス操作やキーなどのユーザー入力そのものには関知しない。

次に、MVCパターンの最もシンプルな構成を、UMLで表現してみる。
Class diagram of MVC without V-C connection
図1-1: 最もシンプルなMVCのクラス図(静的構造図)

Communication diagram of MVC without V-C connection
図1-2: 最もシンプルなMVCのコミュニケーション図(動的構造図)

上記の"MODELS-VIEWS-CONTROLLERS"の定義にはViewからModel、ControllerからViewへの関連が含まれているが、それらは必須の構成要件ではない(その関連におけるメッセージのやり取りが無くてもMVCパターンは動作する)ので、最もシンプルな構成ではそれらを省いている。

ポイントは、次のように集約される。

  • 1つのModelに複数のViewを動的に登録することができる
  • ModelはViewの存在を知っているが、Viewの具体的な実装を知る必要が無い
  • 1つのModelを複数のControllerから操作することができる
  • ViewとControllerは完全に独立している

なお、1つのViewが複数のModelに関連する、つまり複数のModelの表示を受け持つことも可能だとされることが多い(上記MVCの考案者による"THING-MODEL-VIEW-EDITOR"でも"each View being capable of showing one or more pictorial representations of the Model"という記述がある)ので、M-V, M-Cの多重度は1対多でなく多対多が正しい、と思われるかも知れないが、Modelを交換可能とすることはMVCの本質ではないことと、そのようなViewは役割をModelの数だけ分割し、その数だけMVCのセットがあるのと同じことと、一般にオブジェクト指向設計において多重度が多対多の関連は意味が曖昧であることを理由として、M-V, M-Cの多重度は1対多と書いている。
(続く)

See more ...

Posted at 21:48 in PC一般 | WriteBacks (0)
WriteBacks

Sep 01, 2012

将棋の棋譜再生iアプリを作ってみた

昨年はまあまあ満足できた将棋大会に、今年も参加したら、全く思い通りに指せなかった。
将棋では、相手に押さえ込まれて何もできなくなるというのはよくあることだが、そういう感じではなく、筆者の指し手に相当な自由度、選択肢があったのに、さっぱり頭が回らなかったのである。
何も思い付かないまま、何もできないまま、持ち時間が無くなって、2敗して予選落ちしてしまった。大会規程により、今年はA級で参加せざるを得なかったのだが、あの調子だとB級でも散々だっただろう。
そんなことあり、もうちょっと将棋を勉強しようという気になった。

図書館から定跡本を借りて時々読んでいると、ちょっと気が向いた時に見れないことが多いことに気付いた。筆者は割と外出先にでも本を持ち歩く習慣があるのだが、確実な待ち時間が予想できないと持ち歩かないようであるのと、本は携帯電話と違って片手では開けないことが要因としてあるようである。
それでなくても、携帯電話でアプリを動かしていると、将棋盤を再現できるアプリがあればいいのにな、と思うのは自然なことであろう。

筆者が持っている携帯電話は、昨年の将棋大会の日に買った、ドコモのP-01Cである。iモードアプリしか動かない「ガラパゴス携帯」である。スマホは保有していない。
これで動く棋譜再生アプリが見つかれば良かったのだが、毎月費用が105円とか315円とかかかるものを除くと、適当なアプリが見つからなかった。1つ、棋譜管理に特化した、丁度いいアプリがあった(今はもう見つからない)のだが、大抵のiモード機種に対応してるのに、なぜかP-01Cは対応しておらず、ダウンロードもできなかった。

それに対して、スマホ用の棋譜管理ができる将棋アプリはごろごろ転がっているようである。この機会にスマホを購入しようかと思ったが、それだけの為にスマホを買うのはどうかと思った。

棋譜再生アプリを自分で作ろうか、と、ちょっと思い始めた。しかし、筆者はiアプリの作り方をほとんど覚えていなかった。というより、5年ほど前に簡単なものを1回か2回作って実機で動かすのを試しただけなので、覚えたことがある程でもない。もしやるとすれば、アプリの一挙手一投足に至るまで、DoJaのAPI仕様書を検索しまくることになる。

今や世界シェアの50%以上がスマホというこのご時世に、今更DoJaアプリの開発に挑戦すべきだろうか。今から覚えるならAndroidかiPhoneのアプリの作り方であろう。この機会にスマホを1台買おう、とも思ったのだが、スマホを買うと、上述の通り、自分で棋譜再生アプリを作る必要性が無くなってしまう。

それに、スマホを買うと、きっともうP-01Cを使わなくなってしまうだろう。Javaに思い入れがある者としては、このまま自作のJavaアプリを1つも作らずにP-01Cを使い終わることは、ケーキを半分残して腐らせてしまうくらいに勿体ないことなのである。そうなれば、将来必ず後悔するであろう。その前に、このままでは必ず、廃棄する直前に、供養の為にもiアプリを1つは作って動かさなければならないという強迫観念に襲われるに違いない。もはやあと1回iアプリを作ることは筆者の宿命なのである。

・スクリーンショット
screen shot
※この画面はiDKDoJaのエミュレーターで作成したもので、実機の画面とは異なる。
 実際には、盤面の駒も含めて、文字は機種毎のシステムフォントが使用される。
i-mode用ダウンロードページへのリンク
・ボタン操作
 1-9: 1手進める
 *: 1手戻す
 #: 次の分岐点まで進める、または前の分岐点まで戻す
 0: 初期状態に戻す
・ソースコード(iDKDoJaプロジェクトのsrc/に配置)
 iKifuPlayer.java
 Board.java
 KifTree.java
・作成者
 maruinen(筆者のネット将棋でのハンドル)
・棋譜データの例(iDKDoJaプロジェクトのres/に配置)
 Kifs.txt
 空行は1つの棋譜の終わりとして扱われる。ファイル名は固定。
・棋譜データの入れ替え方法
 iDKDoJaと上のソースコードを使って、アプリ自体を作り直すしか無い。

See more ...

Posted at 22:31 in Java | WriteBacks (0)
WriteBacks