第6章:Entityの芯=更新の入口を絞って“壊れない”設計 🧱🪪✨
この章のゴールはこれだよ〜😊💡 **「Entityは変わるけど、ルールを破って壊れない」**ように、更新の入口(=メソッド)をちゃんと用意できるようになること!🚪🔒✨
1) まず結論:Entityは「直接いじらせない」が基本だよ🚫✋
Entityって「時間と一緒に変化する」存在だよね⏳ でも、どこからでも自由に書き換え可能だと…😇
- ルールを通らずに値が変わる😱
- バグが出ても原因が追えない😵💫
- “ありえない状態”が作れちゃう💥
だから、設計のコツはこれ👇 ✅ フィールドを直接書き換えさせず、更新メソッドに集める 🧠✨
2) 今日の題材:ミニ注文(Order)でいくよ🛒🍰
第6章でやりたいのは「更新イベント」を整理することだったよね😊📝 Orderなら、たとえばこんな感じ👇
- 注文を確定する(submit)📨
- 支払う(pay)💳
- キャンセルする(cancel)🧯
この“動詞”がそのまま、**更新の入口(メソッド)**になるよ〜🚪✨
3) ダメな例:なんでも直接いじれるOrder 😇🔥
「とりあえず動く」けど、あとで泣きがちパターン😭
type OrderStatus = "Draft" | "Submitted" | "Paid" | "Cancelled";
class OrderBad {
id: string;
status: OrderStatus = "Draft";
paidAt: Date | null = null;
constructor(id: string) {
this.id = id;
}
}
const o = new OrderBad("o-1");
// どこからでも勝手に…😱
o.status = "Paid";
o.paidAt = null; // 支払い済みなのに支払日時が無い!?💥
こういうのが起きると、あとから「え、なんで?」ってなるの🥲 “更新ルール”がコードに残ってないからだよ〜。
4) 良い例:更新の入口を「メソッド」に集めるOrder 🧱✨
💡ポイント
- 状態(status)を外から直接変えられないようにする🔒
- 変更は
submit()/pay()/cancel()だけにする🚪 - その入口でルール(ガード条件)をチェックする✅
ここで、より強いカプセル化として # を使う方法を見せるね😊
# のプライベート要素は JSの実行時にも守られるタイプだよ🔐(TypeScriptの private より“ガチ”)✨ (TypeScript)
type OrderStatus = "Draft" | "Submitted" | "Paid" | "Cancelled";
class DomainError extends Error {
constructor(message: string) {
super(message);
this.name = "DomainError";
}
}
export class Order {
readonly id: string;
#status: OrderStatus = "Draft";
#paidAt: Date | null = null;
#cancelledAt: Date | null = null;
constructor(id: string) {
this.id = id;
}
// 読み取りはOK👌(でも書き換えはNG🙅♀️)
get status(): OrderStatus {
return this.#status;
}
get paidAt(): Date | null {
return this.#paidAt;
}
get cancelledAt(): Date | null {
return this.#cancelledAt;
}
submit(): void {
if (this.#status !== "Draft") {
throw new DomainError("Draftのときだけ注文確定できるよ📨");
}
this.#status = "Submitted";
}
pay(paidAt: Date = new Date()): void {
if (this.#status !== "Submitted") {
throw new DomainError("確定済み(Submitted)のときだけ支払えるよ💳");
}
this.#status = "Paid";
this.#paidAt = paidAt;
}
cancel(cancelledAt: Date = new Date()): void {
if (this.#status === "Paid") {
throw new DomainError("支払い後はキャンセルできないよ🙅♀️💥");
}
if (this.#status === "Cancelled") {
throw new DomainError("すでにキャンセル済みだよ🧯");
}
this.#status = "Cancelled";
this.#cancelledAt = cancelledAt;
}
}
}
🌟この設計のうれしさ
- “ありえない状態”が作れない(ルールを入口で守る)🛡️
- 変更理由がメソッド名に残る(submit/pay/cancel)🧠
- デバッグが一気にラクになる🔍✨
5) 図解イメージ:更新は「入口1本化」🚪✨

外の世界🌍
|
| ✅ submit() / pay() / cancel()
v
Order(Entity) 🪪
|
| 入口でルールチェック✅
v
状態が安全に変わる🔄✨
「勝手に書き換え」は通れないようにしておくのがコツだよ〜🔒😊
6) “更新メソッド”の作り方:初心者向けテンプレ💖
迷ったらこれでOK👇
✅ 1. メソッド名は「動詞」にする
changeEmail()✉️addItem()➕removeItem()➖
✅ 2. メソッドの最初に“ガード条件”
- 状態チェック🚦
- 範囲チェック📏
- nullチェック🧯
✅ 3. 成功したら状態を変える
- 状態変更はここだけ!🔁✨
7) ここも最新寄りTips:private と # どっち使う?🤔🔐
private:TypeScriptの型チェック上は守られる(でも実行時の強制力は弱め)#:JavaScriptの機能として実行時にもアクセス不可で、より隔離が強い🔒✨ (TypeScript)
学習用&小さなアプリなら private でも全然OK😊
「絶対に外から触らせたくない!」なら # が気持ちいいよ〜✨
8) テストして“壊れない”を確認しよ🧪🍰
「支払い後にキャンセルできない」をテストで守るよ💪✨ (Vitestは最近も4系が継続して更新されてるよ〜🧪 (Vitest))
import { describe, it, expect } from "vitest";
import { Order } from "./Order";
describe("Order", () => {
it("支払い後はキャンセルできない🧯", () => {
const o = new Order("o-1");
o.submit();
o.pay();
expect(() => o.cancel()).toThrowError();
});
it("Draftのまま pay はできない💳", () => {
const o = new Order("o-2");
expect(() => o.pay()).toThrowError();
});
});
9) 演習(やってみよ〜!)🎀📝
演習1:更新イベントを3つ書く✍️✨
Order以外でもOKだよ😊 例:サークル会計なら
collectFee()💰refund()🔁closeMonth()📅
演習2:禁止ルールを2つ入れる🚫
例:
- Cancelledのあとにsubmitできない
- Paidのあとにsubmitできない
演習3:テストを2本追加🧪
- “すでにCancelledならcancelできない”
- “Submittedじゃないとpayできない”
10) 小テスト(サクッと!)🎓✨
Q1. Entityを直接書き換えできると何が困る?😵💫 A. ルールを通らずに状態が変わって、ありえない状態が作れるから💥
Q2. 更新の入口を絞るって、具体的に何する?🚪 A. フィールドを隠して、変更は 動詞メソッドだけにする🔒✨
Q3. pay() の中で最初にやるべきことは?💳
A. ガード条件(状態チェック) 🚦✅
11) AIプロンプト集(Copilot/Codex向け)🤖💖
- 「Orderの状態遷移で、禁止すべきケースを10個列挙して。理由もつけて」🚦
- 「submit/pay/cancel のテストケースを境界値っぽく増やして」🧪
- 「このEntity、外から直接書き換えできそうな穴がないかレビューして」🔍
- 「メソッド名が“動詞”になってるかチェックして、改善案を出して」📝
12) まとめチェックリスト✅🌈
- フィールドを外から直接書き換えできない🔒
- 更新は“動詞メソッド”に集まってる🚪
- 入口でルール(ガード条件)を守ってる🛡️
- “ありえない状態”が作れないようになってる✨
- テストで禁止ルールを固定した🧪
おまけ:今日の「最新版メモ」📌✨(参考)
- TypeScript は 5.9 のリリースノートが公開・更新されてるよ🧡 (TypeScript)
- Node.js は v24 Krypton がActive LTSで、24.13.0 (LTS) のリリース情報も出てるよ🔐 (nodejs.org)
- VS Code は 1.108(リリース日 2026-01-08)、Insiders は 1.109 のノートが更新されてるよ🧰 (Visual Studio Code)
次の章(第7章)は「迷わないための判定フロー」だね🗺️✨ この第6章の内容を使って、**“更新イベント→入口メソッド”**の流れをチートシート化していこ〜😊💖