第3章 失敗例①:直接import&直叩きがつらい😣📦
この章は「DIって必要なの?」の答えを、わざとツラい例で体感する回だよ〜💉✨ (次章以降で、ちゃんと“ラクにする方法”を作っていくから安心してね🥹🌸)
この章のゴール🎯💖
- 「直接import&直叩き」が、なぜ差し替え不能になるのか説明できる🗣️
- テストで起きる「え、モックできない…」の原因がわかる🧪💥
- 「困ったポイント」をコード上で発見して、印を付けられる🔎🟥
1) まず“つらい例”を見よう😣📦
たとえば「ユーザーにウェルカムメール送る」みたいな処理✉️✨ (※あえて“悪い書き方”)
// src/features/welcome/sendWelcome.ts
import { sendMail } from "../../infra/mailer"; // 直接import(固定)
import { getUserById } from "../../infra/db"; // 直接import(固定)
import { format } from "../../infra/dateFormat"; // 直接import(固定)
export async function sendWelcome(userId: string) {
const user = await getUserById(userId); // DB直叩き
const body = `ようこそ! ${format(new Date())}`; // 日付直叩き(間接的に環境依存)
await sendMail(user.email, "Welcome!", body); // メール送信直叩き
}
一見「普通に動く」んだけど…ここからが地獄の入口😇🔥
2) 何がつらいの?(壊れ方ベスト4)🧨

つらい①:差し替えできない(本番固定)🔒
sendMailが本物固定だと、テストでメール送っちゃう💌💥getUserByIdが本物固定だと、テストでDBを触っちゃう🗄️💥- “外部I/O”が混ざると、テストが遅い・不安定・準備だるいの三重苦😵💫
つらい②:テストでモックしにくい(特にESM)🧪⚠️
ES Modules(import ... from)は、importが先に評価される性質があるから、
「あとから差し替え(モック)したい」がやりにくいことがあるよ🥲
- Jestは、ESMでは
jest.mockがそのまま効かないケースがあって、dynamic import や別の手順が必要って明記されてるよ📌 (Jest) - Vitestも、static import は hoist される(importが先に動く)前提があって、モックの書き方に制約が出ることがあるよ📌 (Vitest)
つまり、「直接importで固定」が増えるほど、テストが“ツールのクセ勝負”になりがち😣🌀
つらい③:環境差(Node/ブラウザ)で詰む🪤🌐
直接importで fs とか localStorage とかを握りしめると、環境が変わった瞬間に崩れる💥
さらに、TypeScriptの moduleResolution は Nodeの解決ルール(ESM/CJS)に合わせた設定が重要で、ここを甘く見ると「動くはずが動かない」が起きやすいよ⚙️😵 (TypeScript)
つらい④:循環import(circular dependency)で“undefined事故”🌀😱
「便利だから index.ts(barrel)経由でimportしよ〜」をやると、 循環参照が混ざったときに runtime で undefined になったりする😭
index.ts経由の自動importが循環参照を生みやすい、って話も出てるよ📌 (GitHub)- barrel(index.tsで再export)自体が循環の温床になりやすい、という注意喚起も多いよ📌 (TkDodo)
“直接import多用”は、依存関係が絡まったときの爆発力が高いの…💣🌀
3) “ツラさ”を見える化するコツ🧠✨
次の3つを見つけたら、そこに 🟥 外部! ってコメントを付けてね👇
fetch/localStorage/process.env/Date/Math.random/consoleみたいな 環境依存- DB・メール・ファイル・ネットワークみたいな I/O
- 直接importしていて 差し替えたいのに差し替えられないやつ
4) ミニ課題📝💖(10〜15分)
ミニ課題A:🟥スタンプ付け職人になろう
さっきの“悪い例”に、コメントを足してみてね👇
// 🟥 外部!(DB)
// 🟥 外部!(メール)
// 🟥 外部!(時間/日付)
// 🟥 外部!(環境差の可能性)
ミニ課題B:テスト視点で「困ること」を3つ書く🧪
例:
- 「メール送信を止めたい」
- 「DBアクセスをFakeにしたい」
- 「日付を固定したい」
5) AIにお願いするなら🤖✨(超使える!)
Copilot/Codexにこう投げると、次章につながるリファクタ案が出やすいよ🌸
- 「この関数の外部依存(DB/メール/日付)を列挙して、差し替え可能な形にしたい」
- 「直接importを減らして、依存を引数で受け取る形(deps注入)に分解して」
- 「テストが書きやすいように、I/Oと純粋ロジックを分離して」
まとめ🎀🏁
- 直接import&直叩きは、動くけど差し替え不能になりやすい😣📦
- ESMの性質(importが先に評価される)で、モックが難しくなることがある🧪⚠️ (Jest)
- barrelや循環importで、undefined事故が起きやすい🌀😱 (GitHub)
次の章(第4章)では、似た“固定化地獄”の代表 「new直書き」 をやっつけるよ〜🧱🔨✨