多層アーキテクチャ MVC・MVVM・DDD
概要
- 日程: Day 3 / セッション 3
- 時間: [10:30-11:00]
- 形式: 座学
- ゴール: 3層アーキテクチャの各層の役割を、家計簿システム等の具体例を挙げて(条件)説明できる。MVCとMVVMの違い、DDDの主要概念(ドメイン、ドメイン層、ユビキタス言語、ドメインモデル)をそれぞれ一言ずつ言える(行動・基準)
- 学習形式: 対話型解説
導入(5分)
Day 2 で皆さんは、情報モデルの状態遷移から「機能」と「プレゼンテーション」を分離して抽出しました。
ここで少し考えてみてください。あの「分離」、世界中のエンジニアはどう呼んでいるでしょうか?
答えは「多層アーキテクチャ」です。皆さんがDay 2 でやったことは、業界標準の設計そのものでした。今日はその標準に正式な名前をつけ、語彙を業界共通のものにアップグレードします。
前のセッションで皆さんは設計アプローチを選び、根拠を言葉にしました。このセッションで学ぶ多層アーキテクチャは、選んだアプローチを実装の構造に落とすときの定番の型です。3層アーキテクチャ → MVC → MVVM → DDD の順に、粗い分離から洗練された分離へと進みます。
本編(20分)
1. 3層アーキテクチャ 分離の業界標準
3層アーキテクチャは、システムを役割の違う3つの層に分ける定番の型です。
これはレストランのようなものです。客席(見せる場所)・厨房(調理する場所)・食材庫(保存する場所)が分かれているから、メニュー改定でも厨房ごと作り直す必要がありません。
| 層 | 役割 | レストランなら | 家計簿システムなら |
|---|---|---|---|
| プレゼンテーション層 | 見せる・入力を受ける | 客席・メニュー | 支出一覧画面、入力フォーム |
| ロジック層 | 業務のルール・計算 | 厨房 | 月次集計、予算超過の判定 |
| データ層 | 保存する・取り出す | 食材庫 | 支出テーブルへの読み書き |
(画面・入力)"] -->|操作・入力| L["ロジック層
(業務ルール・計算)"] L -->|結果| P L -->|保存・取得の依頼| D["データ層
(DB読み書き)"] D -->|データ| L
大事なルールは「層をまたぐ会話は隣同士だけ」です。画面がDBに直接SQLを投げる構成は3層アーキテクチャに該当しません。一方、画面がロジック層に「今月の合計をください」と頼み、ロジック層がデータ層に取得を依頼する構成は該当します。なぜなら、前者は画面とDBが密結合になり、DBの変更が全画面に波及してしまうからです。
Day 2 の成果物と対応づけると、こうなります。
- プレゼンテーション一覧・ワイヤーフレーム → プレゼンテーション層
- 機能一覧(CRUD由来の機能) → ロジック層
- 情報モデル → データ層(明日、テーブル設計に変換します)
コード例・実例
「今月の食費合計を表示する」を、層の分離なし/ありで比べます。
// 分離なし: 画面のボタン処理にSQLも計算も混在(アンチパターン)
button.onclick = async () => {
const rows = await db.query("SELECT * FROM expenses"); // 画面がDB直叩き
let sum = 0;
for (const r of rows) if (r.category === "食費") sum += r.amount;
label.textContent = sum + "円";
};
// 分離あり: 画面はロジック層に頼むだけ
button.onclick = async () => {
const sum = await expenseService.monthlyTotal("食費"); // ロジック層
label.textContent = sum + "円";
};
分離ありの形なら、DBをファイル保存に替えても、画面のコードは1行も変わりません。
ここがポイント
- 3層の本質は「変更の影響範囲を層の中に閉じ込める」こと
- Day 2 の「機能とプレゼンテーションの分離」=プレゼンテーション層とロジック層の分離。皆さんはすでに実践者
- 明日のDay 4 実装は「プレゼンテーション層(UI)+ロジック/データ層(モックAPI)」という3層構成そのもの
コラム
3層アーキテクチャが広まった1990年代、その前の主流は「クライアント/サーバ2層」でした。画面アプリがDBに直接つなぐ構成です。業務ルールを変えるたびに、全社員のPCのアプリを入れ替えて回る必要があり、情報システム部門はフロッピーディスクを抱えて社内を行脚したそうです。「ロジックを真ん中の層に集めれば配り直さなくて済む」——3層アーキテクチャの普及の裏には、この行脚からの解放という切実な事情がありました。
2. MVCとMVVM プレゼンテーション層の中の分離
3層のうちプレゼンテーション層は、さらに内部を分けるのが定番です。その代表が MVC です。
- Model: 扱う情報とルール(例: 支出レコード、金額は0以上)
- View: 見せる部分(例: 支出一覧画面)
- Controller: 入力を受けてModelとViewを仲介(例: 「登録」ボタン→Modelの更新を指示)
(登録処理の仲介)"] C -->|更新指示| M["Model
(支出レコード)"] M -->|変更の通知| V["View
(支出一覧画面)"] V -->|表示| U
家計簿でいえば、Model=支出レコード、View=支出一覧画面、Controller=登録処理の仲介、という対応です。
MVVM はMVCの発展形で、Controllerの代わりに ViewModel を置きます。最大の特徴はデータバインディングです。これは、ViewとViewModelを自動同期の紐で結ぶ仕組みです。ViewModelの値が変わればViewが勝手に更新され、Viewの入力は勝手にViewModelへ反映されます。
MVCとMVVMの違いを一言でいうと、こうなります。
- MVC: Controllerが「Modelを更新しろ」「Viewを描け」と手続きで仲介する
- MVVM: ViewとViewModelがバインディングで自動同期され、仲介コードが激減する
「ボタンを押したらJSで label.textContent を書き換える」コードはMVVMのバインディングには該当しません。一方、Vue.jsの {{ total }} のようにデータを宣言的に結びつけて自動更新されるものは該当します。なぜなら、バインディングとは「同期処理を自分で書かないこと」だからです。
コード例・実例
同じ「合計金額の表示更新」をMVC風とMVVM風(Vue.js)で比べます。
// MVC風: Controllerが手続きで同期させる
class ExpenseController {
addExpense(amount) {
this.model.add(amount); // Modelを更新し、
this.view.renderTotal(this.model.total()); // Viewの描画を指示する
}
}
<!-- MVVM風 (Vue.js): バインディングが自動で同期する -->
<p>合計: {{ total }} 円</p>
<button @click="expenses.push({ amount: 500 })">追加</button>
<!-- total は expenses から自動計算され、画面も自動更新される -->
MVVM側には「Viewを更新せよ」というコードがどこにもない点に注目してください。
ここがポイント
- MVCもMVVMも「3層と対立する概念」ではなく、プレゼンテーション層の内部整理の型
- MVVMのデータバインディングは、React/Vue等の現代フレームワークの基盤概念。明日UIを作るときに再会する
- どちらが優れているかではなく、フレームワークがどちらの型を前提にしているかで決まることが多い
分からなくなったらAIに「MVCの登場人物を家計簿システムの登場人物に置き換えて」と質問してみましょう。自分のテーマに置き換えるのが最短の理解ルートです。
コラム
MVCの生みの親はノルウェーのトリグヴェ・リーンスカウグ。1979年、客員研究者として滞在したXerox PARC(マウスもGUIもここ生まれという伝説の研究所)で、Smalltalkのために考案しました。原型の名前は「Model-View-Controller-Editor」で、最初は「Thing-Model-View-Editor」というさらに素朴な名前だったそうです。「Thing(モノ)」が最終的に「Model」になったわけで、命名に苦労する姿は40年前の天才も同じだったようです。
3. DDD ドメインを中心に据える
最後は DDD(ドメイン駆動設計) です。主要概念は4つ。それぞれ一言で言えるようにしましょう。
- ドメイン: ソフトウェアが対象とする問題領域(例: 「家計の管理」という業務そのもの)
- ドメイン層: 業務ルールを集める層。3層のロジック層のうち「業務の本質」部分を独立させたもの
- ユビキタス言語: 開発者と業務側が同じ用語を使う共通言語(例: 「費目」と呼ぶと決めたら、会話でもコードでも「費目(category)」で統一)
- ドメインモデル: ドメインの概念と関係をモデル化したもの(例: 「支出は1つの費目に属する」を表現したモデル)
ここで気づいてほしいことがあります。ユビキタス言語、どこかで見覚えがありませんか?
そう、Day 1 で作った情報定義書です。「この情報を何と呼び、どういう意味か」をチーム(皆さんの場合は自分とAI)で統一する——情報定義書はユビキタス言語の辞書そのものです。そしてドメインモデルは、Day 2 の情報モデルとほぼ同じ役割です。皆さんはDDDの中心概念を、名前を知らないまま実践してきたことになります。
「DBのテーブル名はexpense、画面では『お小遣い帳の記録』、会話では『レシート』と呼ぶ」状態はユビキタス言語に該当しません。一方、「情報定義書で『支出』と定め、コードもAPIも会話も『支出(expense)』で通す」状態は該当します。なぜなら、ユビキタス言語の目的は「翻訳による誤解をなくすこと」だからです。
コード例・実例
ドメイン層のイメージです。業務ルール「予算超過の判定」がドメイン層に集まっています。
// ドメイン層: 「家計の管理」の業務ルールだけを持つ
class MonthlyBudget {
constructor(limit) { this.limit = limit; this.expenses = []; }
addExpense(expense) { this.expenses.push(expense); }
total() { return this.expenses.reduce((s, e) => s + e.amount, 0); }
isOverBudget() { return this.total() > this.limit; } // 業務ルール
}
// 画面もDBも登場しない。「家計の言葉」だけで書かれている点がドメイン層らしさ
このクラスには画面(View)もSQL(データ層)も出てきません。ユビキタス言語(予算・支出・超過)だけで書かれています。
ここがポイント
- DDDは「技術ではなくドメイン(業務)を設計の中心に据える」思想。前セッションの軸でいえば「ドメイン中心アプローチ」
- ユビキタス言語 ≒ 情報定義書、ドメインモデル ≒ 情報モデル。IAとDDDは「情報(業務の言葉)から始める」仲間
- DDDの全体は分厚い。今日は4概念を一言ずつ言えれば合格。深入りはAIと少しずつ
コラム
DDDを提唱したエリック・エヴァンスの著書(2003年)は、通称「エヴァンス本」。約560ページの大著で、「買ったが最後まで読めない技術書」の常連としても有名です。あまりに挫折者が多いため、世界中で入門書・要約本(『DDD Quickly』等)が出版されるという珍しい現象が起きました。それでも中心の主張はシンプルで、「ソフトウェアの複雑さと戦う武器は、業務を語る言葉そのものだ」ということ。皆さんが情報定義書で体験したことです。
💬 AIに聞いてみよう
- 「私の開発テーマ◯◯を3層アーキテクチャに分けると、各層には何が入りますか?機能一覧を貼るので割り当ててください」
- 「MVCとMVVMの違いを、データバインディングの有無に注目して、コード例つきで説明してください」
- 「私のDay1の情報定義書はDDDのユビキタス言語としてどこまで使えますか?足りない観点を指摘してください」
まとめ(5分)
今回学んだことを一言でまとめると「Day 2 でやった機能とプレゼンテーションの分離は、多層アーキテクチャという業界標準そのものであり、MVC/MVVM/DDDはその分離を洗練させた型である」です。
- 3層アーキテクチャ: プレゼンテーション・ロジック・データの分離。変更を層に閉じ込める
- MVC/MVVM: プレゼンテーション層の内部整理。MVVMはバインディングで自動同期
- DDD: ドメインを中心に据える思想。ユビキタス言語は情報定義書の親戚
次のセッションは演習です。「アーキテクチャ」「設計」「駆動」「アプローチ」「パターン」——今日大量に出てきたこれらの用語そのものを、Day 1 で学んだIAの手法(カードソーティング)で整理・分類します。IAが「設計知識」という情報にも効くことを確かめましょう。
🔄 振り返りチェック
- 3層アーキテクチャの各層の役割を、家計簿システムを例に言えますか?
- MVCとMVVMの違いを「データバインディング」という言葉を使って一言で言えますか?
- ユビキタス言語とは何か、自分のDay 1 の成果物と関連づけて説明できますか?
補足資料
- 参考リンク:
- 『エリック・エヴァンスのドメイン駆動設計』: DDDの原典(通称エヴァンス本)
- Martin Fowler「GUI Architectures」: MVC等のGUIパターンの歴史的整理
- 『Clean Architecture』(Robert C. Martin): 層の依存方向を突き詰めた発展形
- 発展課題:
- 使ったことのあるWebフレームワーク(Express、Ruby on Rails、Vue.js等)が、MVC/MVVMのどの型に近いかAIと調べてみましょう
- 自分の情報モデルの1つを「ドメイン層のクラス」としてJavaScriptで書き、業務ルールを1つメソッドにしてみましょう
学習ガイド
想定される質問と回答例
| 質問 | ヒント |
|---|---|
| 3層アーキテクチャとMVCは何が違うのですか? | 粒度が違う。3層はシステム全体の分離、MVCはそのうちプレゼンテーション層の内部の分離。対立ではなく入れ子の関係 |
| ModelとViewModelとドメインモデルは同じもの? | 全部別物なので注意。MVCのModelは「画面が扱う情報とルール」、ViewModelは「View専用に整形した状態」、ドメインモデルは「業務概念のモデル」。名前が似ているのは歴史の事故 |
| DDDは小さな個人開発でも使うべきですか? | フル装備は過剰なことが多い。ただしユビキタス言語(用語統一)とドメインモデルの意識だけは小規模でも効く。情報定義書を作った皆さんはすでに実践している |
| MVVMのデータバインディングは魔法に見えます。仕組みは? | フレームワークがデータの変更を検知(プロキシや監視)して再描画する。Day4でVue/React等に触れると具体像がつかめる。AIに「Vueのリアクティビティの仕組みを初心者向けに」と聞いてみよう |
つまずきやすいポイント
| つまずきポイント | ヒント |
|---|---|
| 「層」と「MVC」の関係が混ざる | 入れ子で覚える。システム全体=3層、そのプレゼンテーション層の中身=MVC/MVVM。地図の縮尺が違うだけ |
| MVCの矢印(誰が誰を呼ぶか)を暗記しようとして混乱する | 流派により矢印は微妙に違うので暗記は不毛。「入力はControllerへ、表示はViewが、情報とルールはModelが」という役割分担だけ押さえる |
| DDDの用語(ドメイン/ドメイン層/ドメインモデル)が区別できない | 「ドメイン=問題領域そのもの、ドメイン層=それをコードで置く場所、ドメインモデル=その表現物」。家計簿なら「家計管理/MonthlyBudgetクラスを置く層/支出と費目の関係図」 |
| ユビキタス言語を新しい特別な技術だと思ってしまう | 技術ではなく「用語統一の約束」。Day1の情報定義書がほぼそれ。自分の成果物と結びつければ一気に身近になる |