第27章 Outbound Adapter②:DB実装に差し替え(考え方)🔁🗃️
この章は「InMemoryで動いたアプリを、DBに差し替えるときの“設計のコツ”」を身につける回だよ〜!🥳 次の第28章でDB実装の最低限サンプルをやる前に、ここで迷子にならない地図を作る感じ🗺️💕
0. まず結論:差し替えで変えたいのは“外側だけ”🛡️✨

ヘキサゴナルの美味しいところはこれ👇
- ✅ Port(interface)は変えない(=約束は固定)
- ✅ Core(Domain/UseCase)は変えない(=業務ルール守られる)
- ✅ Adapterだけ入れ替える(=外部の都合だけ交換)
つまり「DB対応=大改造」じゃなくて、 「プラグインを差し替える」みたいな感覚になるのが理想だよ🔌😆
1. “差し替え”の全体像を1枚で🧠📌
イメージはこう👇
-
Core(UseCase)が欲しいのは「保存できること」「取得できること」だけ
-
それを IOrderRepository(Port) に言語化してある
-
実装は複数あってOK
- InMemoryOrderRepository(いま)
- DbOrderRepository(これから)
そして DI(Composition Root)でどっちを使うか選ぶ🧩✨ (この「選ぶ場所」が超だいじ!)
2. DB差し替えの“正しい手順”】【最短で事故らない】🚦🧯
差し替えって、焦るとぐちゃぐちゃになるので… おすすめ手順をそのまま使ってOKだよ🙆♀️💕
Step A:まず“いま”が全部グリーンか確認🟢✅
- テストがあるなら全部通す
- テストないなら最低でも「注文作成→一覧表示」が動くのを確認
ここが赤いまま次に行くと、原因が混ざって地獄になるよ😇💥
Step B:DB用Adapterを“別プロジェクト/別フォルダ”に作る📦✨
ここが超重要ポイント💡 DBの都合(EF Core、接続文字列、Entityクラス)をCoreに入れないために分けるよ!
EF Core は .NET 10 と同じタイミングの EF Core 10(LTS) があり、.NET 10 SDK/Runtime が必須だよ〜(古い .NET では動かない)📌✨ (Microsoft Learn)
Step C:Portはそのまま、DB Adapterが実装する🧠🔌
Portは「欲しいこと」だけを表してるはず👇
- Save(保存)
- Find(取得)
- List(一覧)
DB Adapterはその interface を実装して、DBへつなぐ役目だけやる✨ このとき Core は DB を1ミリも知らないのが勝ち🏆
Step D:差し替えポイントは “DI登録(配線)” だけにする🔁🧩
差し替えの本体はここ! 「どの実装を IOrderRepository として使うか」を切り替えるのは Composition Root(例:Program.cs) だよ📍✨
ASP.NET Core のDIは AddScoped / AddTransient / AddSingleton みたいに登録して使うのが基本だよ〜🔧 (Microsoft Learn)
例(雰囲気だけ。実装は次章で!)👇
// Program.cs(Composition Root)
if (builder.Configuration.GetValue<bool>("UseInMemory"))
{
builder.Services.AddScoped<IOrderRepository, InMemoryOrderRepository>();
}
else
{
builder.Services.AddScoped<IOrderRepository, DbOrderRepository>();
}
これができると、Coreのコード0行変更で差し替えが成立するよ😆🛡️
3. “差し替えで壊れやすいポイント”だけ先に潰そ〜😵💫🧯
❶ Domain型をそのままDBに保存しようとして詰む💥
ありがち👇
- DomainのクラスにEFの属性を貼る
- Domainに
DbContextが出てくる - CoreプロジェクトがEFパッケージ参照しちゃう
👉 これは「DB都合がCoreに侵入」してアウト〜🧼😭 DBモデル(Entity)とDomainは別物にして、変換はAdapterに押し込むのが安全🙆♀️✨
❷ Portが“DBっぽい形”になる(Queryable地獄)🕳️😇
Portにこういうのを入れると、差し替え不能になりがち👇
IQueryable<Order>を返すExpression<Func<...>>を受ける- 「DBの検索最適化都合」が interface に滲む
👉 Portは「ユースケースが欲しいもの」を返すのが大事🎯 検索条件も「ユースケース語彙」で表現できると強いよ💪✨
❸ 例外がDB依存のままCoreへ飛んでくる💣
DB Adapterが投げる例外(接続失敗、制約違反など)を、そのままCoreに流すと…
- CoreがDB例外型を知る羽目になる
- 画面にDBっぽいエラーが出る
👉 Adapter側で「アプリとして意味ある失敗」に変換するのが理想(この話は第35章で仕上げるよ🎁)
4. “差し替えに強い”設計の合言葉3つ🧡✨
合言葉①:Portは「欲しいこと」だけ📝
- 保存したい
- 取得したい
- 一覧が欲しい → 方法は言わない(SQLとか知らん!😤)
合言葉②:Adapterは「変換係」🔁
- Domain ↔ DB Entity
- DTO ↔ Domain(Inboundの話と同じ!)
合言葉③:配線は外で(Composition Root)📍
- Coreは配線しない
newしない(DIに寄せる)
5. AI(Copilot/Codex)で爆速にするコツ🤖⚡
AIはこういう“外側作業”が得意だよ😆✨ ただし 境界ルール(Coreに漏らさない)は人間が守る🚦
おすすめ指示例👇(そのまま投げてOK)
- 「
IOrderRepositoryを実装するDbOrderRepositoryの雛形を作って。DomainとDB Entityは分けて、変換はRepository内でやって」 - 「EF Core用の
OrderEntityとOrderItemEntityを作って、DomainOrderとのマッピング関数も用意して」 - 「Program.csで
UseInMemoryフラグに応じて実装を切り替えるDI登録コードを書いて」
AIに作らせたら、人間はここだけ見る👀✨
- CoreがEF参照してない?
- PortがDB都合になってない?
- 変換がAdapterに閉じてる?
6. ミニ演習:差し替えの“気持ちよさ”を体験しよ😆🎮
やることは超シンプル👇
-
DbOrderRepository : IOrderRepositoryを作る(中身はthrow new NotImplementedException()でもOK) -
DI登録を
DbOrderRepositoryに切り替える -
コンパイルエラーがどこに出るかを見る👀
- 理想:Adapter側だけで完結
- もしCore側が壊れたら、依存が漏れてるサイン🚨
この“漏れ検知”にめちゃくちゃ効くよ✅✨
7. この章の最終チェックリスト✅✨
- Port(interface)を変えずに進めてる?📝
- CoreがEF/DBを参照してない?🛡️
- DBモデルとDomainを分けた?🧼
- 変換はAdapterに押し込めた?🔁
- 差し替え箇所がDI登録(配線)に集中してる?📍
ちなみに:2026時点の基盤はこんな感じだよ📌🪟
- .NET 10 は 2025年11月リリースのLTS で、2026年1月時点でもアクティブサポート中だよ🧡 (Microsoft)
- EF Core 10 も LTS で .NET 10 が必須だよ🔒 (Microsoft Learn)
- Visual Studio は Visual Studio 2026 のリリースノートが出ていて、2026年1月の更新も案内されてるよ🧰✨ (Microsoft Learn)
次の第28章では、いよいよ DB Adapterの“最低限実装” をやって「ほんとに差し替わるじゃん!」を体験するよ〜!🗃️🔥