いままでPHPでWebサイトを作ってきたが、仕事でも趣味でも常にひとりで作ってきたので、新しい会社でふたりでひとつのプログラムを作れとなった時に、分業や連携をどうやればいいのかというのを大きな課題に感じている。
会社から「MVCで検索してみろ」とヒントをもらった。
MVCについてはこちら
http://www7.ocn.ne.jp/~fishbone/mvc/
つまり、
■次のみっつの領域を分けて作成する。
◆Model:見えないが色々処理する部分。Webで言えばログインセッションの管理やデータベースとのやりとり。
◆View:見える部分=ユーザーインターフェイスの部分。
Webで言うならHTMLの出力やJavaScriptの仕掛けの実装など。
◆Controller:上記2つを橋渡しするための上位存在。
■分業は厳密に。つまり、
◆Model部分は表示の機能を持ってはいけない。
Webで言えば「データベースを一行ずつ読みながらテーブルを一段ずつ出力していく」
ということをやってはいけない。
◆View部分は処理の機能を持ってはいけない。
Webで言えば出力のために加工したデータをデータベースに書き込むといったことをしてはいけない。
じゃあ上記の思想を実際の現場でどうやって組み込めばいいのだろうとピンとこなかったけど、暫定的な理解が得られたのでメモっておく。
PHPでもオブジェクト指向にそったプログラミングをしようと試み始めている。
オブジェクト指向については以下の2つの教材で勉強し、かなり腑に落ちた。
C++入門(Weサイト)
要点は、
■現実世界を観察し、それを仮想世界(プログラム)で再現しようというのがオブジェクト指向の目的。
■現実世界での登場人物をクラスに置き換える。
■登場人物は擬人化したものでもよい。どんどん擬人化するといい。
Webシステムでクラスを設計するなら、つまり登場人物を擬人化で作成するなら、次のようになると思う。
■HTMLのお決まりの部分を出力するひと
■ログイン状態を監視するひと
■データベースに問い合わせる人
■入力フォームに入力された内容にエラーがないかチェックするひと
など。
さて。
メインのプログラムがあり(たとえばindex.php)、必要な処理はなるべくクラスを作ってそのメソッド呼び出しで実現している。
たとえば商品台帳のデータベースからデータを参照して表として出力するプログラムがあるとする。
--------------------------------------------------------------------
[メインの処理]
ユーザーからの入力(表示ページ番号や検索条件など)を受け取れ。
HTMLでメタ部分を出力しろ。
HTMLでテンプレートのヘッダー部分を出力しろ。
HTMLで表の直前まで出力しろ。
ユーザーからの入力を検索条件にしてデータベースに問い合わせ、商品の一覧のデータをピックアップしろ。
データベースからもらったデータを使って表を出力しろ。
HTMLで表が終わった部分からフッター直前まで出力しろ。
HTMLでテンプレートのフッター部分を出力しろ。
HTMLで残りの部分を出力しろ。
[メインからの命令に答えるために必要となるクラス]
■各種データを受け取るクラス
受け取ったデータを格納する
■静的なHTMLを出力するクラス
メタ部分を出力する
ヘッダーを出力する
フッターを出力する
フッター以後を最後まで出力する
■表を出力するクラス
表を出力する
■データベースに問い合わせるクラス
受け取った検索条件を元にデータベースに問い合わせる
問い合わせた結果を返却する
--------------------------------------------------------------------
こんな感じになる。
メインの処理にはなるべく直接的な処理を書かないほうがかっこいいと思うのでそれを目指してクラスを作っている。
現状ではそういう作り方。
で、この流儀をベースに、MVCの思想を導入するにはどうしたらいいのか。
「メインの処理があり、各種クラスに命令を出す司令塔の役割をさせる」というのは正しいと思う。
つまり、メインの処理=コントローラーとなる。
用意したクラスを観察すると、どうも確かに、表示系と処理系とに分けられることに気づく。
■表示系
◆静的なHTMLを出力するクラス
◆表を出力するクラス
■処理系
◆データベースに問い合わせるクラス
ここまでで、なるほどこいつらの分業を厳密にして、フォルダも分ければいいのか、ということが分かる。
例えばこうすればいのかな。
index.php
┣view
┃┣(各種クラスファイル)
┃┣js
┃┣css
┃┗img
┗model
┗各種クラスファイル
仕事を分けるということが必要。
たとえば「表を出力するクラス」というのを作るとき、MVCの思想を知らなければ、次のようなクラスを作ってしまうと思う。
■表を出力するクラス
HTMLでテーブルタグの一行目を出力する。
データベースに問い合わせてデータを取得しつつ、TR一段分のHTMLを出力する。
HTMLでテーブルタグを閉じる。
しかしこのクラスは、表示と処理とをひとつのクラス内でやっているので、MVC的にいうとアウト。
クラスは分ける。
■表のHTMLを出力するクラス
■データベースに問い合わせるクラス
で、じゃあ2つのクラスをどう連携させるのかという問題。
それは、「引数」と「戻り値」とで実現する。で、そのやりとりは二人に直接やらせるのではなく、コントローラーという司令塔(メインの処理)にやらせる。
「やりとり」とは、
やり:メソッド(クラスの持つ関数、働き)に渡す引数
取り:メソッドから返却してもらう戻り値
検索条件などの入力内容を、データベース問い合わせ係(Model)に引数として渡す。
データベース問い合わせ係から、欲しいデータが戻り値として渡される。
表の出力係(View)に、表示してもらいたいデータを引数として渡す。
表の出力係は、受け取ったデータを元に、表を出力する。
こういう流れになる。
じゃあ疑問なのが、「データを受取るクラス」はViewなのかModelなのかということ。
検索フォームなんかの場合、受け取るデータに付いている名前は検索フォームのHTMLで定義している。つまりその命名責任はViewにある。
GETやPOSTで送信されてくるデータを受け取る場合、HTMLで名づけた名前が必要。その名前についてはModel側は検知してはいけない。
すると、View側で受け取って、それをコントローラーに渡し、コントローラーその値を引数としてModel側に手渡せばいいのかな。引数の形式の指定は常に、コントローラー-View間、コントローラー-Model間で行われ、View-Model間で行われることはない。
とりあえず、MVCの思想でのプログラム作成をざっくりと上記のように理解しておこう。
それを、実際の環境にどう落としこむか(現在の案件ではFuelPHPというシステムがベースになっているところに入れないといけないらしい)というのは、また別の話。
で、じゃあ分業はどうやってやればいいのかという話に戻る。
二人体制なら、
■片方がView部分担当で、出力系のクラスを作成する。JavaScriptを使ったギミックなども作成。
■片方がModel部分担当で、ログインセッションの管理やデータベースへの問い合わせ、APIからのデータ取得などを行う。
■コントローラー部分(メインの処理=上位的存在)は経験の豊かな方が担当し、もう片方は随時、「自分の作ったメソッドの呼び出しはこう書いてください」とか「こういう引数がほしいんですけど」みたいな相談をする。
こんな感じかな。