第1章 CQRSってなに?最短でわかる入口🚪✨
この章は「CQRSの“雰囲気”をつかむ」がゴールだよ😊 むずかしい単語が出てきても、今日はぜんぶ完璧に覚えなくてOK!「なるほど、こういう分け方なんだ〜」って思えれば勝ち🏆✨
1) CQRSを一言でいうと?📌

CQRS = “更新するもの(Command)” と “見るだけのもの(Query)” を分けようねっていう考え方だよ🧠✨ 正式には Command Query Responsibility Segregation(コマンド/クエリ責任分離)って呼ばれるよ。(martinfowler.com)
- Command(更新):状態を変える(=副作用あり)🔧 例)注文する、支払う、キャンセルする、住所を変更する…など
- Query(参照):見るだけ(=副作用なし)👀 例)注文一覧を見る、売上集計を見る、在庫を確認する…など
ポイント:「変える」か「見る」かだけでまず判定できる👍✨
2) なんで分けるの?(雑に混ぜると起きがちなこと)😵💫
システムが育つと、だんだんこんなことが起きやすいの👇
- 一覧表示を直しただけなのに、更新ロジックまで壊れた💥
- 「集計を速くしたい」けど、更新と絡みすぎて触れない🙈
- テストがしんどい(参照のはずがDB更新してたり)🧪💦
CQRSは、“見る”と“変える”の役割を分けて、変更しやすくしたり、表示を速くしたりしやすくする考え方だよ🚀✨(Microsoft Learn)
ただし!CQRSは強いけど、複雑さも増えるから、何でもかんでも採用すれば良いわけじゃないよ(ここ大事)⚠️ 「多くのシステムでは複雑さがリスクになる」って注意も有名👍(martinfowler.com)
3) Command / Query を一瞬で見分けるコツ👓✨
迷ったら、この3つの質問でOK😊
✅ 質問A:データが変わる?
- 変わる → Command 🔧
- 変わらない → Query 👀
✅ 質問B:副作用がある?(保存・送信・課金・通知など)
- ある → Command 🔥
- ない → Query 🧼
✅ 質問C:名前が「〜する」?
- 「注文する」「支払う」みたいな動詞 → Commandっぽい
- 「取得する」「一覧を見る」 → Queryっぽい
4) よくある誤解:CQRS = イベント駆動?イベントソーシング?🤔
ここ、初心者が混乱しやすいところ!💡
- CQRSは“必ずイベントが必要”ではないよ🙆♀️
- ただ、現場では「CQRS + イベント(非同期投影)」みたいにセットで語られがちだから、そう見えるだけ👍
「CQRS自体はイベント必須じゃない」って説明もあるよ📚(martinfowler.com)
5) 身近な例でつかむ:学食モバイル注文🍙📱
たとえば学食アプリだと👇
🔧 Command(更新)
- 注文する
- 支払う
- 注文をキャンセルする
- メニューを追加する(管理画面)
👀 Query(参照)
- 今日のメニューを見る
- 注文一覧を見る
- 売上集計を見る
- 人気メニューTOP3を見る
「注文する」は世界が変わるけど、「注文一覧を見る」は世界は変わらない、って感じ😊✨
6) ミニ演習:Command?Query?どっちゲーム🗂️🎮
次の10個を Command / Query に分けてみてね✨(直感でOK!)
- 注文する
- 注文一覧を表示する
- 住所を変更する
- 今日の売上合計を見る
- ログインする
- メニューの価格を変更する
- 注文のステータス(準備中/受け取り済み)を見る
- お気に入りメニューに追加する
- 人気メニューTOP3を見る
- レシートを再発行する(PDFを作る)
✅ こたえ(理由つき)🎯
- Command(注文が作られる)
- Query(見るだけ)
- Command(情報が変わる)
- Query(集計を見るだけ)
- だいたいCommand(ログイン状態・セッションが変わることが多い)
- Command(価格が変わる)
- Query(見るだけ)
- Command(お気に入りが増える)
- Query(見るだけ)
- ⚠️迷いどころ:
- 「PDFを生成して保存する」ならCommand
- 「すでにあるPDFを取得して表示」ならQuery → “世界が変わるか”で判定すると強い💪✨
7) 超ミニのTypeScript例(雰囲気だけつかむ)✍️✨
「更新」と「参照」を関数レベルで分けるだけでも、もうCQRSの入り口だよ🚪✨
// ✅ Command(更新): 注文する(状態が変わる)
type PlaceOrderCommand = {
userId: string;
menuId: string;
qty: number;
};
// ✅ Query(参照): 注文一覧を取る(状態は変えない)
type GetOrderListQuery = {
userId: string;
};
type OrderListItem = {
orderId: string;
menuName: string;
qty: number;
status: "ORDERED" | "PAID";
};
// --- Command側 ---
async function placeOrder(cmd: PlaceOrderCommand): Promise<{ orderId: string }> {
// ここでは「保存する」「状態を作る」みたいなことが起きる想定(副作用あり)
// 例: DBにinsert、在庫を減らす、など
return { orderId: "ORD-123" };
}
// --- Query側 ---
async function getOrderList(q: GetOrderListQuery): Promise<OrderListItem[]> {
// ここは「読むだけ」(副作用なし)
return [
{ orderId: "ORD-123", menuName: "唐揚げ定食", qty: 1, status: "ORDERED" },
];
}
ここでの大事ポイント🌟
- Commandは「やる」(世界を変える)
- Queryは「見る」(世界を変えない)
- 関数を分けただけでも、頭の中が整理されてくるよ😊✨
8) AI活用コーナー🤖💬(例を10個出して分類させる😆)
そのままコピペで使えるよ👇✨
✅ プロンプト例1:分類してもらう🗂️
「学食モバイル注文アプリ」で起きる操作を10個考えて、 各操作を Command / Query に分類して、理由を1行で書いて。
✅ プロンプト例2:わざと間違わせてツッコむ😈👉😆
次の操作を Command / Query に分類して。 ただし自信がなくても必ず答えて。 (答えた後で、間違いそうなものだけ“なぜ迷うか”も書いて)
👉 AIが迷った場所こそ、あなたの理解ポイントが育つ場所🌱✨
✅ プロンプト例3:命名の練習🧾
CommandとQueryの名前を、英語の関数名で10個提案して。 例:PlaceOrder, GetOrderList みたいな感じ。
9) まとめ🎀
- CQRSは 「更新(Command)」と「参照(Query)」を分ける考え方😊✨(martinfowler.com)
- まずは「世界が変わる?」で判定すると迷いにくい👓
- CQRSは強いけど、複雑さも増えるから“使いどころ”が大事⚠️(martinfowler.com)
- CQRSはイベント必須じゃない(混同しなくてOK)🙆♀️(martinfowler.com)
おまけ:いまのTypeScript/Nodeの“最新感”メモ🧁✨
- TypeScriptは 5.9 が現行系列として案内されてるよ🧠(Microsoft for Developers)
- Node.js は v24 が Active LTS、v25 が Current(最新系列)として更新されてるよ🔧(Node.js)
(※この章では“知ってると安心”程度でOK!次章以降で手を動かしていくよ😊)
次の第2章は、題材の「学食モバイル注文」を固定して、迷子にならない地図を作るよ🧭✨ 続けて第2章もこのテンションで作る?🍙📱💕