メインコンテンツまでスキップ

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 で“勝手に変えない”宣言🧊
  • 演習:UserIdCurrency を型で表現してみる🪪💴

第6章 TypeScriptで作る「静的な契約」②:unknownを安全にする🧼🧠

  • 外から来た値は unknown で受けるのが安全🌍
  • 型ガードで安全に変換してから使う🔁
  • 演習:unknownstring にしてから処理する🚦

第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章それぞれに「学習目標🎯」「想定時間⏱️」「章末チェックリスト✅」「演習問題🧪」も付けて、教材ページとして完成形に近づけられます🙂✨