Design by Contract(DbC)入門(TypeScript)詳細アウトライン(全25章)📘✨
対象:TypeScript初級〜中級/DbCは初めて/設計は超入門者🙂 環境:Windows🪟+VS Code💻(AI支援:Copilot / Codex 等🤖OK)
第1章 DbCってなに?「約束」でバグを入口で止める🤝🛑
- DbCの目的:壊れた値を中に入れない🚪
- 3点セット:事前条件・事後条件・不変条件🧩
- 「コメント」より「実行される約束」📝➡️✅
- ミニ例(雰囲気):契約がない関数がどう壊れるか😵💫
第2章 超ミニ体験:契約あり/なしで読みやすさが激変🧪✨
divide(a,b)を例に、契約なし→ありへ🔁- “失敗の仕方”が読みやすいとデバッグが楽になる🔦
- 演習:入力チェックとエラーメッセージを入れてみる✍️
第3章 用語をやさしく:事前・事後・不変ってこういう意味📚🙂
- 事前条件=入力の約束📥
- 事後条件=結果の約束📤
- 不変条件=いつでも守るルール🧱
- 「ガード節」との関係(似てるけど目的が違う)🚧
第4章 DbCは“設計のど真ん中”にある(他トピックとのつながり)🧠🔗
- SoC:契約は境界で強く、内部は軽く⚖️
- テスタブル設計:契約はテストと相性抜群🧪
- エラーモデリング:契約違反は扱いを分ける🧾
- 依存関係ルール:契約で境界が崩れにくくなる🧱
第5章 TypeScriptで作る「静的な契約」①:型で守れる範囲🧷✅
string | null/ union / literal type で「ありえる値」を狭める🎯readonlyで“勝手に変えない”宣言🧊- 演習:
UserIdやCurrencyを型で表現してみる🪪💴
第6章 TypeScriptで作る「静的な契約」②:unknownを安全にする🧼🧠
- 外から来た値は
unknownで受けるのが安全🌍 - 型ガードで安全に変換してから使う🔁
- 演習:
unknownをstringにしてから処理する🚦
第7章 型だけでは守れない契約:実行時チェックが必要な理由🌍🛡️
- 型は“コンパイル時”、値は“実行時”⚡
- 例:数値の範囲、文字数、整合性(合計が一致など)📏
- 「型+実行時チェック」の二刀流が最強⚔️
第8章 事前条件(Precondition)入門:入口で止める🚪✅
- 入口チェックの基本(null/空/範囲/形式)🧱
- どこでチェックする?(public境界が基本)📌
- 演習:
transfer(amount)に事前条件を入れる💸
第9章 事前条件の書き方:読みやすいチェック順とメッセージ📝✨
- 「軽いチェック→重いチェック」の順で書く🔽
- エラーメッセージは“直し方が分かる”内容に🧭
- 演習:悪いメッセージ→良いメッセージへ改善🔧
第10章 事後条件(Postcondition)入門:結果の品質を保証🎁✅
- 「成功したなら必ずこうなる」を言い切る🗣️
- 戻り値の保証/副作用の保証(残高が減った等)📤
- 演習:ポイント付与で「合計が増える」を保証🎫⬆️
第11章 事後条件の実務コツ:整合性・単位・丸めの事故を防ぐ📏🧮
- 金額・税・丸めのよくある事故💥
- “期待する整合性”を式で表す✅
- 演習:
total = subtotal + taxを必ず守る💴➕
第12章 不変条件(Invariant)入門:壊れない中心を作る🧱✨
- “無効な状態を作らない”が最強の防御🚫
- 不変条件は散らすと破れる→1か所に集める📌
- 演習:
Money(0以上、通貨必須)を作る💴🧱
第13章 不変条件の配置:コンストラクタ/ファクトリで確定させる🏗️✅
- 生成時に不変条件を確定(作れた=正しい状態)✨
newを隠してcreate()を使う発想🏭- 演習:
Email.create(text)のように作る📩
第14章 更新で不変条件を守る:setter地獄を避ける🔁🚫
- setterを増やすと「どこで壊れた?」になりやすい😵
- 更新メソッドでまとめて守る(例:
changePrice())🧰 - 演習:更新メソッドで必ず検証する🔒
第15章 契約はどこに置く?境界(Boundary)設計が9割🚧🧭
- public API/外部入力で強く守る🌐
- internalは「前提を信頼」して軽くする🏃♀️
- “入口は厳しく、中はスムーズ”の設計ルール🚪➡️✨
第16章 薄いアダプタと中心ロジック:SoCで契約がスッキリ🧼🧠
- 入力変換(DTO)とドメイン(中心)を分ける🔀
- 中心ロジックは“純度”を上げるとテストしやすい🧪
- 演習:パース担当と計算担当を分離する🧩
第17章 契約違反はどう扱う?まずはエラーの分類🧾🧠
- 契約違反:プログラミングミス寄り🧨
- ドメインエラー:仕様として起きる失敗(残高不足など)📉
- インフラエラー:通信・DB・タイムアウトなど🌩️
- 演習:例を分類してみる(クイズ形式)🎲
第18章 throw vs Result:設計の選び方(迷ったらここ)⚖️🎁
- 契約違反は
throwが相性よいことが多い💥 - 仕様として起きる失敗は
Resultが読みやすい📦 - 演習:同じ処理を
throw版/Result版で比較🔁
第19章 “境界で変換する”:内部エラーを外に漏らさない🧱🔁
- 内部の詳細(例:DB例外)をそのまま返さない🙅♀️
- 境界で「ユーザー向け」「ログ向け」を分ける🧾📊
- 演習:エラー変換の小さな関数を作る🔧
第20章 アサーション関数入門:読みやすい契約を関数化🧩📝
assertNonEmptyStringみたいに“意図の名前”をつける✨- コピペチェック地獄から脱出🏃♀️
- 演習:3種類のアサーションを作る(空、範囲、形式)✅
第21章 asserts を使って「型」も一緒に守る🛡️🧠
- アサーションで型推論が効くと安全&読みやすい✨
unknown→安全な型へ変換する流れ🔁- 演習:
assertIsUser(input)を作る👤✅
第22章 外部入力はZodで守る①:Validationで弾く🧱✅
- JSON/フォームは“型が効かない世界”🌍
- Zodでチェック→通ったら安心して使える🎯
- 演習:
CreateUserRequestをZodで受ける📨👤
第23章 外部入力はZodで守る②:ドメイン型へ変換(翻訳)🗣️🔁
- “通ったデータ”をそのまま使わず、ドメイン型にする🧱
- 命名・単位・欠損値を吸収して中心を守る🛡️
- 演習:DTO→
Email/UserIdへ変換する🏭
第24章 DbC×テスト:契約を「壊れない仕組み」にする🧪🔒
- 正常系テスト=約束が守れること🙂
- 契約違反テスト=壊れた入力を確実に止める🛑
- 境界値(0/空/最大)をセットで固める🍎📏
- 演習:1機能に「正常+契約違反」両方のテストを書く✍️
第25章 総合ミニプロジェクト:契約で守る“小さな予約システム”📅🚀
-
目的:型+実行時チェック+テストを1本につなぐ🔗
-
要件例:
- 予約作成:日付は未来、人数は1以上🧍♀️
- キャンセル:既にキャンセル済みは不可🚫
- 一覧:重複なし、並び順保証📈
-
作るもの:
- 契約一覧(事前/事後/不変)📘
- 境界(Zod)+ドメイン型(Money/Email等)🧱
- テスト(正常+契約違反+境界値)🧪🔒
-
AI活用ポイント🤖:
- 雛形生成(テスト骨格、Zodスキーマ)⚡
- でも「不変条件の決定」は人間が責任持つ⚖️
章の流れ(迷ったらこの順)🧭✨
- まず:1〜3章で“概念を体感”🙂
- 次に:5〜14章で“契約3点セットを手で書く”✍️
- その次:15〜19章で“境界とエラーを設計できるようにする”🚧
- 最後:20〜25章で“道具化(asserts/Zod/テスト)→実務へ”🧰🚀
必要なら、この25章それぞれに「学習目標🎯」「想定時間⏱️」「章末チェックリスト✅」「演習問題🧪」も付けて、教材ページとして完成形に近づけられます🙂✨