第3章:まずは嫌なコードを体験(newだらけ)😈🧱
この章はね、「DIPって何?」を頭で理解する前に、**“DIPが無いと何がつらいのか”**を体で感じる回だよ〜🧠➡️💢 いったんわざと「嫌なコード」を触って、変更が怖い理由をハッキリさせようね👀✨
ちなみに今の最新環境だと、.NET は **.NET 10(LTS)**が “latest” 扱いだよ(10.0.2 が 2026-01-13 時点の最新リリース)(Microsoft) 言語は C# 14 が最新で、.NET 10 SDK や Visual Studio 2026 系で試せるよ〜(Microsoft Learn)(でもこの章は基本構文だけでOK🙆♀️)
3.1 まずは「newだらけ」地獄コードを見てみよ〜😵💫🧱

今日のお題:ユーザー情報を取って表示する(よくあるやつ)📇✨
「ユーザーIDを渡すと、ユーザー名を返す」みたいな処理って、めっちゃよくあるよね🙂 で、悪い例ではこうなる👇
- 業務ロジック側のあちこちで
new SqlUserRepository()が出てくる💥 - さらに
new SmtpMailer()とかnew Logger()とかも散らばる💥💥 - 「どこを直せばいいの…?」ってなる👻
3.2 嫌なコード例(new が散らばる)🧨🧨🧨
下のコード、動くっちゃ動く。 でも「変更」に弱い…!それを体験しよう😈
例:Repository を直接 new しちゃう😵
// UserService.cs
public sealed class UserService
{
public string GetUserName(int userId)
{
// ❌ ここで具体クラスを new(しかも接続文字列まで直書き)
var repo = new SqlUserRepository(
connectionString: "Server=localhost;Database=AppDb;Trusted_Connection=True;");
var user = repo.FindById(userId);
// ❌ ついでにメール送信もここで new
var mailer = new SmtpMailer("smtp.example.com");
mailer.SendWelcomeIfFirstLogin(user);
return user.Name;
}
}
さらに別の場所でも new してたら…😇
// WeeklyReportJob.cs
public sealed class WeeklyReportJob
{
public void Run()
{
// ❌ ここにも SqlUserRepository new が出てくる
var repo = new SqlUserRepository(
"Server=localhost;Database=AppDb;Trusted_Connection=True;");
var users = repo.FindAllActive();
Console.WriteLine($"Active users: {users.Count}");
}
}
Repository 側(下位の都合がギュッと詰まってる)🗄️💦
// SqlUserRepository.cs
public sealed class SqlUserRepository
{
private readonly string _connectionString;
public SqlUserRepository(string connectionString)
=> _connectionString = connectionString;
public User FindById(int userId)
{
// ここに SQL / ADO.NET / EF / Dapper 等の “インフラ都合” が入る想定
// (今は例なのでダミーで返す)
return new User(userId, name: "Taro");
}
public List<User> FindAllActive()
=> new List<User> { new User(1, "Taro"), new User(2, "Hanako") };
}
public sealed record User(int Id, string Name);
ここまでで「うん、ありがち〜」って思ったら大正解😂✨ でも、この “ありがち” が後で爆発する💥💥💥
3.3 「修正ポイント探しゲーム」開始〜!👀🎮🔍
ルール:仕様変更が来たよ📩😱
上司「来月からユーザー情報、DBじゃなくて 外部API から取ってね!」🌐💬 あなた「えっ……😇」
つまりこういう変更👇
- 旧:
SqlUserRepository(DB) - 新:
ApiUserRepository(HTTP API)
① まずは “どこを直す?” を探してみよう🔍💨
やることは単純!
✅ 手動で探す(Visual Studio の場合)🧭
Ctrl + Shift + Fで検索🔍- 検索ワード:
new SqlUserRepository - 出てきた場所をメモ📝✨
✅ VS Code の場合も同じだよ💻
Ctrl + Shift + Fで検索🔍- ワード:
new SqlUserRepository
この時点で気付くはず: 「直す場所が “複数” ある」=すでにだるい 😵💫💦
② ありがちな事故パターン😱🚑
- 1箇所だけ直して、別の場所が古いまま残る💥
- ある画面だけDB、別の画面だけAPI、みたいな混在が起きる🌀
- “なんか動くけど挙動が違う” が爆誕する👻
これね、地味に一番つらいタイプ😇
3.4 「差し替えできない」のがつらい理由😢🔁

つらさ①:変更が “点” じゃなく “面” になる🧱📌
new SqlUserRepository() が散らばってると、変更が
- 1箇所修正 ✅ じゃなくて
- 10箇所修正 😭(しかも漏れる)
になるのね…💦
つらさ②:テストがしにくい(=確認がめんどい)🧪😵
たとえば「UserService の挙動だけ確認したい」って思っても…
UserServiceの中で勝手にnew SqlUserRepository()しちゃう- するとテスト時に DB(または接続設定)必須 になる
- つまりテストが遅い・壊れやすい・面倒😇
「本当は Fake(偽物)に差し替えて高速に試したい」のに、できないってやつ💔
つらさ③:責任が混ざって読みにくい🌀📚
UserService のやりたいことは本来こう👇
-
「ユーザーの名前を返す」 なのに、
-
DB接続文字列
-
DB実装の選択
-
メール送信の選択 まで混ざると、話がゴチャる😵💫
3.5 この章のミニ演習(超たいせつ)📝✨
演習A:new を数えよう🔢👀
あなたのプロジェクト(またはこのサンプル)で、
new SqlUserRepositorynew SmtpMailer
みたいな “外部っぽい new” を見つけて、数をメモしてね📝✨ (外部っぽい=DB/HTTP/ファイル/メール/ログなど)
演習B:「変更が来たらどこが死ぬ?」を丸つけ⭕️💥
次の変更が来たら、どのファイルが影響受けそう?
- DB → API
- SMTP → 別のメールサービス
- ログ → クラウドログ基盤
「うわ、ここもここも…」ってなったら、それが今日の収穫だよ🎉😇
3.6 AI(Copilot / Codex)に手伝わせると超ラク🤖✨
この章は “修正しない” けど、探すのはAIが得意👍
🔍 探す系プロンプト例
- 「このソリューション内で
new SqlUserRepositoryが出てくる箇所を一覧にして。ファイル名と行の説明も付けて」🤖📝 - 「DB/HTTP/ファイル/メール送信など “外部I/O” っぽい new を列挙して」🕵️♀️✨
🧠 気づきを言語化させる例
- 「このコードが ‘差し替えに弱い’ 理由を、初心者にもわかる言葉で3つ説明して」🧠💬
- 「仕様変更 ‘DB→API’ のとき、修正漏れが起きるパターンを想像して列挙して」😱📋
ポイント:この章は “直す” じゃなく “痛みを観察する” だよ👀✨ AIにいきなりリファクタさせるのは次章以降でOK🙆♀️
3.7 まとめ:この章でわかったこと🎁✨
new SqlUserRepository()が散らばると、変更が怖い😵💫- 修正ポイントが増えると、漏れ・混在・事故が起きる😱
- 差し替えできないと、テストもしにくい🧪💔
- だから次章で「上位(大事)を守る」話に入るよ🛡️❤️
次の第4章では、この“つらさ”をひっくり返す考え方―― **「上位(業務)を守るために、依存の向きを整える」**に入っていくよ〜🏰✨