3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Repositoryは何を抽象化する存在なのか

Last updated at Posted at 2025-12-18

はじめに

Webアプリケーション設計でよく登場する Repository パターン。

「DbContextのラッパーでは?」
「CRUDしかなくて価値が薄い」
「正直なくても困らない」

そう感じたことがある人も多いのではないでしょうか。

私自身も以前は、

  • Repository は DbContext のラッパー
  • 正直なくても困らない存在

だと思っていました。

しかし、設計を深めていく中で、Repository の本質的な価値は
「DBを隠すこと」 ではないと気づきました。

この記事では、Repository が

  • 何を抽象化する存在なのか
  • 何を気にしなくしてくれるのか
  • 逆に、何をしてはいけないのか

を整理していきます。


Repositoryとは何か

※ここで言う Repository は、
「とりあえず CRUD を並べたクラス」 ではありません。

一言で言うと、Repositoryとは

永続化されたデータを、あたかもメモリ上のコレクションのように扱うための境界

です。

ここで重要なのは、

  • DBかどうか
  • SQLかどうか
  • ORMを使っているか

といった技術要素そのものではないという点です。

Repository の目的は、
「データがどこに、どうやって存在しているか」
を業務ロジックから切り離すことにあります。


Repositoryが気にしなくしてくれること

① データの取得手段(How)

Repository を使わない場合、業務コードはしばしば次のようになります。

var user = dbContext.Users
    .Where(x => x.Id == id && !x.IsDeleted)
    .Select(x => new User { ... })
    .FirstOrDefault();

このコードは、業務ロジックが

  • DB
  • 削除フラグの存在
  • クエリ構造
  • データ取得方法

といった永続化の都合をすべて知っている状態です。


Repository を挟むと、次のようになります。

var user = userRepository.FindById(id);

業務側は

  • DBかどうか
  • SQLかどうか
  • キャッシュがあるか

を一切考えません。

👉 「どうやって取るか」を考えなくてよくなる。


② データの所在(Where)

Repository が抽象化するのは、DBだけではありません。

  • RDB
  • キャッシュ(Redisなど)
  • ファイル
  • 外部API

といった データの所在そのもの です。

IUserRepository
{
    User FindById(UserId id);
}

このインターフェースの背後で、

  • キャッシュを優先する
  • API → DB の順でフォールバックする
  • 障害時はファイルを使う

といった実装が行われていても、 呼び出し側は一切知る必要がありません。

👉 「データがどこにあるか」を忘れられる。


③ 技術的な制約

Repository を使わないと、業務コードは次のようなことを意識しがちです。

  • IQueryable / IEnumerable
  • 遅延実行
  • Include漏れ
  • トランザクション境界

Repository を境界にすることで、 これらの技術的制約を業務から隔離できます。


Repositoryがやってはいけないこと

Repository は万能ではありません。

❌ やってはいけないことは次の通りです。

  • 業務判断を持つ
  • ユースケースの流れを制御する
  • 「AならBする」といった分岐を書く

Repository の責務はあくまで

  • データの取得
  • データの保存
  • 永続化に関する都合の吸収

に限定されるべきです。


よくある誤解

Repository = DBアクセスクラス?

半分正解で、半分不正解です。

Repository は DBアクセスを含みますが、 本質は

業務から永続化の存在を消すこと

にあります。

単なる DbContext のラッパーに留まっている場合、
Repository の価値はほとんど発揮されません。

// 価値が出ていない例
User Find(int id) => _db.Users.Find(id);

この場合、

  • 永続化の都合を何も隠していない
  • 呼び出し側の理解が何も楽になっていない

ため、Repository を置く意味はほとんどありません。


Repositoryの価値が出る瞬間

次のような兆候が出てきたら、Repository が効き始めます。

  • 業務コードに Where / Include が溢れてきた
  • DB構造変更が業務ロジックに波及する
  • テストで DB を意識したくない

「この取得って、業務的に何?」と考え始めた

👉 「データ」より「意味」を扱いたくなった瞬間です。


CQRSとの関係

Repository が扱うのは、
業務的に意味のある集約の取得です。

一方で、画面表示のための取得は、

  • 複数テーブルのJOIN
  • 集計
  • DTO専用構造

になることが多く、
これを無理に Repository に押し込むと、
Repository が「何でも屋」になります。

そのため CQRS では、

  • Command / Domain側

    • Repository
    • Entity / Aggregate
    • 業務ルール・判断
  • Query側

    • 表示専用の取得
    • ReadModel / DTO
    • 意味判断はしない

と役割を分けます。

Query は「検索」ですが、
業務的な意味を判断するための検索ではなく、
表示・参照のための取得
に寄せることで、

  • Repository の責務が明確になる
  • Service地獄になりにくい

という効果があります。


まとめ

  • Repository の価値は 「DBを隠すこと」ではない
  • Repository は データの所在と取得手段を忘れさせる境界
  • 無理に作るものではなく、 必要になったときに初めて効く設計要素

Repository を疑問に思った経験がある人ほど、
本質を理解したときに強力な武器になります。

設計に迷ったときは、

「業務コードから、今何を消したいのか?」

「Repositoryに迷ったら、
 それが業務判断に使われる取得か、表示のための取得かを考える」

を考えてみると、
Repository を置くべきかどうかが見えてくるはずです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?