質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

2715閲覧

クライアントサイド(or GUI)のMVCについて

退会済みユーザー

退会済みユーザー

総合スコア0

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2016/03/11 12:27

###前置き
javascriptのクライアントサイドアプリケーションをMVCで設計する時についての質問です。
※jsに限らずGUI系であれば共通することだと思ったので、iosとandroidのタグ付けをしました。

MVCに関する説明を一部読むと、UIへのイベントをどのように処理するかを判断するのは
ビューではなくコントローラーであると書いてありました。

これに関してビューに該当するクラスを実装する際に指針が分からず、
最近、混乱しております!

以下、疑問点です。

イベントが発生したビューに関する処理も一度、コントローラーに委譲する必要があるのか?

例えば、ヘッダーナビゲーションのUIを管理するビュークラスがあるとします。
このヘッダーナビゲーションはヘッダー内のメニューにマウスオーバーすると、
サブメニューがプルダウンのように表示される仕様であるとします。

このような場合、このヘッダーナビゲーションを管理するビュークラスで、
マウスオーバーのイベントを探知した時、サブメニューを表示させる処理を
コントローラーに委譲せずにそのまま行なってはいけないのでしょうか?

イメージとしては以下のようなものです。
※コードはtypescriptもどきです。(記述に間違ってる可能性有り)

typescript

1class HeaderView { 2 3 constructor(public $navigationLinks: jquery) {} 4 5 this.$navigationLinks.on("mouseenter", this.showSubMenu); 6 7 showSubMenu(event: Event) { 8 9 //サブメニューを表示させる処理 10 11 } 12 13}

それとも、以下のようにそのビューに関する処理でさえも、コントローラーにイベント処理の判断を一旦振るべきなのでしょうか?

class HeaderView { constructor(public $navigationLinks: jquery) {} this.$navigationLinks.on("mouseenter", () => { //コントローラーへマウスオーバーイベントの発生を通知 } showSubMenu(event: Event) { //サブメニューを表示させる処理(コントローラー側から実行される) } } class someController { //マウスオーバーのイベント通知を受け取り、 //HeaderViewのshowSubMenuを実行 }

後者の例のように該当ビュークラス自身に関する処理を
わざわざ一度、コントローラーにイベントが発生した時に委譲するのは
二度手間に感じてしまうのですが、どうすれば良いのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

UIへのイベントをどのように処理するかを判断するのはビューではなくコントローラーであると書いてありました。

モデルの操作をどのように処理するのかを判断するのがコントローラーです。

また、ユーザーインターフェース = ビュー + コントローラーです。
WWWブラウザの場合、ビューとコントローラーはあまり分離していないと思います。つまりMVCに対応しているとは言えません。

投稿2016/03/11 16:45

Stripe

総合スコア2183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/03/14 06:48

回答ありがとうございます!ネット接続出来ない環境にいたため頂いていた回答への返答が遅くなりまして申し訳ございませんでした! UI = view + controllerという風に認識していなかったので参考になりました! WWWブラウザの場合というのは、画面遷移毎にHTTPリクエストが発生するようなサイトやアプリケーションのことを指されていますでしょうか?その場合でしたら、今回の質問に限ってはクライアントサイドMV*の話となるので、初回アクセス時以外はHTTPリクエストは発生しないようなSPA(or SPAに近い)ものをイメージして頂ればと思います。
Stripe

2016/03/14 11:03

そもそもMVCにおいて、Viewではイベントが発生しません。 ユーザーからのイベントを最初に受けるのは、Controllerです。 ただし、Controllerでイベントを処理した結果、Viewに処理が流れることはあります。 WWWブラウザのJavaScriptな環境では、ユーザーからのイベントを集中的に独占的に処理することが難しいため、MVCを適用できません。 代わりに、Document-Viewパターンを採用してはどうでしょうか?
退会済みユーザー

退会済みユーザー

2016/03/16 09:55 編集

引き続き回答ありがとうございます! お付き合い頂いてありがとうございます! 「そもそもMVCにおいて、Viewではイベントが発生しません。ユーザーからのイベントを最初に受けるのは、Controllerです。」 ユーザーからの入力をコントローラーが受け付けるという表現は確かに見たことが何度かあるのですが、これが個人的によく理解出来ておりません。 例えばiosフレームワークで考えてみると、UIViewController内でインスタンス化したUIButtonにクリックがあると、UIButtonの祖先クラスで実装されているtochesbeganでイベントを検知し、それをターゲットアクションパターンでUIViewControllerにイベント処理を委譲していると思います。 これを踏まえるとイベントを最初に受け取っているのはUIButtonで、そこで発火して伝播されたものを受けとっているのがUIViewControllerだと思います。 イベントを最初に探知し発火してるのはUIButtonなので、UIButtonは自分の中ではviewのパーツの一つという認識なのですが、これはコントローラーであるという認識が正しいのでしょうか?
Stripe

2016/03/14 14:07

iOSのUIKitの場合、最初にイベントを受け取るのはUIApplicationです。 UIApplicationはコントローラーです。 UIApplicationはそれをsendEvent:でUIWindowに送ります。 UIWindowはそれをsendEvent:でUIResponder(UIButton)に送ります。 UIButtonが最初にイベントを受け取ってる訳ではありません。
退会済みユーザー

退会済みユーザー

2016/03/16 10:24 編集

ご回答ありがとうございます。そのような流れになっているとは知りませんでした!自分でもUIApplication周りのことを調べてみたのですが、イベント発生からの流れとしては以下のような流れであることを確認致しました。 □引用元:イベント処理ガイド(apple公式) "ユーザの操作によってイベントが発生すると、UIKitはその処理に必要な情報を集約したイベントオブジェクトを生成し、アクティブなアプリケーションのイベントキューに入れます。 タッチイベントの場合、このオブジェクトは、一連のタッチをUIEventオブジェクトにパッケージ化したものです。 モーションイベントの場合は、使っているフレームワークやモーションの型によって異なります。イベントは所定の経路に沿って順次伝播し、これを処理できるオブジェクトに到達します。まず、シングルトンであるUIApplicationオブジェクトが、キューの先頭からイベントを取り出し、これを処理するオブジェクトにディスパッチします。 通常はアプリケーションの中心となるウインドウオブジェクトに送信し、これがさらに、最初に当該イベントを処理するオブジェクトに渡します。" -- 引用ここまで -- また、他のブログでは以下のように説明がありました。 □引用元:http://glassonion.hatenablog.com/entry/20120405/1333611664 "iOS ではアプリを起動してから終了するまで UIApplication オブジェクトがイベントやアプリの状態を管理しています。iOS はイベントが発生するとイベントキューと呼ばれるキューにイベントを溜めていきます。そこに溜まったイベントをイベントループが順番に取り出し UIApplication オブジェクトがイベントメソッドの通知を行います。" -- 引用ここまで -- 流れとしてはiosがイベントを探知しそれをイベントキューに入れて、そのキューの先頭からUIApplicationがイベントを取り出してウィンドウオブジェクトに送信するようですね。 ただ、そもそもUIApplication以前に最初にイベントを探知するのはiosやUIKitと書かれているようでしたが、それらの具体的にどこなんだろうと疑問に思いました。 ただ、少なくともビューではないのだなと感じました。 というのも、イベントキューに追加されるイベントというのはビューが関係するタッチイベントだけではなく、電話がかかってきたとか、メモリが不足したとか、ビューに関係のないイベントもどうやら含まれているみたいだからです。 であれば、確かにビューがイベントを最初に受け取っている場所でないということは納得が行きます。 MVCというのは開発者がコードをかける範囲内での設計概念であると思っていたのですが、開発者がタッチできないようなos部分も含まれるものなのですね。 これらを踏まえると、以下のような解釈で概ね間違ってはいなそうでしょうか? □まとめ ・イベントという言葉にはタップやクリックなどのビューに対するイベントに限らず、電話がかかってきた、メモリが不足したというイベントも含まれている。 ・MVCのCは開発者が触れることが出来ない範囲のものも含まれている。 ・画面上の音量ボリュームを操作するというユーザーアクションがあったからといって、タッチイベントがビューで最初に発生したとそのまま捉えるべきではない。視覚的にはビューで最初にイベントが発生しているが、内部で最初にイベントを探知しているのはビューではない。
Stripe

2016/03/16 11:23

MVCパターンの適用範囲はアプリケーションです。OSは含まれません。 アプリケーション内でUIApplicationよりも先にイベントを感知する部分はありません。
退会済みユーザー

退会済みユーザー

2016/03/16 12:27

なるほど!アプリケーションの範囲で一番最初にイベントを受け取っているのがコントローラーに当たるUIApplicationなのですね。 納得が行きました!ありがとうございます! これを踏まえてウェブのGUIアプリの場合を再考してみたいと思います。 本当にありがとうございました!
guest

0

ベストアンサー

ビューで検知したマウスやキーボードのイベントが、モデル(データ)に何の影響も与えないのであれば、ビューの内部だけで処理する。(例えば、ある領域にmouse_overした時に背景色をyellowにしてデータ表示を太文字にする、ただしこれは表示の変化だけでありデータそのものには何の変更も生じない、というような場合)

逆に、マウスやキーボードイベントがデータそのものに影響する場合は、コントローラーを経由してモデルのプロパティ操作等を行う。(例えば、チェックボックスのON/OFFが、データのあるプロパティのTrue/Falseに直結している場合等)

いくらか例外はあるかもしれませんが、おおむねこのような方針でうまく設計できるのではないでしょうか。

投稿2016/03/11 15:37

tkanda

総合スコア2425

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/03/14 06:43

回答ありがとうございます!ネット接続出来ない環境にいたため返答が遅くなってしまい申し訳ございませんでした! 頂いた回答に納得です。加えて言うならば、例えばヘッダービュークラスの管理下にあるDOMでイベントを探知した場合で、かつ、そのイベントに関連する処理が他の例えばフッタービュークラスにまたがるような場合なら、一度、コントローラーにイベント処理の判断を委譲した方が良いのですか?ビュークラスが他のビュークラスのメソッドを実行するというのはどうでしょう?
tkanda

2016/03/14 07:42

MVCデザインパターンの原則として、モデル(データ)はビューの実装を知らない(知るべきでない)という話はご存知だと思います。これと同じように、ビューはほかのビューの実装を知らない(知るべきでない)ということもよく言われることです。 そのように考えると、一般論ではビューから他のビューのビジュアルを直接変更したり、あるいはビューが他のビューの要素をダイレクトに参照してデータを取り出すのは避けるべきだと思います。 つまり、ご質問にあるシナリオでしたら、ヘッダー系とフッター系に実装を分離するほうがベターだと思います。 ヘッダーコントローラーとフッターコントローラー間のコードが強く結合されるのを避けるため、ヘッダーコントローラーからフッターコントローラーの処理を明示的に呼び出すのではなく、ヘッダーコントローラー側にイベントを実装し、フッターコントローラーはそのイベントを受信することでコントローラー間での連携を図るような設計が望ましいのではないでしょうか。 AngularJSやKnockout.jsのようなフレームワークを使うと、このようなMVC的な設計をとても簡潔に実装することができます。
退会済みユーザー

退会済みユーザー

2016/03/14 08:35

ご返答ありがとうございます! 「ビューはほかのビューの実装を知らない」というのは初耳でした。というのもMVCに関するいろんな説明を読んでも、「ビューは他のビューのことを知っている」とも書かれていないし「ビューは他のビューのことを知らない」とも明示的に書かれていなかったからです。なんとなく他の管理下にないビューを直接、ビュー自身が操作するのは変かなとは感覚的には分かっていたのですが、ビューからビューの直接的な操作はNGという認識で良かったのですね!必要であればオブザーバーパターンやPub/Subパターンで対応ということですかね。 「ヘッダーコントローラーとフッターコントローラー間の・・・」というところなのですが、これを「ヘッダービューとフッタービュー間」と書かなかったのには何か意味があるのでしょうか? 自分が一番クライアントサイドMVCでモヤモヤしているところが、「コントローラーは何をするのか?」、「ビューは何をするのか?」、「これらふたつは別クラスとして分けられるものなのか?」という点です。サーバーサイドMVCの場合はビューはHTML+αみたいな感じですし、また、明確にコントローラーとも分離されているので分かりやすいです。 ですが、クライアントサイドMVCの場合、フレームワークのコードや、ウェブ上のブロガーが書いたコードを見ると、表示に関する処理もコントローラーのようなクラスに書かれていたり、逆にそうでなかったりすることもあって、ビューとコントローラーの役割や区切りがイマイチよくわからず混乱してしまいます。 オライリーの「javascriptデザインパターン」の3章がjsのmv*パターンに関する章で、基本的なmvcの話や主要なフレームワークの簡単な紹介があるのですが、ここを見るだけでも混乱するばかりで自分の疑問がクリアになることがなく、設計の方向性に関して行き詰まってしまっています。
tkanda

2016/03/14 09:51 編集

ビューとコントローラーの境界線についてお悩みなのかもしれませんね。 WindowsのWPFやSilverlight(XAML+コード+データバインド)、あるいはAngularJS(HTML+JavaScript+データバインド)のご経験はお持ちでしょうか? これらのフレームワークを使うと、モデルとビューの連結をデータバインディングのみで記述することが可能になり、結果として究極的にはビュークラスのコードをゼロにすることができるという特徴があります。(あくまでも究極的には、という話です。実際は、若干コードが必要になることがほとんどです) これらの双方向データバインディング機構によって、「データをビューに表示する」ためのコードを最小化(可能ならばゼロ化)し、コントローラーの役割りを「ビューへのユーザー操作(クリック、リスト選択、テキスト入力等)を、データの作成/削除/更新処理に紐づけること」だけに絞り込むことが可能になります。 この状態のコントローラーの役割から逆にたどることで、データバインディング機能のない環境でビューに求められる機能というのも整理できるのではないでしょうか。つまり、ビューに記述しなければならないコードがあるとすれば、それは(1)データをビューに表示する処理と、(2)ビューで発生するユーザー操作をコントローラーに伝える処理、のみに集約できる、というのが基本的な考え方になると思います。 最初の質問に戻りますが、複数のビュー間でデータや操作の連携が必要な場合、ビューではなくコントローラーレベルで論理的な連携インターフェースを実装するのが、全体としてわかりやすい設計になるのではないでしょうか。
退会済みユーザー

退会済みユーザー

2016/03/14 13:45

お付き合い頂いてありがとうございます! 例に挙げて頂いたフレームワークはどれも経験がございません。iosのフレームワークは経験がありますが、こちらは双方向バインディングではないものとなりますね。 頂いた回答の内容は分かりやすく説明を頂いているので、おそらく理解出来だと思います!ありがとうございます。 「ビューに記述しなければならないコードがあるとすれば」のくだりのところなのですが、一点確認させて頂けますでしょうか? 挙げて頂いた1と2のビューに書くコードに加えて、以下のような処理もビューに書くことは間違ってはいないでしょうか? □例 htmlのテーブルセルの中にhtmlのtextareaを縦中央表示させたい。ただし、textareaタグはテーブルセルの中でもcssのvertical-alignで縦中央揃えが効かない仕様のため、jsで入力文字数や行数からtextareaの高さの変更を、textareaに文字入力イベントがある度に随時取得し、常にテーブルセルの縦中央にtextareaが表示されるように位置調整をする。テーブルセルとその中のtextareaを仮に一つのビュークラスで管理していた場合、このtextareaの位置調整を行うメソッドはビュークラスに実装しても問題ないでしょうか? 表示に関することで、かつ、モデルのデータとも無関係な処理なので、ビュークラスに実装するのが適切と判断しても大丈夫でしょうか? また最初の質問の再確認になってしまいますが、この時、このtextareaの位置調整は該当ビュークラス自身内で完結する処理、かつ、モデルのデータに関係のない処理なので、コントローラーにtextareaへの文字入力イベントを伝播せず、そのまま、このビュークラス内でイベント処理を行なっても問題ないのですよね?
tkanda

2016/03/14 14:44

例示されている内容は、そのように理解されて問題ないと思います。
退会済みユーザー

退会済みユーザー

2016/03/16 08:56

ご回答ありがとうございます!自分の認識はひとまず大丈夫そうなので安心致しました。 もう一人の回答者様からのご指摘が気になっているので、未だ設計の方針に自信が持てないままではありますが。。。根本的なところを理解していないまま安易にフレームワークに頼りたくないので、もうちょっと勉強してみます!お付き合い頂いて本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問