タイトル: MVC
SEOタイトル: MVC アーキテクチャ完全ガイド
| この記事の要点 |
|
MVC とは
MVC (Model-View-Controller) はアプリケーションを 3 つの責務に分割するアーキテクチャパターンです。1979 年に Trygve Reenskaug が Smalltalk-80 のために考案し、その後 GUI アプリ・Web アプリの基本設計として広く普及しました。
| 役割 | 責務 | 例 |
|---|---|---|
| Model | データ構造、永続化、ビジネスルール | Eloquent モデル、JPA エンティティ、Active Record |
| View | 表示、UI レンダリング | Blade / Thymeleaf / JSP / HTML テンプレート |
| Controller | 入力受付、Model 操作、View 選択 | Laravel Controller、Spring @Controller |
情報の流れ (Web MVC の典型)
[ブラウザ]
↓ HTTP リクエスト (例: GET /users/1)
[ルーター]
↓
[Controller] ← ① 入力を受け取る
↓ Model に問い合わせ
[Model] ← ② DB アクセス / ロジック
↑ データを返す
[Controller] ← ③ View を選んでデータを渡す
↓
[View] ← ④ HTML をレンダリング
↓ HTTP レスポンス
[ブラウザ]
各層の責務 (詳細)
Model の責務
- データの永続化(DB アクセス)
- ビジネスロジック / ドメインルール
- バリデーション(ドメインレベル)
- 状態を持つ(インスタンス変数)
- View や Controller を知らない(依存方向: Controller → Model)
View の責務
- 受け取ったデータを HTML / JSON / その他形式に整形
- 表示専用のロジック(フォーマット、ループ、条件分岐)
- ビジネスロジックを書かない(プレゼンテーションロジックのみ)
- Model に直接アクセスしない(Controller 経由で受け取る)
Controller の責務
- HTTP リクエストを受け取る
- 必要に応じて Model を呼び出す
- 結果を View に渡す
- ロジックを書きすぎない(Fat Controller アンチパターン)
Laravel での MVC 実装例
// Model: app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $fillable = ['name', 'email'];
// ドメインメソッド
public function isAdmin(): bool
{
return $this->role === 'admin';
}
}
// Controller: app/Http/Controllers/UserController.php
namespace App\Http\Controllers;
class UserController extends Controller
{
public function show(int $id)
{
// ① Model からデータ取得
$user = User::findOrFail($id);
// ② View を選んで渡す
return view('users.show', ['user' => $user]);
}
}
// View: resources/views/users/show.blade.php
{{ $user->name }}
{{ $user->email }}
@if ($user->isAdmin())
管理者
@endif
MVC が選ばれる代表的フレームワーク
| 言語 | フレームワーク | 登場年 |
|---|---|---|
| Ruby | Ruby on Rails | 2004 |
| PHP | Laravel / CodeIgniter / Symfony / CakePHP | 2011 / 2006 / 2005 / 2005 |
| Python | Django (MTV) / Flask | 2005 |
| Java | Spring MVC / Struts / Play | 2003 / 2000 |
| C# | ASP.NET MVC / ASP.NET Core MVC | 2009 |
| Node.js | Express + 自前 MVC / NestJS / Adonis | 2010〜 |
Django は厳密には MTV (Model-Template-View) を名乗りますが、Template=View、View=Controller と読み替えれば MVC と同じです。
MVC の派生パターン
| パターン | 特徴 | 主な用途 |
|---|---|---|
| MVC | Controller が View を選ぶ | サーバ Web アプリ |
| MVP (Presenter) | Presenter が View ↔ Model を仲介、View は受動 | Android (古典) / WinForms |
| MVVM (ViewModel) | 双方向データバインディングで自動同期 | WPF / Vue / Knockout / SwiftUI |
| MVI (Intent) | 単方向データフロー、状態を一元管理 | Redux / Flux / Compose |
| Clean / Onion | 依存方向を内側へ統一、層を増やす | 大規模 Enterprise |
現代の MVC: API + SPA への分離
近年はサーバが MVC でレンダリングする形より、サーバは JSON API、フロントは Vue/React/Angular で MVVM の構成が主流です:
[ブラウザ (React/Vue)]
├ View (コンポーネント)
└ ViewModel (state / store)
↑↓ JSON
[サーバ (Laravel/Spring)]
├ Controller (API エンドポイント)
├ Service (ビジネスロジック)
└ Model (DB アクセス)
↑↓
[DB]
Fat Controller アンチパターン
Controller にビジネスロジックを書きすぎると、テスト困難・再利用不能・肥大化します。Service 層やUseCaseに切り出します:
// ❌ Fat Controller
class OrderController extends Controller
{
public function store(Request $request)
{
// 200 行のロジック...
DB::beginTransaction();
$order = Order::create($request->only('items'));
foreach ($order->items as $item) {
$stock = Stock::find($item->product_id);
$stock->qty -= $item->qty;
$stock->save();
}
Mail::to($order->user)->send(new OrderCompleted($order));
// ...
}
}
// ✅ Service 層へ分離
class OrderController extends Controller
{
public function __construct(private OrderService $service) {}
public function store(StoreOrderRequest $request)
{
$order = $this->service->place($request->validated());
return redirect()->route('orders.show', $order);
}
}
class OrderService
{
public function place(array $data): Order
{
return DB::transaction(function () use ($data) {
$order = Order::create($data);
$this->reserveStock($order);
event(new OrderPlaced($order));
return $order;
});
}
}
MVC のメリット・デメリット
| メリット | デメリット |
|---|---|
| 関心の分離で保守性が向上 | 規模が小さいと過剰設計 |
| 並行開発しやすい(View 担当、Model 担当) | 3 層境界の判断に学習コスト |
| テスタビリティ(Model 単体テスト可) | Fat Controller / Fat Model に陥りやすい |
| フレームワーク化で標準化 | SPA 時代は Controller / View の境界が薄い |
FAQ
Q: MVC と MVP の最大の違いは?
A: MVC では View が Model を直接参照するケースがありますが、MVP では View は完全に受動で Presenter 経由でしか Model に触れません。
Q: SPA (React/Vue) では MVC は古い?
A: クライアント側は MVVM / Flux が主流。ただしサーバ側 API は依然として MVC が一般的です。「両側でアーキテクチャが違う」が現代の標準です。
Q: 小さなツールでも MVC を守るべき?
A: 小さければ 1 ファイルでも十分。チーム開発や 1000 行を超え始めたら層分離で得をします。