MVCはアーキテクチャにあらず

ソフトウェア開発の現場で「MVCアーキテクチャ」という言い方は根強いですが、厳密にはこれは誤解を招きます。MVC(Model-View-Controller)はアーキテクチャではなく、UI層の責務分割に関するデザインパターン、より正確には「インタラクション・パターン」です。本記事では、なぜMVCをアーキテクチャと呼ぶべきではないのか、そしてその誤解がもたらす設計上の問題、代わりに何を基準に全体設計を語るべきかを整理します。

なぜ「アーキテクチャ」ではないのか

  • アーキテクチャはシステム全体の構造と原則を指す
    例:レイヤードアーキテクチャ、ヘキサゴナル、クリーンアーキテクチャ、マイクロサービスなど。これらは境界、依存関係の方向、デプロイ単位、運用モデル、変更容易性まで含めて語ります。
  • MVCはUIの入出力と状態表示の分割方法
    Model/View/Controllerの責務を定義し、イベントの流れを整理するもの。データの永続化、ドメインの境界、外部システム連携、障害分離、スケール戦略など、アーキテクチャ上の主要関心事をカバーしません。

言い換えれば、MVCは「一部分の解」であって「全体設計」ではありません。

MVCが引き起こす誤解とアンチパターン

  • Fat Controller/Fat Model
    永続化、バリデーション、ドメインロジック、アプリケーションフローがControllerやModelに肥大化して集約。責務の境界が曖昧になり、テスト容易性が低下します。
  • レイヤー短絡(UI→DB直結)
    ViewやControllerから直接リポジトリやORMに触れることで、ユースケースの意図と副作用が混在。変更の波及が大きくなります。
  • プラットフォーム固有フレームワークへの過剰依存
    「MVCフレームワーク=アーキテクチャ」と誤認し、フレームワークの制約が設計の制約にすり替わる。

では何が「アーキテクチャ」なのか

  • 境界の定義
    ドメイン、アプリケーション、インフラの分離。依存方向は内向き(ドメインが最も安定)。ポート/アダプタで外界に接続します。
  • デプロイと運用の形
    モノリスかマイクロサービスか、同期/非同期通信か、スケール戦略、可用性要件、障害隔離。
  • 変更容易性とチーム境界
    コンウェイの法則を踏まえたモジュール分割、チームごとの認知負荷最適化。
  • 非機能要件の取り込み
    観測性、セキュリティ、パフォーマンス、データ整合性、トランザクション境界。

MVCの正しい位置づけ

  • UIレイヤー内部の実装パターンの1つ。
  • MVVM/MVP/MVIなどの代替と同列で、プラットフォーム特性(Web/モバイル/デスクトップ)や双方向データバインディングの有無で選択。
  • ユースケースやドメインと疎結合であるべき。UIはアプリケーションサービス(ユースケース)を呼び出し、結果を表示する。

シンプルな参照モデル

  • ドメイン層
    エンティティ、値オブジェクト、ドメインサービス、ドメインイベント。ビジネスルールの中心。フレームワーク非依存。
  • アプリケーション層
    ユースケース(アプリケーションサービス)。トランザクション境界、権限チェック、ワークフロー調整。ドメインをオーケストレーション。
  • インフラ層
    DB、メッセージング、外部API、ファイルシステム。ポート/アダプタを介して接続。
  • プレゼンテーション層
    ここでMVC/MVVM/MVP等を採用。入出力整形とイベントハンドリングに集中。

よくある疑問への回答

  • Q: RailsやSpring MVCはアーキテクチャでは?
    A: それらは強力なアプリケーションフレームワークですが、提供するのは主にプレゼンテーション層とインフラ統合のための仕組みです。アーキテクチャはあなたのシステム内でどのように境界を引き、依存を管理するかの選択の総体です。
  • Q: 小規模プロダクトでも分けるべき?
    A: 過剰設計は不要ですが、「UIがユースケースに依存し、ユースケースがドメインに依存する」最小限の依存方向だけは守ると、後の拡張コストが激減します。

実践ガイド(最小セット)

  1. ユースケースを関数として定義する
    • 入力DTO、出力DTOを定義。副作用はポート越しに。
  2. ポート/アダプタを導入
    • Repositoryや外部APIはインタフェース(ポート)で抽象化。実装(アダプタ)はインフラ層。
  3. UIはユースケースを呼ぶだけ
    • Controllerは入力のバリデーションとユースケース呼び出し、ViewModelへの変換に徹する。
  4. フレームワーク依存を端に寄せる
    • ドメインとユースケースからフレームワークを追い出す。テスタビリティ向上。
  5. 非機能要件の早期織り込み
    • トランザクション境界、監視、レート制限、リトライ/タイムアウトをアーキテクチャ決定に含める。

まとめ

  • MVCはアーキテクチャではなく、UIレイヤーのパターン。
  • アーキテクチャは境界と依存、デプロイ、非機能要件、チーム構造を含む総合設計。
  • 誤解を解くことで、Fat Controllerやレイヤー短絡を避け、変更に強いシステムを育てられます。
  • MVCは正しい位置に置けば強力。だが「全体設計」は別途、明示的に行いましょう。
Posted in

コメントを残す