MVCモデルをデザインパターンを使いながら理解する
- 2021.07.18
- IT
「Head Firstデザインパターン」という本に、
「MVCモデルを理解するにはデザインパターンが有用である」と書いてあり「本当か?」と思ったのでまとめてみました。
MVCとは
テキトウな定義
MVCとは、Model, View, Controllerの頭文字をとったものです。
Modelは、ビジネスロジック(データの管理と操作)を実装します。
Viewは、名前通りUIを実装します。ユーザーとの接点となるのは、ここです。
Controllerは、Viewからのアクションをモデルに対するアクションに変換する司令官のようなものです。
(Controllerだけ、「er」が語尾についていることからも、この人が主体だと分かると思います。)
詳しくはコチラ
MVCはSmalltalkという言語が発祥のようです。(Wiki)
(1970年代からあったんですね)
ウィンドウを用いた対話型アプリケーションを開発する設計指針として作られたようで、
Controllerが頑張るMVC、依存性を利用したMVC、プラガブルを利用したMVCがあるそうです。(出典)
とはいえ、Web時代のMVCとは異なる部分も多くあるとは思いますが、歴史がSmalltalkの方がありますから、
Web系のシステムでも参考にされている部分は多くあると思います。
MVCの流れ
ざっとですが、HeadFirstデザインパターンの11章に載っていたDjViewをPythonでGUIソフトを作ってみたので、参考にしてみてください。
(この本自体はJavaで書かれている)
起動時
まずは、起動時に必要なデータを作るために、Modelを作ります。
次に、Controllerがそのデータを利用しつつ、Viewに作成命令を出します。
Main文には、Viewのインスタンスを作る、などのコードは登場しません。
そこはControllerがやります。
Main文はこのようになります。
1 2 3 4 5 6 7 |
def main(): model = BeatModel() controller = BeatController(model) if __name__ == "__main__": main() |
起動後の流れ
起動後は、下記の図のように、ユーザのアクションによって、主に3つほど(パターンA,B,C)呼び出しパターンがあるかなと思います。
なお、重要な点は、「パターンをどれにするかは、Controllerが判断している」という点です。
それぞれについて説明します。
パターンA
こちらは単純で、ユーザからのアクションに対して、Viewのみを変える、というパターンです。
例えば、テキストをマウスで左クリックしながら選択すると青色になる、とかですかね。
パターンB
こちらは、ユーザからのアクションに対して、ViewとModelを変える、というパターンです。
例えば、音楽再生アプリで「▶||」ボタンを押したときに、
Modelでは音楽の再生が停止され、Viewでは音楽再生時の背景の変化などが変わるのが停止される、とかですかね。
パターンC
こちらは、ユーザからのアクションに対して、Modelを変えた後に、そのModelの結果を基に、Viewを変えるというパターンです。
例えば、家計簿アプリで、「費用を登録」ボタンを押したときに、
Modelでは、費用のデータを更新し、そのModelのデータを基に、Viewの「今月の費用」の表示が変わる、というパターンです。
(図中の「Observerパターンを使う。Modelが変化すると、ViewにNotifyしてあげる」は以降で説明します。)
さて、色々とMVCの流れを説明してきましたが、この流れを実現するために、デザインパターンが使われている、ということです。
MVCとデザインパターン
HeadFirstデザインパターンによると、下記の図のように、
ModelがObserverパターン、ViewがCompostieパターン、ControllerがStrategyパターンが使われているとのことです。
(全部が全部使われているとは限らないですけど。)
使用されているデザインパターンの説明
Model: Observerパターン
Observerパターンとは、「オブジェクト間の1対多の依存関係を定義し、あるオブジェクトの状態が変化するとそれに依存しているすべてのオブジェクトが自動的に通知され、更新されるようにする」パターンです。(HeadFirstデザインパターン)
そして、MVCにおいては、Modelの状態が変化した時に、Viewに通知され、GUIが更新される、のように使われています。
observer(観察者)という言葉の意味とは少し違う動きをobserverパターンはします。
この点を、「Java言語で学ぶデザインパターン入門」では下記のように記しています。
observerという言葉の本来の意味は「観察者」ですが、実際にはObserver役は能動的に「観察」するのではなく、Subject役から「通知」されるのを受動的に待っていることになります。Observerパターンは、Publish-Subscribeパターンはと呼ばれることもあります。
こう考えると、ModelがSubject役で、Viewが通知されるのを待っている、といえるので、納得です。
View:Compostieパターン
Compostieパターンとは、「部分ー全体階層を表現するために、オブジェクトをツリー構造に構成する。Compostieパターンにより、クライアントは個別のオブジェクトとオブジェクトのコンポジションを同じように扱える」パターンです。(HeadFirstデザインパターン)
説明だと分かりにくいですが、データ構造の1つのツリー構造において、
子要素を持つ「ノード」と、子要素を持たない「リーフ」と言いますが、ノードもリーフも同様に扱えるということです。
GUIはこのようにツリー構造になっているので納得です。
(Modern Tkinter for Busy Python Developers より)
Controller :Strategyパターン
Strategyパターンとは、「一連のアルゴリズムを定義し、それぞれをカプセル化してそれらを交換可能にします。Strategyパターンによって、アルゴリズムを使用するクライアントとは独立して、アルゴリズムを変更でき」るパターンです。(HeadFirstデザインパターン)
今回のMVCではさして使っていませんが。。
アルゴリズムをとっかえひっかえできるのは、改修が楽になりますし作る上では意識しても良いかなと思います。
まとめ
書いたコードをリファクタリングするにあたりデザインパターンを使ったら、分かりやすくなるかなと思い、
「Head Firstデザインパターン」という本で勉強していました。
その際に、MVCモデルを理解するにはデザインパターンが有用である、と書いてあり「本当か?」と思ったのでまとめてみました。
私としては、確かに理解のためになったし、理解が進んだな、と思いました。
誰かの一助となれば幸いです。