第13章 Shared地獄を回避①:共有していいもの・ダメなもの📦⚠️
ここはめっちゃ事故りやすいポイントです🫠 「とりあえず Shared 作ろっか!」が始まると、数か月後に高確率で泣きます😭
この章でできるようになること🎯✨
- 「Sharedに入れてOK✅」と「入れたらヤバい❌」をサクッと判定できる
- Sharedが増えたときに起こる“地獄”の正体がわかる😇
- Sharedを作らずに解決する選択肢を持てる🧠💡
- AIに「Shared候補のリスク評価」をさせて、判断を安定させる🤖🔍
13-1. まず “Shared地獄” ってなに?😇🔥

✅ ありがちな流れ(ほぼテンプレ)
- UIとInfraで同じ処理が必要になった!😳
- 「共通化しよう!」→ Sharedプロジェクトを作る📦
- あれも入れる、これも入れる…便利便利🎉
- 気づくと全員がSharedに依存してる😇
- Sharedをちょい変更 → 全部に影響 → 変更が怖い → 触れない “神棚” 化🛐
13-2. なぜSharedは “依存のハブ” になって壊すの?🧲💥
Dependency Ruleの感覚でいうと…
- Domain(中心)➡️ 外側(UI/Infra)に依存しない
- なのに Shared があると、こうなることが多い👇
❌ よくある依存図(罠)
これ、何がヤバいかというと…
- Sharedはみんなが依存する場所=“第2の中心”になる👑
- でも Shared に入るのはだいたい「中心のルール」じゃなくて「寄せ集め」🌀
- 結果、中心がSharedに引っ張られる(依存関係ルールが実質崩壊)😭
13-3. Sharedに入れてOKなもの✅(ただし条件つき!)
Sharedに入れていいのは、基本この3カテゴリだけに絞るのがおすすめです✂️✨ (そして “薄く・小さく・依存なし” が大前提💪)
✅ OK①:契約(Contract)系🤝📜
「層をまたぐための“約束”」だけは共有してOKになりやすいです🙆♀️
例👇
- DTO(APIリクエスト/レスポンスの箱)📦
- Port(IRepositoryみたいな“中心側に置いたIF”)🧷
- イベントの“型”だけ(DomainEventのペイロード定義など)📣
これは次章(第14章)の「Contractsを中心に置く」に繋がります🧭✨
✅ OK②:プリミティブ寄りの超安定部品🪨✨
ドメインじゃない、かつ どのアプリでも同じ意味のやつだけ。
例👇
Result<T>(成功/失敗の入れ物)🎁Error(エラーコード+メッセージ)📛Clockみたいな抽象(ただしIFだけ!)⏰
✅ OK③:“薄い”ユーティリティ(純粋関数)🧼🧠
Sharedに入れるなら、こういう条件を満たすやつだけ!
- 状態を持たない(staticでもOK)
- I/Oしない(DB/HTTP/ファイル/ログに触らない)🚫
- 外部ライブラリ依存を増やさない(依存の伝染が起きる)🦠
- ドメイン用語が出てこない(OrderとかUserとか出たら赤信号🚨)
例👇
stringの軽い整形(汎用)Guidの安全なパース(汎用)IEnumerableの軽い補助(汎用)
13-4. Sharedに入れたらだいたい事故るもの❌🚨
ここからが本番😂 Sharedに入れがちな “地雷” をまとめます💣
❌ NG①:業務ルール(ドメイン知識)🌀
例👇
OrderCalculatorUserRankServiceCampaignDiscountRule
ドメイン用語が出た瞬間、Sharedじゃないです🙅♀️ それは Domain(中心) に置くべき✨
❌ NG②:便利機能の寄せ集め(Utility盛り合わせ)🍱😇
例👇
DateUtilに100個メソッドCommonHelperAppUtil- 「困ったらここ」フォルダ
これは最終的に…
- 誰も全体を把握してない
- 依存が増えすぎて動かせない
- 変更したらどこが壊れるかわからない
の三重苦になります😭
❌ NG③:外側の都合が混ざるもの(特にInfra臭)🧪🛢️
例👇
- EF Core の
DbContextや Entity - HTTPクライアント周り
ILoggerをがっつり使うログ実装- 設定読み込み(Options)を直接触るやつ
これをSharedに入れると、中心側が外側に汚染される のでアウトです🧼🚫
❌ NG④:フレームワーク依存が強い“共通基盤”🧷🦠
「共通化したいから」って理由で
Microsoft.Extensions.* や外部ライブラリを Shared に入れ始めると…
- Sharedが依存の感染源になって
- みんながそのライブラリに引きずられます😇
13-5. 共有OK/NGを一発で判定する “5つの質問”⚖️✅
Shared候補が出たら、これを順に聞いてください🙋♀️💡
-
ドメイン用語が出る?(Order/User/Payment…) → 出るなら Sharedじゃない(Domain寄り)❌
-
I/Oする?(DB/HTTP/ファイル/ログ/設定) → するなら 外側(Infra/UI)に寄せる❌
-
依存(NuGetや他プロジェクト)増やす? → 増やすなら Sharedに入れるの慎重に⚠️(感染する)
-
変更頻度が高い?(仕様でよく揺れる) → 高いなら共有しない(分岐点)⚠️
-
共有しないと“本当に困る”? → 困らないなら、複製の方が安全なことも多いです✂️😊
13-6. ミニ演習:Shared候補をOK/NG判定してみよう📝⚖️

次の候補、Sharedに入れていい?ダメ?(直感でOK!)😆✨
Result<T>OrderDiscountCalculatorEmailAddress(メールの形式チェック+値オブジェクト)DateOnlyExtensions(日付の超汎用な補助)SqlConnectionFactoryApiErrorResponseDto
解答例(理由つき)✅
-
✅ OK(プリミティブ寄り・契約寄りで汎用)
-
❌ NG(業務ルール=ドメイン)
-
⚠️ ケース次第:
- それが特定ドメインの概念なら Domainへ
- 複数プロダクト横断の“共通基盤”なら Sharedもあり得るけど、置き場所は慎重(Sharedに入れると“全員の仕様”になる)
-
✅ OK(純粋・汎用・依存なしなら)
-
❌ NG(Infra臭100%)
-
✅ OK(契約DTO。契約専用の場所に寄せたい)
13-7. Sharedを作りたくなったときの “代替案” 3つ🧭✨
代替案A:小さいものは複製する✂️😊
えっ!?ってなるけど、マジで強いです💪 共有のコスト(影響範囲・調整・破壊)より、複製の方が安いことが多いです。
ポイント👇
- 複製するなら、テストも一緒に🧪
- “同じものが2つある” は悪じゃなくて、境界が守れてる証拠になることもある✨
代替案B:置き場所を “正しい層” に戻す🧭
「共有したい」=「本当は中心の概念だった」ことが多いです👀
- ルール系 → Domainへ
- ユースケースの補助 → Applicationへ
- DB/HTTP → Infrastructureへ
- 画面都合 → UIへ
代替案C:Sharedじゃなく “Contracts” を作る📜🎯
Sharedの正体の多くは「契約」なので、 契約だけを隔離して “薄く” 保つのが最強です💎 (これは次章でガッツリやります🔥)
13-8. AIに「Shared提案のリスク評価」をやらせる🤖🕵️♀️
Copilot / Codex に、こう頼むとめっちゃ便利です✨
プロンプト例①(判定)
次のクラス/ファイル一覧を「Sharedに入れてOK/NG」で分類して。
各項目に、理由を1行でつけて。
判断基準は「Dependency Rule(中心→外側に依存しない)」。
プロンプト例②(代替案まで)
Sharedに入れたくなっている候補がある。
Shared地獄を避けたいので、
(1) どの層に置くべきか
(2) 共有しない代替案(複製/Contracts/別の抽象化)
(3) 依存が増えるリスク
を提案して。
プロンプト例③(“依存感染”チェック)
このShared候補が依存するNuGet/プロジェクト参照を列挙して、
「それが全プロジェクトへ伝染すると何が起きるか」を説明して。
13-9. 章末まとめ:Sharedを作る前に、これだけ守ろう✅🎀
-
Sharedは最小・薄い・依存なしが基本📦🧼
-
ドメイン用語が出たらSharedじゃない🚨
-
I/OやInfra臭が出たらSharedじゃない🚨
-
Sharedを作る前に、まずは
- 複製✂️
- 正しい層へ移動🧭
- 契約を分離📜 を検討する😊✨
ちょい最新情報メモ(この章の背景として)📌✨
C# 14 は .NET 10 と一緒に提供され、Visual Studio 2026 などで試せます。新しい言語機能が増えるほど「共通ヘルパー」に寄せたくなる誘惑も増えるので、Sharedの線引きがさらに重要になります⚠️ (Microsoft for Developers) また、.NET 10 は 2025-11-11 に公開されたLTSリリースです。 (Microsoft)
次の第14章は、この章で出た「共有OKの代表格=契約(Contract)」を、ちゃんと中心寄りに置いて運用できる形に整えていきます📜🎯✨