フレームワークとMVC

タグ: Framework  

初心者向け解説の第2弾です。

MVC…うむ…

MVC、モデル、ビュー、コントローラーの頭文字をくっつけたものです。

Webフレームワークにおいて、しばらく前には「うちのフレームワークはMVCです」と喧伝されました。そのため、自ずからMVCフレームワークだと宣言していないものまで、MVCと解説されます。文字通り捕らえるなら、そのフレームワークにはモデルとビューとコントローラーの3機能しか備えていないということになります。実際は、非常に多機能なフレームワークが多く、MVCかその要素が含まれているという意味合いで利用されます。

ですから、MVCと言っても、フレームワーク機能の一部分だけを指しているに過ぎません。

MVC

MVCは元々、Webアプリケーション向けに作られた概念ではありません。詳細は検索してもらうとして(情報量と意見の違いで嫌になることうけあいです)、基本的には「何もかも一つにまとめちゃうとごちゃごちゃしちゃうよね。だからモデル、ビュー、コントローラーに分けると良いんじゃねぇ〜(若者言葉風に語尾を挙げる)」というものです。そこにオブジェクト志向の風味を足したものです。

そんな単純なものですから、全ての問題を解決できません。ごちゃごちゃにもいろいろありますし、動作する状況だっていろいろです。ですから派生パターンが多くなりました。MVCと言っても厳密に同じものを指せなくなりました。「俺のMVCはこうなんだ」という意見により、よく論争が起きます。

結局、PHPのWebアプリケーションがMVCであると言っても、その3要素が含まれているという程度の情報しかありません。

深遠なるモデル

話は更に深くなります。暗黒面には手を出したくありませんので、さっと通り抜けましょう。

モデルです。多くのフレームワークでモデルの説明にはデータベースが引き合いに出されます。あるフレームワークではわざわざ図で説明してあります。

そして、そのフレームワーク公式のブログで、「モデルはデータベースではなく…」と説明されていたりしました。恐ろしいですね。混乱を招くだけです。(幸いに、どのフレームワークだったか忘れていますので、あえて検索して恐怖を蘇らさないように気をつけています。)

ぶっちゃけて言うと、モデルはデータベースからの取得結果である説明が初心者向けの資料で書かれており、それを読んだ新しい人がそれを信じました。多分、書いた方はもっと深遠な知識を備えていたのでしょうが、説明が面倒だったのでしょう。それから、ドメイン駆動設計をざっくりと応用して、「モデルはもっと広い意味で、アプリケーション独自のロジックも含むよねー」という解釈と、きっちりとドメイン駆動設計に基づいた意見があります。だいたいモデルに関しては、この3つの見方があるんだと覚えておきましょう。(だからといってドメイン駆動設計を勉強し始めなくてもだいじょうぶです。将来、もっと設計がうまくなりたいと思ったときに、技法の一つとして勉強してください。フレームワークを使うために必要なものではありません。)

フレームワークを勉強する場合、そのフレームワークによりどういう捉え方をしているのかを先ず捉えましょう。一番多いのはやはり、取得したデータベースレコードを指すオブジェクトを指すことが多いです。文脈や解説者により、意味がずれることもあり得ることに注意してください。

ビュー

PHPのビューは通常シンプルです。PHPがもともとHTMLに組み込まれ動的に内容を変更するために使われた言語だからです。一番手をかけない形式であれば、PHPファイルにHTMLを記述し内容が変わる部分をPHPで記述します。

PHPを使えるのですから、全てをビューに書くことができます。ビューって最強!

しかしながら、それではMVCとか言っている意味がありません。ビューという名前が示す通り、内容の表示に絞り込むべきでしょう。

でもまあ、MVCの混乱は当然ビューにも影響を与えます。ある人は「ビューからはロジックを完全に排除すべきだ」といい、オブジェクトを渡すのはとんでもないと言います。別の人は逆の意見で「オリジナルのMVCはビューからオブジェクトの参照を許しているので、オブジェクトの利用は問題ない」と言います。うーん、すると正解は真ん中を取って、オブジェクトを渡しても良いが、ロジックの入るメソッドは呼んじゃいけない? いやいやいや…

コントローラー

コントローラーはどのビューを表示するか選択し、モデルの操作を行う役割を持っています。

MVCと分けると単純に提唱されると、「モデルはデータベースのオブジェクト…ビューは表示…じゃあ、アプリケーション独自のロジックはコントローラーだ。」となります。そして、コントローラーにロジックが集中します。

そもそも、一箇所にまとまるとわかりづらいから分離しようという考えなのに、コントローラーにロジックが集まり、保守しづらくなります。有名なバッドプラクティスである、「ファット(太った)コントローラー」です。

大抵のフレームワークにおけるモデルはデータベースレコードを表すオブジェクトとして説明されます。ならば、ロジックの大抵はモデルの操作になるわけですので、そのモデルクラスにロジックを組み込もうと言う発想が起きるわけです。するとコントローラーの代わりにモデルクラスが太ってしまいます。どこか一箇所がメンテしづらいほど大きくなってしまえば、MVCを採用する意味がありません。初心者にMVCを強調しすぎては行けない点です。

VC+いろいろ

MVCの形にこだわりすぎて、いろいろ問題が起きるわけです。ですからより細かく役割分担を行えば良いだけの話です。責務の分離といいます。関心(事)の分離とも言います。同じことです。

新しい言葉、オブジェクト指向が生まれてから出てきた言葉を使わなくても、「機能分離」といえば古い方にもお馴染みでしょう。ええ、古い概念に新しい言葉を付けおしゃれに見せかけるのは、よくある手法です。(厳密には違うというアカデミックな意見を持つ人もいるでしょうが、大方は同じです。)

ビューは表示に関するロジックを含むのは良しとしましょう。あれこれ表示に準備が必要な場合は?悩まなくても、そうした役割を持つクラスを作りましょう。専任者を付けましょう。もちろんオブジェクトを渡してもOKにしましょう。PHPですから。

モデルに表示のためのロジックを含めるのは良いのか、悪いのか?善し悪しではなく好みの問題でしょう。規模が大きくなっても、方針が変わらなければごちゃごちゃする部分でありません。モデルに表示のためのロジックを含めると決めたなら、それに従いましょう。モデルからの情報の取得を含め、ビューに表示準備の専用クラスを付ける方針にしたら、それに従いましょう。

ところで、モデルってなんでしたっけ? 曖昧なままですね。多分、構築するアプリケーションの規模にも影響があるでしょう。小さくて個人で使用するサイトであれば、テーブルレコードのオブジェクトを簡単に取得できるORMが返す結果でかまわないでしょう。大きくなるにつれ、ある概念を指す純粋なクラスの事になるでしょう。理想的には、曖昧なモデルは利用せず、その役目に応じて責務を独立させましょう。

モデル云々は自分の設計指針や考え方でかまわないのです。しかし、他人が別の指針を持っていることもあります。同じプロジェクトでは統一する必要がありますが、それ以外では他の人が別の意見を持つ自由を尊重しましょう。

コントローラーはシンプルに保ちましょう。太るようであれば、自分の作成するアプリケーションの責務を考え、分離しましょう。しかし、小さく単純なアプリケーションを作成するなら、コントローラー内に書いたままにしておくのも、やぶさかではありません。責務の分離にこだわりすぎ、クラス分離による複雑さの増加が、同じく分離による利点を上回ってしまうのであれば意味がありません。重要なのは「トレードオフ」です。

まとめ

現代の機能豊富なフレームワークではMVCが表すのは、全容の一部分だけです。ところが、MVCがオブジェクト指向と共に古くから使われてきた概念のため、こだわる人が多いのです。こだわる部分は強調されます。そのため、とても重要なように思えます。しかし、実際はあくまでも一部分です。

ビューとコントローラー、そしてその他の部分は「責務の分離」により、より細かく捉えましょう。

幸いにしてPHPには名前空間があり、多くのフレームワークはComposerに乗っかり、PSR-0、PSR-4ローディング規約に従っています。名前空間とフォルダー構造により、自由に構成できるのです。MVCにこだわりすぎ、迷わないようにしましょう。MVCの3つを分離の基準とするのではなく、アプリケーションの複雑さに合わせて、責務を分離しましょう。