メインコンテンツまでスキップ

第13章 Shared地獄を回避①:共有していいもの・ダメなもの📦⚠️

ここはめっちゃ事故りやすいポイントです🫠 「とりあえず Shared 作ろっか!」が始まると、数か月後に高確率で泣きます😭


この章でできるようになること🎯✨

  • 「Sharedに入れてOK✅」と「入れたらヤバい❌」をサクッと判定できる
  • Sharedが増えたときに起こる“地獄”の正体がわかる😇
  • Sharedを作らずに解決する選択肢を持てる🧠💡
  • AIに「Shared候補のリスク評価」をさせて、判断を安定させる🤖🔍

13-1. まず “Shared地獄” ってなに?😇🔥

✅ ありがちな流れ(ほぼテンプレ)

  1. UIとInfraで同じ処理が必要になった!😳
  2. 「共通化しよう!」→ Sharedプロジェクトを作る📦
  3. あれも入れる、これも入れる…便利便利🎉
  4. 気づくと全員がSharedに依存してる😇
  5. 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①:業務ルール(ドメイン知識)🌀

例👇

  • OrderCalculator
  • UserRankService
  • CampaignDiscountRule

ドメイン用語が出た瞬間、Sharedじゃないです🙅‍♀️ それは Domain(中心) に置くべき✨


❌ NG②:便利機能の寄せ集め(Utility盛り合わせ)🍱😇

例👇

  • DateUtil に100個メソッド
  • CommonHelper
  • AppUtil
  • 「困ったらここ」フォルダ

これは最終的に…

  • 誰も全体を把握してない
  • 依存が増えすぎて動かせない
  • 変更したらどこが壊れるかわからない

の三重苦になります😭


❌ NG③:外側の都合が混ざるもの(特にInfra臭)🧪🛢️

例👇

  • EF Core の DbContext や Entity
  • HTTPクライアント周り
  • ILogger をがっつり使うログ実装
  • 設定読み込み(Options)を直接触るやつ

これをSharedに入れると、中心側が外側に汚染される のでアウトです🧼🚫


❌ NG④:フレームワーク依存が強い“共通基盤”🧷🦠

「共通化したいから」って理由で Microsoft.Extensions.* や外部ライブラリを Shared に入れ始めると…

  • Sharedが依存の感染源になって
  • みんながそのライブラリに引きずられます😇

13-5. 共有OK/NGを一発で判定する “5つの質問”⚖️✅

Shared候補が出たら、これを順に聞いてください🙋‍♀️💡

  1. ドメイン用語が出る?(Order/User/Payment…) → 出るなら Sharedじゃない(Domain寄り)❌

  2. I/Oする?(DB/HTTP/ファイル/ログ/設定) → するなら 外側(Infra/UI)に寄せる❌

  3. 依存(NuGetや他プロジェクト)増やす? → 増やすなら Sharedに入れるの慎重に⚠️(感染する)

  4. 変更頻度が高い?(仕様でよく揺れる) → 高いなら共有しない(分岐点)⚠️

  5. 共有しないと“本当に困る”? → 困らないなら、複製の方が安全なことも多いです✂️😊


13-6. ミニ演習:Shared候補をOK/NG判定してみよう📝⚖️

次の候補、Sharedに入れていい?ダメ?(直感でOK!)😆✨

  1. Result<T>
  2. OrderDiscountCalculator
  3. EmailAddress(メールの形式チェック+値オブジェクト)
  4. DateOnlyExtensions(日付の超汎用な補助)
  5. SqlConnectionFactory
  6. ApiErrorResponseDto

解答例(理由つき)✅

  1. ✅ OK(プリミティブ寄り・契約寄りで汎用)

  2. ❌ NG(業務ルール=ドメイン)

  3. ⚠️ ケース次第:

    • それが特定ドメインの概念なら Domainへ
    • 複数プロダクト横断の“共通基盤”なら Sharedもあり得るけど、置き場所は慎重(Sharedに入れると“全員の仕様”になる)
  4. ✅ OK(純粋・汎用・依存なしなら)

  5. ❌ NG(Infra臭100%)

  6. ✅ 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)」を、ちゃんと中心寄りに置いて運用できる形に整えていきます📜🎯✨