読者です 読者をやめる 読者になる 読者になる

わざわざ残す必要もないことを整理とか気にせずに吐き出していく。そんな空間。

MVCのViewというものについて考えてみる

PHP

MVCについて語ると、ホットエントリー入りするみたいです。

Viewとはなにか

 Viewとはそもそもなんなのだろうか。うちはWeb屋さんなので考えるのはもっぱらHTMLのWeb出力なのです。が、時としてはPDFで帳票出力したり、excel(という拡張子のCSV)でデータ出力したり、Javascriptの為にJSONで出力したりします。ログはTXT形式で出力しますし、バッチスクリプトを意識する時はbash向けに出力します。

 こうなってくるとViewという仕組み自体実は一枚岩ではなく、複数のレイヤーからなるものだというのは言わずもがな、のように思えてきます。うちの場合はだいたい次の3レイヤで考えている感じです。

  • 出力部:出力する。WebだとHeader吐いたり、bashだと出力先決めたり,exitコード吐いたり。もちろんBODYも吐くのですが、BODYの内容は外部要因です。
  • テンプレート部:いわゆるBODYの構造を決定する。構造はWeb画面ならHTMLだし、CSVなら配列だし、JSONなら相応のto_array可能なクラスだったり。
  • モデル部: いわゆるViewModel。見た目に関するロジック。

 Viewの中になんでモデルが入ってるんだよ、みたいなツッコミがあるかもしれませんが、そう言う話はまた後でしましょう。

出力部

 色々と軽視されがちなんですが、大事だと思います。http 200の404ページとか地味におおいですよね。うちもそういうことよくやりますが。このへんが触りにくいフレームワークとかはよくあるのですが、そういうのはあまり気乗りしません。

 特にAJAX系の処理とか触ってる時はHTTPのステータスコードでコールバックの関数が変わったりとか、JSONに入れちゃうの嫌な内容をHTTP HEADERに押し込んだりしたいのでこのへんが触りやすくないシステムはなるだけご遠慮願いたいところです。 (あと処理系のPOST URLアクションでリロード対策としてリダイレクトしてる系のあれをデバッグするときには、HTTP CODEをDebug用の余白として使うと便利だったりするのですよ)

テンプレート部

 この辺はもう別に特にいうこともないのですが、いわば処理の末端の部分で一番ユーザに触れやすい部分なわけなので。ビジネスロジックの変化を一番受けやすい部分といいますか、頻繁に変更が起こることは覚悟しておきたい部分、だと認識しています。

 システムの都合で画面の表示が変えられないなんてお粗末なことはできるだけ避けたいですので、こんな所でえっこらせっこらDRY精神むき出しにして「美しいコード」なんて書いても骨折り損なだけなんじゃなかろうかと。正規表現という便利なものもありますし。

 何より大事なのは、モデルみたいなコアの処理部分と違って、テンプレートに多少のバグがあろうが、メインの処理系には何の影響もない、ってことです。バグに対するリスクが非常に少ない。むしろ少なく無いと行けない、というか。テンプレート部書き損じたらデータベースの外部キー構造がぶっ壊れた、なんてありえないので。強気に改修できる。

 そう言う部分であり、そう言う部分ある事を意識した設計であるべきなんじゃないかと思うわけです。

モデル

 Viewの中にモデルが入ってる、という事に嫌悪感をもたれる方も多いんじゃないかと思うのですが、ViewにはViewなりのロジックがあって、そういうまで「モデル」と呼ばれるものの中に入れてしまうのはちょっとげんなりします。

 そもそもViewだけじゃなくてControllerにもモデルはある。モデル、というかロジックか。ロジックは全部モデルに!!みたいな訳の分からないMVCスタイルが何故か流行ったりするのですが、システムにロジックがあるのはMでもVでもCでも当たり前の話で、それを全部モデルに押し込む事に何の意味があるのか、と。

 スキニーコントローラ目指したらモデルが肥大化し過ぎた…みたいな話はよく耳にします。名前空間を使ってモデル構成を綺麗に階層化しようとかそういうアプローチも無くはないと思うのですが、ViewにはViewの役割を、ControllerにはControllerの役割をしっかり認めて、それぞれのドメイン毎に適切にロジックを分配するってのがいいんじゃないですかねぇ…と思うのです。

 まぁ言ってしまえば、Model内のView寄り処理と呼ぶか、View内のModelと呼ぶかの違いなだけかもしれないです。ですが、Model内のView寄り処理なら、きっちりViewとしてModelの外に置くという意識付けをしないと再利用性の少ないガチガチのModelが量産されてしまうと思うのですよ。

 Viewにモデルを認めない人は、使いようのないモデルを量産する。モデルがViewの事を意識しすぎてるから、画面(HTML)で使ってたモデルをJSONで再利用しようとしたらHTMLタグが邪魔で使い物にならないし、スマホ対応するだけなのに、何故かモデルから書きなおさないといけなくなってくる。

 最初はPCの画面だけ、のシステムでも、将来スマホ対応するかもしれないし、画面処理が高度化してAjax使うならJSON出力が必要になってくるし、処理が重くてCRONで処理するとなればbash向けの処理が必要になってくる。画面を印刷したいと言われればPDFなりCSVなり…。なのになぜDAOがHTMLを出力しますか?と。

 それをきっちり同じ「モデル」という枠組みの中で分離して再利用性確保しながら設計できるなら、別にModel内のView寄り処理だろうが、View内のModelだろうが構いはしないのですがね、どうもそう言う訳にはいかないのが現状なんじゃないかなぁと…

最後に

 年の瀬も近いと言う事で、去年の自分に見せてやりたいエントリーを一つ仕上げてみました。

 いろんな設計を見てきましたが、何事もバランスが必要なんじゃないか?という話です。

 年末は一人アドベントカレンダーで忙しくなりそうなので、11月中に色々片付けておきたいところです。

 あ、あとモデル内でリダイレクトとかするのもやめてください。血を吐きそうです。