laravel ででで MVC でででで chatbox でででで @mkkn_info KFUG ででで LT でで http://kfug.connpass.com/event/22377/ 2015.12.13
laravel で学ぶ MVC
株式会社 chatboxみかかね @mkkn_infoKFUG 年忘れ LT 大会http://kfug.connpass.com/event/22377/2015.12.13
about meみかかね @mkkn_info#PHPer, フロントエンド# 株式会社 chatbox 代表# 関西フロントエンド UG 代表
関西で Web 制作とかやっています。03/05 に FRONTEND CONFERENCE 2016開催します。
facebook: 後藤知宏
twitter: @mkkn_info
laravel
この頃流行りのフレームワーク
laravel開発が盛んな PHP 製フレームワーク
コミュニティ等でも人気が高い
Symfony ベースのコンポーネントシステム・ DI使いやすさを重視した柔軟な UI
日本語リファレンスのほか、最近は本も出てますます学びやすく。
とにかく人気
laravel の豊富な機能• 認証• キュー管理• DB マイグレーション• Tack / Schedule 管理• Billing • etc…
lumen という派生のマイクロフレームワークも
ミニマルな構成+豊富な機能パッケージ
他人と同じものを使うというのはそれだけでメリットだったり
本日は MVC のお話
Model View ControllerWeb アプリケーション構築の考え方の 1 つ
ロジックを扱うモデル、見た目に関する処理をする View 、制御系の Controller の3層に分割する。
アプリケーションを Model View Controller の3階層に分ける膨大なシステムの分割手法の1つ
という、教科書的な話を聞いても実際の現場ではよくわからない事が多かったり。
分割分割というけど、何のために?
なんとなくで MVC してませんか?
MVC の目的と役割を理解して正しいシステム分割を !!
laravel ≠ MVC フレームワーク
laravel = MVC もできるフレームワーク
Dispatchいわゆるルーティング。 MVC の前段階のレイヤ
route.php を利用してなんでも出来る。
フレームワークの重要な機能として、リクエスト処理に応じて、処理を振り分ける機能
MVC ディレクトリ構造を無視した柔軟なルーティング設定が可能な点があげられる。
( 非常に重要 !! )
MVC という概念の無いコード<?php // routes.php
Route::get('/top', function () { $mode = Request::get("list_mode"); $list = Master_List::get($mode); return view("top",["list"=>$list]);});
1 つのファイルに全てを収めるのは管理が大変
だが、しかし
ファイルを分割するだけでシステムは便利になるのだろうか…
ファイル分割のデメリット• 分散するコード• 障害復旧の探索コスト• 追加実装時に実装箇所で迷う• etc…
システム分割の基本基本的な目的は責務の明確化
責務の明確でないファイル分割は、無駄にコードが分散して、逆に複雑になりがち。
ファイルを分ける事がシステム分割ではない。ファイル毎にやること・やらないことを明確にする。
逆に1枚ものの PHP でもブロックごとに責務が明確であれば、十分に可読性のあるコードが出来上がる。
ファイルを分割しようとしない
責務を分割する( 結果としてファイルが分かれる )
Controller Model View
Request 扱う 扱わない 扱わない
ロジック 扱わない 扱う 扱わない
HTML 扱わない 扱わない 扱う
Controller の責務Request (HTTP)を扱う責務
Request を C に集約する (ロジックが HTTP を意識しない )と、View 層、 Model 層の再利用性が上がる。
Request = パラメータの処理や、 Session などHTTP固有の処理
HTTP が Controller 層に集約されると、View 層、 Model 層のテスト可能性が高まる。
Controller 層をView ・ Model から分離することが一番重要
スキニーコントローラの実践は簡単
Controller でやるべきことを考える
Controller(層 )ですべきこと• Request の処理• Session の管理• バリデーション• エラーハンドリング• ( 諸説あります )
View の責務見た目に関する処理を扱う責務
何をするか (ロジック )と何を返すか (レスポンス )を明確に分離することで、仕様変更に対する柔軟性が上がる。
一般的には HTML だが、 API などの場合には JSONResponse として捉えると良い。
一般的にロジックの修正は入りにくい。レスポンスに関する修正は頻繁に発生する。
ポイント: View で Controller を扱わない
Controller 層を含む View
<div id=“header”> <?php if($user = Auth::user()):?>
username: <?=$user->name?> <?php endif;?></div>
<?php if($msg = Session::get(“message”)):?> <div class=“alert alert-default”> <?= $msg ?> </div><?php endif; ?>
View で気をつけること• データの割当は極力変数で割り当てる。• テンプレート内部で呼び出すのは
ステートレスなヘルパー系の関数のみ• ロジック的な複雑な処理は、
ステートレスにして、 Model に追い出す。
見た目に特化した View のメリット• View の中にロジックが入らないので
コードの見通しが良くなる。• HTTP レベルの要件に依存しないので、セッション等リクエスト層での仕様変更でView を調査・変更する必要が無くなる。
• リクエストの状態に影響されないので、View を部分的に切り出して転用も楽。
Model の責務ロジックに関する処理を扱う責務
機能に関するベースの部分で、テストの重要性が高い設計においても比較的初期に仕様が固められる
ロジック = システムの根幹機能に関する処理全般システム UI に関する影響を受けない根底部分
ロジックと言っても範囲は広範なため、更に細かくレイヤを分割する必要がある。
ポイント 1:Model で Controller を扱わない
Controller 層を含むModel
public function login(){ $email = Request::get(“email”); $password = Request::get(“password”); $user = User::where([ “email” => $email ........
public function getUser(){ $id = Session::get(“login_id”); return User::get($id);}
ポイント 2:Model で View を扱わない
View 層を含むModel
public function getUserJson(){ $data = $this->toArray(); unset($data[“passowrd”]); // パスワードはマスク return $data;}
public function getCategory(){ if($this->category){ return “<span class=‘category’>{$this->category}</span>” }else{ return “<span class=‘default’> 未分類 </span>” }}
Model で気をつけること• Model の入出力について、特定のケースのみを想定し
た書き方をしない。• 入力: HTTP だけでなく Artisan,Job など• 出力: HTML だけでなく console, json など• 単純に引数と戻り値のみ考えれば良い。
• どうしても…という場合には ControllerService やViewModel といった層の導入も考えてみる。
ロジックに特化した Model のメリット• Model の責務が明確で仕様変更に強い Model
が出来上がる。• 入出力が明確で、再利用性の高い柔軟なモデ
ルが出来上がる。• 再利用性が高く、仕様変更にも強いためテス
トを書いても寿命が長く使える。
ユニットテストの導入は、現場の状況次第で難易度が変わる
テスト可能なコードを書く= 本人の技術力次第
テスト可能なコード= 責務が明確であるコード
責務を意識してコード記述を進めるとドメイン駆動などの設計論もわかりやすい
なんとなくでなぞると「っぽい」だけで意図のわからないコードが…
責務意識して綺麗な MVC
ご清澄ありがとうございました。