テスタブル設計(I/O境界の分離)30章アウトライン🌟🧪
第1章:はじめに(この講座のゴール)🎯😊
- ねらい:テスタブル設計=「怖くない変更」を作る感覚をつかむ✨
- 学ぶ:I/O境界の分離って何?どこが嬉しい?🧠
- ハンズオン:テストしにくいコードの例を“眺めて”つらさを体験😵💫
第2章:I/Oと副作用ってなに?⚡🚪
- ねらい:「I/O=外の世界」を言語化できるようにする
- 学ぶ:HTTP/DB/ファイル/時刻/乱数/環境変数/ログ…ぜんぶI/O寄り🌀
- ハンズオン:自分が書きがちな処理を「I/O」「ロジック」に分ける📝
第3章:テストしやすいってどういう状態?🧪✨
- ねらい:“テスト可能性”の条件を持つ
- 学ぶ:入力→出力が安定、外部依存が差し替え可能、実行が速い⚡
- ハンズオン:同じ処理を「テストしやすい版」に言い換えてみる🔁
第4章:「中心(ロジック)」と「外側(I/O)」モデル🏠➡️🌍
- ねらい:頭の中に設計の地図を作る
- 学ぶ:中心=純粋ロジック/外側=アダプタ、境界=インターフェース📌
- ハンズオン:図を描く練習(中心・外側・境界線)🖊️
第5章:Windows + VS Codeで“動く最小環境”を作る🪟💻
- ねらい:迷子にならない土台を作る
- 学ぶ:プロジェクト構成(TypeScript、実行、テストの置き場所)📁
- ハンズオン:空プロジェクトを作って「テストが走る」まで✅
第6章:テストランナー入門(まず1本通す)🧪🎉
- ねらい:成功体験で安心する
- 学ぶ:テストの実行・失敗の読み方・基本アサーション👀
- ハンズオン:超小さい純粋関数を作ってテストを書く✍️
第7章:テストの型(AAA)で迷わなくする📐🧪
- ねらい:毎回の書き方を固定して楽にする
- 学ぶ:Arrange/Act/Assert、命名、境界値テストの考え方🧠
- ハンズオン:同じ関数にテストケースを増やして慣れる📈
第8章:純粋関数の作り方(I/Oゼロの中心)🍰✨
- ねらい:中心を“きれい”にする技術
- 学ぶ:副作用を持たない、同じ入力なら同じ出力、例外の扱い方の基本
- ハンズオン:文字列整形・料金計算など“日常ネタ”で練習🍩💰
第9章:TypeScriptの型でテストを減らす🛡️📘
- ねらい:型を味方にする
- 学ぶ:型で表現できる不正を締め出す(ユニオン型、型ガードの感覚)✅
- ハンズオン:入力型を強くしてバグの入口を塞ぐ🚧
第10章:「テストしにくい臭い」カタログ👃💨
- ねらい:リファクタ対象を見つけられるようにする
- 学ぶ:関数の奥で
new、直Date、直fetch、直process.env、巨大関数…😱 - ハンズオン:臭いポイントに赤ペン入れて「何を境界にする?」を言語化🖍️
第11章:境界線の引き方(判断軸だけ覚える)✂️🧠
- ねらい:境界の“引き方”を持つ
- 学ぶ:変更理由の違いで分ける、外部都合を中心に入れない🚪
- ハンズオン:同じ題材に3つ線引きして比較🔁
第12章:分離の基本手順(押し出す→薄くする)🧹➡️🧩
- ねらい:安全に分離する手順を身につける
- 学ぶ:①中心抽出→②I/Oを外へ→③境界をinterface化→④テスト追加
- ハンズオン:小さな“最悪コード”を段階的に改善する🛠️
第13章:依存を外から渡す(引数注入)🎁➡️
- ねらい:差し替え可能にする最短ルート
- 学ぶ:関数引数で依存を渡す、中心は依存を作らない🙅♀️
- ハンズオン:Clock/Loggerを引数で受け取る版に変える⏰📝
第14章:コンストラクタ注入&合成の置き場(組み立て場所)🏗️🧱
- ねらい:アプリの“組み立て係”を作る
- 学ぶ:中心は薄い依存、外側で実体を組み立てる(Composition Root)📌
- ハンズオン:main側で依存を組んで中心に渡す✅
第15章:interfaceは“最小の約束”にする📜✨
- ねらい:巨大interface地獄を回避
- 学ぶ:必要な操作だけ、I/Oの詳細を漏らさない🚫
- ハンズオン:HTTP/DBのinterfaceを“最小化”する練習✂️
第16章:テストダブル入門(スタブ/モック/スパイ)🧸👀
- ねらい:差し替えテストの道具を覚える
- 学ぶ:スタブ=返す、スパイ=記録、モック=期待を確認
- ハンズオン:通知送信を“送ったことにする”テスト📩😆
第17章:時刻(Clock)を分離する⏰🧊
- ねらい:時間バグを消す
- 学ぶ:期限判定・日跨ぎ・タイムゾーン事故の入口
- ハンズオン:Clockを注入して“時間を止める”テストを書く🧪
第18章:乱数(Random)を分離する🎲🎯
- ねらい:再現性のあるテストにする
- 学ぶ:乱数直書きが不安定の原因
- ハンズオン:固定乱数でくじ引きロジックを検証🎁
第19章:ファイルI/Oを外に押し出す📁🚪
- ねらい:読み書きと計算を分ける
- 学ぶ:中心=解析/集計、外側=読み込み/保存
- ハンズオン:CSVっぽい入力→集計ロジックを中心へ📊
第20章:HTTPアクセスを外に押し出す🌐🧩
- ねらい:API変更に強くする
- 学ぶ:Client interface + Adapter、レスポンス変換は境界で
- ハンズオン:API結果を“ドメイン型”に変換して中心へ✨
第21章:DB/永続化を外に押し出す🗄️🧩
- ねらい:永続化都合でロジックを汚さない
- 学ぶ:Repositoryの最小操作、中心はDBを知らない🙈
- ハンズオン:保存/取得を差し替え可能にして中心テストを高速化⚡
第22章:設定・環境変数を外に押し出す⚙️📦
- ねらい:環境差で壊れない設計
- 学ぶ:設定はConfigとして注入、中心は
process.envを触らない🙅♀️ - ハンズオン:テストでConfigを差し替えて分岐を検証✅
第23章:境界でデータ変換(DTO ↔ Domain)🔁✨
- ねらい:外の形を中心に持ち込まない
- 学ぶ:命名・単位・欠損値・nullの吸収、変換の置き場
- ハンズオン:外部DTOを“きれいな型”に直して中心へ💎
第24章:入力検証と不変条件(入口で守る)🚧🛡️
- ねらい:中心に“壊れたデータ”を入れない
- 学ぶ:入口でチェック、中心は前提を信頼する設計
- ハンズオン:不正入力が来たときの挙動をテストで固定📌
第25章:エラー設計(ドメイン vs インフラ)😇🚨
- ねらい:例外が暴れない世界へ
- 学ぶ:ドメインエラー(仕様の失敗)/インフラエラー(外部都合)
- ハンズオン:失敗の種類を分類して、中心が扱う形を決める🧠
第26章:境界でエラー変換(例外→結果、結果→表示)🔁🧯
- ねらい:「境界で変換する」一点突破
- 学ぶ:外側の例外を中心の扱いやすい形へ、逆に表示用へ
- ハンズオン:HTTP失敗→中心の結果→UI/CLI表示、を一本につなぐ🔗
第27章:テストの粒度(ユニット/結合)と基本方針🍱🧪
- ねらい:どこを何で守るか迷わない
- 学ぶ:中心=ユニットで速く、外側=最小限の結合で確認🔌
- ハンズオン:同じ機能を「中心テスト」「結合テスト」両方で作る🙂
第28章:観測(ログ)もI/O!テスタブルにする📈📝
- ねらい:あとで調査できる&テストも壊れない
- 学ぶ:Loggerを注入、重要イベントだけ出す、テストではスパイで検証👀
- ハンズオン:「失敗理由が追えるログ」を設計してテストする🕵️♀️
第29章:AI拡張と上手に進める(丸投げしないコツ)🤖🎀
-
ねらい:AIで速くなるけど設計は自分が握る
-
学ぶ:AIに頼るところ(テストケース列挙、モック下書き、命名案)📝 逆に頼らないところ(境界判断・要件解釈の丸投げ)🙅♀️
-
ハンズオン:
- 良いプロンプト例(ケース洗い出し)
- ダメ回答の見抜き方(責務が混ざる、境界が曖昧)👁️
第30章:ミニプロジェクト(集大成)🎓🌈
-
ねらい:現実っぽい形で「中心と外側」を完成させる
-
題材例:注文(合計/割引/在庫チェック)🛒🍕(難しすぎないやつ)
-
進め方(章内で3ステップに分けてやる)✨
- 設計:境界図・依存の向き・interface決定🗺️
- 中心実装:純粋ロジック + ユニットテスト🧪
- 外側接続:HTTP/DB/設定/ログのアダプタ + 最小の結合テスト🔌
-
成果物:中心が“ほぼユニットテストだけで守れる”構造🎯