14260


MVCというデザインパターンでコード分けすることになっているのですが、  
様々なサイトを見てみるもMVCがいまいち理解しきれません。

まず以下の考えは合っているでしょうか？

  * `Model`はUIに関係のないことをする
  * `View`は`Model`から情報を取得して表示する
  * `Controller`は`Model`と`View`の仲介役

また、`View`のイベントを処理して`Model`に何かさせるのが`Controller`かと思うのですが、  
`Controller`には例えば`View#setOnClickListener`などを記述すれば良いのでしょうか？  
それとも`View#setOnClickListener`自体は`View`に記述して  
`View#onClickListener`かその中身を`Controller`に記述するほうが良いでしょうか？

あと、Androidの`Activity`や`Fragment`は`View`と`Controller`どちらに当てはまるのでしょうか？  
それから、`Fragment`にはどこまでやらせるのがよいのでしょうか？  
現状はxmlからの`View`生成程度しかやらせておらず、その`View`にデータをセットしたりというのは別のクラスでやらせています。


CC BY-SA 3.0
2015-08-11T00:57:37.697
14252
2015-08-14T12:25:01.390
2015-08-11T04:46:08.303
7290
9710
question
android android-fragments mvc
MVCがいまいち理解しきれず困っています


> `Controller`は`Model`と`View`の仲介役

私の場合は、もっと単純に **入力** という言葉で片付けてしまっています。  
つまり **VC** はまとめて **出入力** 。  
**それ以外の** 、入出力インターフェースから切り離した、純粋な **内部ロジック** の部分が **Model** 。  
[Wikipediaの解説](https://ja.m.wikipedia.org/wiki/Model_View_Controller)によると

> このような **M-VC** となるような構造を **Document-View** と呼ぶ

そうです。 **V** と **C** の違いはわりとどうでもよくて、まずはともかくは **M** を他から切り離したい、というのが肝ではないかと思います。

一方、Androidの膨大なAPI群は **VC** がほとんどだろうと思うので、 **V** と **C**
の違いはかなり前面に出てくると思います。基本的にそのまんま、 **V** はAndroidでも`View`と呼ばれているので、迷う余地は少ないと思います。

**Activity** というのは **MVC**
とは完全に違う次元の捉え方なので、無理に混ぜて考えない方がいいと思います。イベントを中心にどう振る舞うかというようなものだと思うので。対して **MVC**
は単純に部品（ブツ）を分けているだけです。

>
> 現状Viewへの表示とViewのイベント処理を同じクラスでやらせてしまっていて、VC的にはそこを分けたほうが良いだろうけどどこで分けたら良いかわからない‌​状態です。

**V** と **C** の境界で悩まれているようですが、実は、 **M** さえ間に一枚挟めば、必然的に解消されてしまうことなのです。 **V** と
**C** の境界について考えるあまり、 **M** の存在がどこかに行ってしまってはいませんか？

**View** は **Model** から読み取って **受動的に** 表示するだけです（ **出力** ）。 **View**
へのイベントは、実は、「 **View** へ」と考えるのではなく、 **Model** へのイベントであり、 **Model**
の内部状態を変更するために受け取ります（ **入力** ）。

ですから、実際の Android プログラミング的には、`View`に`OnTouchListener`を implement するというのは、
**MVC** 的ではないと思います。外側から、`View`に対して、`OnTouchListener`を set することはあっても、callback
を受けとる主体が`View`なのではなく、そこはあくまで、 **Controller** と **Model** の間の関係であるべきです。

* * *

## Model について

**Model** は、簡単な例で言うと、オセロ（リバーシ）ゲームをプログラムするとして、8x8 の升目を 64 の int 配列で表現する（か、8x8 の
2 次元の int 配列で表現する）という部分が **Model** です。（int にするのは 0: 空; 1: 白; -1: 黒とでもするため）

**View** はこの配列を見て、どういう風に表示すればいいかだけを常に考えています。

**Controller** はユーザーからの操作や、何らかの外部的な要因によって、この配列に適宜変更を加える役割だけを考えています。

こうすることによって、必然的に、 **V** と **C** が直接触れあうことはなくなり、間に、「わざわざ」 **M**
という薄紙を一枚挟むことの利点が得られるわけです。

特に、 **C** → **M** → **V** という 3
段階の流れで考える必要はないと思います。手続指向ではないからです。（結果的にはそういう順番の手続で処理されますが）


CC BY-SA 3.0
2015-08-11T04:35:28.037
14260
2015-08-14T12:25:01.390
2015-08-14T12:25:01.390
7290
7290
14252
answer


> ModelはUIに関係のないことをする

「ModelはUIに関する処理を担当しない」って意味ならイエス  
だがMVC間で「関係ない」っつー言い方はしねー。二つにまたがるもんは必ず出てきてどっちに実装するか考えることになる

> ViewはModelから情報を取得して表示する

イエス  
ただ二者の関係を考えんなら双方向だ。ビューは表示するデータをモデルに依存するがモデルはビューに頼ることは何もねー。それと取得というより参照だ

> ControllerはModelとViewの仲介役

ノー。コントローラが仲介するのはユーザーとモデルだ  
ユーザーの存在 - 操作を受ける - モデルを変更する - ビューを更新する、っつー流れだ。お前の考えではユーザーの存在が抜けてねーか

* * *

> Viewのイベントを処理してModelに何かさせるのがControllerかと思うのですが...

ここ微妙に違うんだけどな、質問の要旨は次だから飛ばすわ

> Controllerには例えばView#setOnClickListenerなどを記述すれば良いのでしょうか？

イベントリスナをどこに書いたらいいかっつー話だろ。コントローラだ  
んでビューとコントローラが性質上融合してっからそのままViewクラスに書けばいい。イベントリスナのメソッドが用意されてりゃクラス名がViewでもコントローラの役割があるっつー逆説的な考え方だよ

> AndroidのActivityやFragmentはViewとControllerどちらに当てはまるのでしょうか？

コントローラ  
ユーザー操作をメソッドの形でアプリ、言い換えるとプログラマに伝えてるだろ。アプリのライフサイクルもユーザーが端末をスリープさせたとかアプリを終了させたとかいう操作なんだよ

> Fragmentにはどこまでやらせるのがよいのでしょうか？

開発者次第だが基本はコントローラの範囲だろ。まずはモデルに属するメソッドを呼べ

* * *

実装のコツ

  * コントローラのイベントリスナのメソッドではモデルの操作をするだけ
  * ビューはモデルの変更を自動的に知り自身を更新する

アプリ全体の大きなMVC以外にも内部の小さなMVCを意識しろ。モデルはアプリのデータだけじゃねーぞ。スイッチのオンオフ状態、ビューのツリー構造、ボックスの背景色の値もモデルだ。そしてMVCの関係は必ずしもクラスで切り分ける必要はねー。ユーザーの操作で発生した仕事の流れをコントローラから始まりビューの更新で終わるという一定のパターンにしろ

* * *

コメントへの返答

> MVCモデルの概念を漫画で解説してみる

俺の考えでは「Viewを窓口」と言っている時点で間違いだ（窓口はコントローラだ）。だが理論を実装に落とし込んだ時にそう考えるようになったんならそれがそいつの実装結果だ  
実装時は言語仕様やMVC各要素の比重などあらゆる要因で設計が変わる。ひとつのビューがふたつの異なるモデルの表示を担当することもある。柔軟に考えろ。変化しないのはユーザー操作から発生する操作受付、モデル変更、ビュー更新の仕事の流れだ

> 話の中に出てくる"おしゃれした私"がどういう変化か理解しきれていません。

クラスを用いた処理の抽象化と外部向けAPIの互換性保持の話だ。MVCに限らねークラス設計の常識だ

> あんな風に完全分業できないですよね？

デザインパターンは「人の分業」は目的にしてねーだろう  
ボタンの配置からコマンドまでをデザイナに一作業だけで変更させるならそうできる仕組みを開発環境側で構築するしかねー


CC BY-SA 3.0
2015-08-11T21:56:02.523
14297
2015-08-13T08:12:18.893
2015-08-13T08:12:18.893
14252
answer


私は、DOMやボタンコントロール等画面部品を直接処理するコードがViewで、（要求仕様に基づく計算式やデータベース等）画面がHTML5かJavaかにかかわらず同じ（例えば使いまわしできる）コードならModel、Controllerは、そのどちらとも言えない処理だと思って層分けしています。

加えて、以下の依存関係は守りたいです。Contoroller-(使う)→Model,
View-（使う)→Model。つまり、ModelがContorllerやViewを使う（依存する）ことはないような関係です。

なので私ならば、View#setOnClickListenerはViewに記述します。なぜなら、画面部品をきかっけとして呼び出され（依存し）ているからです。

View#onClickListenerかその中身をControllerに記述するほうが良いかどうかという点については、ほぼYESになると思います。


CC BY-SA 3.0
2015-08-12T22:33:22.690
14341
2015-08-12T22:33:22.690
10752
14252
answer