{"componentChunkName":"component---src-templates-post-template-js","path":"/posts/data-access-patterns","result":{"data":{"markdownRemark":{"id":"8797a892-00fc-5ac1-b45e-643b75610d07","html":"<h2 id=\"はじめに\" style=\"position:relative;\"><a href=\"#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB\" aria-label=\"はじめに permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>はじめに</h2>\n<p>アプリケーション・アーキテクチャについて議論する中で、最近は DDD の戦術的設計やクリーンアーキテクチャなどがキーワードとして解説されることが多いです。</p>\n<p>そんな中、データアクセスの実装については Repository 意外の情報源が少なく、また Repository についても「データアクセス用のクラス」くらいの曖昧な定義で使われているケースも多いと思います。</p>\n<p>この記事では、そんな<strong>データアクセスのパターンについて改めて整理</strong>し、よく見かける議論の 1 つである「<strong>Rails の ActiveRecord や Laravel の Eloquant による Repository の実装</strong>」についても考察してみます。</p>\n<h2 id=\"注意事項\" style=\"position:relative;\"><a href=\"#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85\" aria-label=\"注意事項 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>注意事項</h2>\n<h3 id=\"内容の正確性について\" style=\"position:relative;\"><a href=\"#%E5%86%85%E5%AE%B9%E3%81%AE%E6%AD%A3%E7%A2%BA%E6%80%A7%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6\" aria-label=\"内容の正確性について permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>内容の正確性について</h3>\n<p>この記事はドメイン駆動設計に関する各種書籍や PoEAA などを参考にしていますが、情報源によって同じ言葉が違う意味で使われていることがあります。</p>\n<p>できるだけよく使われている意味で整理しようとしていますが、筆者の主観が入っている部分もありますので、ご了承ください。</p>\n<h3 id=\"用語について\" style=\"position:relative;\"><a href=\"#%E7%94%A8%E8%AA%9E%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6\" aria-label=\"用語について permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>用語について</h3>\n<p>記事の中で</p>\n<ul>\n<li>ビジネスロジック</li>\n<li>データアクセス</li>\n<li>ドメインモデル</li>\n</ul>\n<p>という用語を使いますが、こちらは過去に書いた</p>\n<ul>\n<li><a href=\"https://qiita.com/os1ma/items/25725edfe3c2af93d735\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">「ビジネスロジック」とは何か、どう実装するのか - Qiita</a></li>\n</ul>\n<p>という記事内と同じ意味で使っています。</p>\n<p>また、上記の記事の「コアなルール」のことを「ドメインロジック」と表現させていただきます。</p>\n<h3 id=\"表記について\" style=\"position:relative;\"><a href=\"#%E8%A1%A8%E8%A8%98%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6\" aria-label=\"表記について permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>表記について</h3>\n<p>記事の中で書籍『<a href=\"https://amzn.to/3I1E7ui\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">エンタープライズアプリケーションアーキテクチャパターン</a>』を参考にしている箇所では『PoEAA』と省略表記させていただきます。</p>\n<h2 id=\"データアクセスのパターン整理\" style=\"position:relative;\"><a href=\"#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%AE%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E6%95%B4%E7%90%86\" aria-label=\"データアクセスのパターン整理 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>データアクセスのパターン整理</h2>\n<p>それでは本題に入ります。</p>\n<p>この記事では、まず最初にデータアクセスについて以下の 3 つのパターンを整理してみます。</p>\n<ul>\n<li>Table Data Gateway パターン</li>\n<li>ActiveRecord パターン</li>\n<li>Repository パターン</li>\n</ul>\n<p>細かく分類すればもっと多数のパターンに分けられますが、まずはこのくらいの分類が分かりやすいのではないかという考えです。</p>\n<p>また、これらと併用して QueryService というクラスを設けるケースもありますが、そちらの説明は今回は省略します。\nQueryService については以下の記事が非常に分かりやすいです。</p>\n<ul>\n<li><a href=\"https://little-hands.hatenablog.com/entry/2019/12/02/cqrs\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">CQRS実践入門 [ドメイン駆動設計] - little hands’ lab</a></li>\n</ul>\n<p>では、ここから上記の 3 パターンについて書いていきます。</p>\n<h3 id=\"table-data-gateway-パターン\" style=\"position:relative;\"><a href=\"#table-data-gateway-%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3\" aria-label=\"table data gateway パターン permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table Data Gateway パターン</h3>\n<p>Table Data Gateway パターンをざっくり言えば、<strong>DB のテーブルと 1 対 1 に対応するデータアクセス用のクラスを設ける</strong>というものです。</p>\n<p>Java 界隈には Data Access Object (DAO) と呼ばれるパターンがありますが、<strong>DAO は Table Data Gateway と同じものを指している</strong>と言われています。</p>\n<h4 id=\"実装イメージ\" style=\"position:relative;\"><a href=\"#%E5%AE%9F%E8%A3%85%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8\" aria-label=\"実装イメージ permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>実装イメージ</h4>\n<p>擬似言語による実装イメージは以下のようになります。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">TaskTableDataGateway {\n  find(id)\n  findWithName(name)\n  insert(name)\n  update(id, name)\n  delete(id)\n}</code></pre></div>\n<p>※ メソッド名は『PoEAA』p153 を参考にしています。</p>\n<h4 id=\"メリット\" style=\"position:relative;\"><a href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88\" aria-label=\"メリット permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>メリット</h4>\n<p>DB のテーブルと 1 対 1 に対応するクラスを作成してデータを取り出すのは、<strong>非常にシンプルで理解が簡単</strong>です。</p>\n<h4 id=\"デメリット\" style=\"position:relative;\"><a href=\"#%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88\" aria-label=\"デメリット permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>デメリット</h4>\n<p><strong>呼び出し側がデータモデルを意識する</strong>ことになります。\n例えば Service から Table Data Gateway を呼び出す場合、ビジネスロジックがデータモデルに依存することになります。</p>\n<p>また、Service クラスが Table Data Gateway を呼び出すようなアーキテクチャの場合、1 つの Service クラスが必要とする Table Data Gateway の数がかなり多くなるケースがあります。</p>\n<p>さらに、Order と OrderDetail など、同時に DB からロードすべきデータを同時にロードすることを保証できず、ビジネスロジック層でオブジェクトの整合性がとれていない瞬間を生んでしまいます。</p>\n<p>なお、これら 3 つのデメリットは、Repository パターンを使うことで解消可能です。</p>\n<h4 id=\"関連パターン\" style=\"position:relative;\"><a href=\"#%E9%96%A2%E9%80%A3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3\" aria-label=\"関連パターン permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>関連パターン</h4>\n<p>類似のパターンとして、以下のような実装も考えられます。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">TaskTableDataGateway {\n  find(id)\n  findWithName(name)\n  insert(task)\n  update(task)\n  delete(task)\n}</code></pre></div>\n<p>違いは insert、update、delete メソッドの引数がテーブルと対応するクラスのオブジェクトになっていることです。</p>\n<h3 id=\"activerecord-パターン\" style=\"position:relative;\"><a href=\"#activerecord-%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3\" aria-label=\"activerecord パターン permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>ActiveRecord パターン</h3>\n<p>続いて、ActiveRecord パターンについてです。</p>\n<p><strong>ActiveRecord という単語で Ruby on Rails の OR マッパー「ActiveRecord」を思い浮かべる方も多いと思いますが、それは ActiveRecord パターンを実装したものです</strong>。</p>\n<p>同様に、Laravel の Eloquant も ActiveRecord パターンを実装した OR マッパーです。</p>\n<p>ActiveRecord パターンでは、<strong>ドメインモデルを DB のテーブルと 1 対 1 対応させ、データアクセスのメソッドも持たせます</strong>。\n（ここで言うドメインモデルは、データとドメインロジックを持つクラスのことです）</p>\n<h4 id=\"実装イメージ-1\" style=\"position:relative;\"><a href=\"#%E5%AE%9F%E8%A3%85%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8-1\" aria-label=\"実装イメージ 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>実装イメージ</h4>\n<p>擬似言語による実装イメージは以下のようになります。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Task {\n  id\n  name\n\n  isAssigned()\n\n  insert()\n  update()\n  delete()\n}</code></pre></div>\n<p>※ メソッド名は『PoEAA』p170 を参考にしています。</p>\n<p>このように、</p>\n<ul>\n<li>id、name といった<strong>データ</strong></li>\n<li>isAssigned といった<strong>ドメインロジックのメソッド</strong></li>\n<li>insert や update、delete のような<strong>データアクセスのメソッド</strong></li>\n</ul>\n<p>を同じクラスが持つことになります。</p>\n<p>※ メソッド名は OR マッパーにより異なる場合があります</p>\n<h4 id=\"メリット-1\" style=\"position:relative;\"><a href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88-1\" aria-label=\"メリット 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>メリット</h4>\n<p>ActiveRecord パターン最大のメリットは、Rails の ActiveRecord や Laravel の Eloquant といった <strong>ActiveRecord 系の OR マッパーを使うことで、非常に低コストで実装できる</strong>ことです。</p>\n<p>また、これらのフレームワークは近年プログラミングの入門として選択されることも増えており、経験のあるエンジニアが多いです。</p>\n<h4 id=\"デメリット-1\" style=\"position:relative;\"><a href=\"#%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88-1\" aria-label=\"デメリット 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>デメリット</h4>\n<p>ActiveRecord パターンでは、ドメインモデルと DB が 1 対 1 対応になるため、<strong>ビジネスロジックはデータモデルと強く結合します</strong>。</p>\n<p>また、<strong>1 つのクラスがドメインモデルとデータアクセスという複数の役割を持つことになってしまいます</strong>。</p>\n<h3 id=\"repository-パターン\" style=\"position:relative;\"><a href=\"#repository-%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3\" aria-label=\"repository パターン permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Repository パターン</h3>\n<p>最後に Repository パターンです。</p>\n<p>Repository パターンは、<strong>コレクションライクなインタフェースで、「集約」という単位でデータを読み書きする</strong>データアクセスのパターンです。</p>\n<p>今まで紹介した 2 パターンと異なり、<strong>Repository は DB と 1 対 1 対応させるのではなく、ドメインモデルの都合でデータアクセスを取り扱います</strong>。</p>\n<h4 id=\"実装イメージ-2\" style=\"position:relative;\"><a href=\"#%E5%AE%9F%E8%A3%85%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8-2\" aria-label=\"実装イメージ 2 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>実装イメージ</h4>\n<p>擬似言語による実装イメージは以下のようになります。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">TaskRepository {\n  taskOfId(id)\n  taskOfName(name)\n  save(task)\n  remove(task)\n}</code></pre></div>\n<p>※ メソッド名は『実戦ドメイン駆動設計』p405 を参考にしています。</p>\n<p>これだけ見ると Table Data Gateway パターンと同じように見えるかもしれませんが、</p>\n<ul>\n<li><strong>Table Data Gateway は DB のテーブルと 1 つと対応</strong></li>\n<li><strong>1 つの Repository に対応する DB のテーブル数は状況次第</strong></li>\n</ul>\n<p>といった違いがあります。</p>\n<p>この違いについては以下の記事が非常に分かりやすいです。</p>\n<ul>\n<li><a href=\"https://qiita.com/mikesorae/items/ff8192fb9cf106262dbf\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">やはりお前たちのRepositoryは間違っている - Qiita</a></li>\n</ul>\n<h4 id=\"メリット-2\" style=\"position:relative;\"><a href=\"#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88-2\" aria-label=\"メリット 2 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>メリット</h4>\n<p>Repository を使うと、Repository を呼び出す<strong>ビジネスロジック層が、データモデルに依存しなくなります</strong>。\nそのため、ヘキサゴナルアーキテクチャ・オニオンアーキテクチャ・クリーンアーキテクチャなどで語られる、依存性逆転が可能になります。</p>\n<p>また、Table Data Gateway とは異なり、Service などのクラスに多数必要とされにくくなったり、ロードしたオブジェクトの整合性のない状態を防ぐことができます。</p>\n<h4 id=\"デメリット-2\" style=\"position:relative;\"><a href=\"#%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88-2\" aria-label=\"デメリット 2 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>デメリット</h4>\n<p>Repository パターンのメリットや目的を理解するのは、<strong>他のパターンと比べて何段階か難易度が高い</strong>です。</p>\n<p>そのため、どんなパターンなのか理解しているエンジニアも少ないです。</p>\n<h4 id=\"関連パターン-1\" style=\"position:relative;\"><a href=\"#%E9%96%A2%E9%80%A3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-1\" aria-label=\"関連パターン 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>関連パターン</h4>\n<p>上の例では最近 DDD などの文脈で見かけるリポジトリの実装イメージを示しましたが、『PoEAA』p345 では以下のようなインタフェースとして紹介されています。</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">TaskRepository {\n  matching(criteria)\n}</code></pre></div>\n<p>検索条件を表す criteria オブジェクトを引数として検索するというものです。</p>\n<p>どちらが正しいということはできませんが、重要なポイントは、どちらも「ドメインモデルを中心的に考えたインタフェースになっていること」だと思います。</p>\n<h2 id=\"どのパターンを使うか\" style=\"position:relative;\"><a href=\"#%E3%81%A9%E3%81%AE%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%82%92%E4%BD%BF%E3%81%86%E3%81%8B\" aria-label=\"どのパターンを使うか permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>どのパターンを使うか</h2>\n<p>ここまで、最近の開発でよく見かけるデータアクセスのパターンを整理してきました。</p>\n<p>この中のどのパターンを使うかですが、「上記のメリット・デメリットを踏まえて、今回の状況ではどうするかを考える」というのが私の意見です。</p>\n<p>例えば、「DDD だから Repository じゃないと絶対にダメ」といったことは必ずしもなく、トレードオフを理解した上で ActiveRecord パターンを採用してもいいと思います。</p>\n<p>それ以上に前提として理解しておくべきポイントとして、どのパターンを使うかは、</p>\n<ul>\n<li>ビジネスロジック層とのインタフェース</li>\n<li>データアクセス層の内部実装</li>\n</ul>\n<p>の 2 箇所について検討する必要があります。</p>\n<h3 id=\"ビジネスロジック層とのインタフェース\" style=\"position:relative;\"><a href=\"#%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF%E5%B1%A4%E3%81%A8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9\" aria-label=\"ビジネスロジック層とのインタフェース permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>ビジネスロジック層とのインタフェース</h3>\n<p>データアクセスの処理は主に Service (または ApplicationService、UseCase。アーキテクチャによっては Controller) といったクラスから呼び出すことになりますが、呼び出し先として</p>\n<ul>\n<li>Table Data Gateway</li>\n<li>ActiveRecord</li>\n<li>Repository</li>\n</ul>\n<p>のどれを使うか、という議論がまずあります。</p>\n<p>これは各パターンのメリット・デメリットを踏まえて決めることになります。</p>\n<p>その内部実装についてが少しややこしいかもしれません。</p>\n<h3 id=\"データアクセス層の内部実装\" style=\"position:relative;\"><a href=\"#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%B1%A4%E3%81%AE%E5%86%85%E9%83%A8%E5%AE%9F%E8%A3%85\" aria-label=\"データアクセス層の内部実装 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>データアクセス層の内部実装</h3>\n<p>ActiveRecord パターンを採用する場合は、ActiveRecord 系の OR マッパーを使うことが多いです。\nしかし、Table Data Gateway や Repository を使う場合は、その内部を自前で実装することが多いです。</p>\n<p>ここでは特に Repository の内部実装について書いていきます。</p>\n<h4 id=\"repository-の内部実装の方法\" style=\"position:relative;\"><a href=\"#repository-%E3%81%AE%E5%86%85%E9%83%A8%E5%AE%9F%E8%A3%85%E3%81%AE%E6%96%B9%E6%B3%95\" aria-label=\"repository の内部実装の方法 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Repository の内部実装の方法</h4>\n<p>Repository の内部を実装する際は、何らかの OR マッパーを使うことが多いです。</p>\n<p>OR マッパーとしては、</p>\n<ul>\n<li>SQL とマッピング方法の 2 つを書く方式</li>\n<li>流れるようなインタフェース (fluent interface)</li>\n<li>JPA などの狭義の OR マッパー</li>\n<li>ActiveRecord 系の OR マッパー</li>\n</ul>\n<p>などがあります。</p>\n<p>また、Table Data Gateway を Repository の内部実装として使うといったこともできます。</p>\n<h4 id=\"repository-と他のデータアクセスパターンの関係\" style=\"position:relative;\"><a href=\"#repository-%E3%81%A8%E4%BB%96%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%AE%E9%96%A2%E4%BF%82\" aria-label=\"repository と他のデータアクセスパターンの関係 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Repository と他のデータアクセスパターンの関係</h4>\n<p>ここでポイントは、<strong>Repository の内部に Table Data Gateway や ActiveRecord が登場するケースがある</strong>ことです。</p>\n<p>つまり、Table Data Gateway や ActiveRecord には、</p>\n<ul>\n<li><strong>Repository は使わず、ビジネスロジック層とのインタフェースを Table Data Gateway (または ActiveRecord) にする</strong></li>\n<li><strong>ビジネスロジック層とのインタフェースは Repository とし、内部実装を Table Data Gateway (または ActiveRecord) にする</strong></li>\n</ul>\n<p>といった選択肢があるということになります。</p>\n<p>最後に、後者の「ビジネスロジック層とのインタフェースは Repository とし、内部実装を Table Data Gateway (または ActiveRecord) にする」パターンについて書いていきます。</p>\n<h2 id=\"rails-の-activerecord-や-laravel-の-eloquant-による-repository-の実装について\" style=\"position:relative;\"><a href=\"#rails-%E3%81%AE-activerecord-%E3%82%84-laravel-%E3%81%AE-eloquant-%E3%81%AB%E3%82%88%E3%82%8B-repository-%E3%81%AE%E5%AE%9F%E8%A3%85%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6\" aria-label=\"rails の activerecord や laravel の eloquant による repository の実装について permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Rails の ActiveRecord や Laravel の Eloquant による Repository の実装について</h2>\n<p>Rails の ActiveRecord や Laravel の Eloquant といった ActiveRecord 系の OR マッパーは広く使われています。\nそのため、「Rails や Laravel にクリーンアーキテクチャを適用する」といった目的で、Repository の内部実装として ActiveRecord や Eloquant が使われている例を見かけることがあります。</p>\n<p>これに対して、「<strong>Rails の ActiveRecord や Laravel の Eloquant を使うなら、基本的に Repository は設けないほうが良い</strong>」というのが今の私の考えです。</p>\n<p>理由は主に 2 つあります。</p>\n<h3 id=\"理由-1\" style=\"position:relative;\"><a href=\"#%E7%90%86%E7%94%B1-1\" aria-label=\"理由 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>理由 1</h3>\n<p>ActiveRecord パターンはデータベースと密結合になる代わりに実装コストを下げるのがメリットであり、Repository パターンとは逆の特徴を持ちます。</p>\n<p>そのため、<strong>ActiveRecord と Repository を組み合わせると、ActiveRecord パターンのメリットは得られなくなります</strong>。</p>\n<p>Repository パターンを採用する前提で、Repository の内部実装にすぎないと割り切って ActiveRecord 系の OR マッパーを使うことはありえなくはないですが、あまりメリットは大きくないと思います。</p>\n<h3 id=\"理由-2\" style=\"position:relative;\"><a href=\"#%E7%90%86%E7%94%B1-2\" aria-label=\"理由 2 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>理由 2</h3>\n<p>ActiveRecord 系の OR マッパーが付属するフレームワークとして有名な <strong>Rails や Laravel は、ヘキサゴナルアーキテクチャ・オニオンアーキテクチャ・クリーンアーキテクチャといった、Repository パターンを活かせる設計と相性がよくない</strong>とも考えています。</p>\n<p>ヘキサゴナルアーキテクチャ・オニオンアーキテクチャ・クリーンアーキテクチャといった設計は、クラス数が増える代わりに疎結合で変更に強くなるといった特徴があります。</p>\n<p>これは Rails や Laravel などのスタンダードな実装とは対局にあり、言語としても、静的型付けのものを採用した方が相性が良いと思います。</p>\n<h3 id=\"落としどころ\" style=\"position:relative;\"><a href=\"#%E8%90%BD%E3%81%A8%E3%81%97%E3%81%A9%E3%81%93%E3%82%8D\" aria-label=\"落としどころ permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>落としどころ</h3>\n<p>以上の理由から、「Rails の ActiveRecord や Laravel の Eloquant を使うなら、基本的に Repository は設けないほうが良い」と考えています。</p>\n<p>Rails や Laravel でアーキテクチャを改善するのであれば、</p>\n<ul>\n<li>Request クラスや Response クラスをしっかり定義する</li>\n<li>Model にしっかりメソッドを持たせ、適宜 ValueObject を作る</li>\n<li>ユースケースは UseCase (または Service、ApplicationService) クラスに分離する</li>\n</ul>\n<p>といったところから着手するのが望ましいと思います。</p>\n<p>例えば以下の書籍や記事が非常に参考になります。</p>\n<ul>\n<li><a href=\"https://amzn.to/3FNp0Tw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">パーフェクト Ruby on Rails 【増補改訂版】 (Perfect series)</a></li>\n<li><a href=\"https://techracho.bpsinc.jp/hachi8833/2021_01_07/14738\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">肥大化したActiveRecordモデルをリファクタリングする7つの方法（翻訳）｜TechRacho by BPS株式会社</a></li>\n<li><a href=\"https://speakerdeck.com/suusan2go/have-a-rethink-on-rails-service-class\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Rails サービスクラス再考 / have a rethink on Rails service class - Speaker Deck</a></li>\n<li><a href=\"https://zenn.dev/mpyw/articles/ce7d09eb6d8117\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">5年間 Laravel を使って辿り着いた，全然頑張らない「なんちゃってクリーンアーキテクチャ」という落としどころ</a></li>\n</ul>\n<p>この内容と関連して、自分も過去に以下のような関連記事を書いています。</p>\n<ul>\n<li><a href=\"https://qiita.com/os1ma/items/66fb47f229896b32b2e8\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">「Controller にビジネスロジックを書くな」の対応パターン - Qiita</a></li>\n</ul>\n<h2 id=\"おわりに\" style=\"position:relative;\"><a href=\"#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB\" aria-label=\"おわりに permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>おわりに</h2>\n<p>以上、データアクセスのパターンについて考えていたことをまとめました。</p>\n<p>他にも様々な実装方法があると思いますが、勉強中の方の理解のとっかかりになれば嬉しく思います。</p>\n<p>用語の定義など含め、ご指摘事項などあれば <a href=\"https://twitter.com/oshima_123\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Twitter</a> の DM などでいただけますと幸いです。</p>\n<h2 id=\"参考書籍\" style=\"position:relative;\"><a href=\"#%E5%8F%82%E8%80%83%E6%9B%B8%E7%B1%8D\" aria-label=\"参考書籍 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>参考書籍</h2>\n<ul>\n<li><a href=\"https://amzn.to/3FeJ4yy\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">エンタープライズアプリケーションアーキテクチャパターン</a></li>\n<li><a href=\"https://amzn.to/3eOykZa\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">エリック・エヴァンスのドメイン駆動設計</a></li>\n<li><a href=\"https://amzn.to/2ZNetFR\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">実践ドメイン駆動設計</a></li>\n<li><a href=\"https://amzn.to/3cmseB2\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">．ＮＥＴのエンタープライズアプリケーションアーキテクチャ　第２版</a></li>\n<li><a href=\"https://amzn.to/30DYXLI\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Clean Architecture</a></li>\n<li><a href=\"https://amzn.to/3AeR0MK\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ドメイン駆動設計入門 ボトムアップでわかる！ドメイン駆動設計の基本</a></li>\n<li><a href=\"https://amzn.to/32GGu3p\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">「実践ドメイン駆動設計」から学ぶDDDの実装入門</a></li>\n</ul>\n<p><a href=\"https://www.amazon.co.jp/dp/B01B5MX2O2?&linkCode=li1&tag=oshimayuki0d-22&linkId=7884eecb4f77a09490554e5e80b05ab9&language=ja_JP&ref_=as_li_ss_il\" target=\"_blank\"><img border=\"0\" src=\"//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B01B5MX2O2&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=oshimayuki0d-22&language=ja_JP\" ></a><img src=\"https://ir-jp.amazon-adsystem.com/e/ir?t=oshimayuki0d-22&amp;language=ja_JP&amp;l=li1&amp;o=9&amp;a=B01B5MX2O2\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\"></p>\n<p><a href=\"https://www.amazon.co.jp/dp/B00GRKD6XU?&linkCode=li1&tag=oshimayuki0d-22&linkId=e5bebe195262dc16be2ef0186c837ceb&language=ja_JP&ref_=as_li_ss_il\" target=\"_blank\"><img border=\"0\" src=\"//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B00GRKD6XU&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=oshimayuki0d-22&language=ja_JP\" ></a><img src=\"https://ir-jp.amazon-adsystem.com/e/ir?t=oshimayuki0d-22&amp;language=ja_JP&amp;l=li1&amp;o=9&amp;a=B00GRKD6XU\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\"></p>\n<p><a href=\"https://www.amazon.co.jp/dp/B00UX9VJGW?&linkCode=li1&tag=oshimayuki0d-22&linkId=fd4e4e0245294231d9b486e262c64c1d&language=ja_JP&ref_=as_li_ss_il\" target=\"_blank\"><img border=\"0\" src=\"//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B00UX9VJGW&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=oshimayuki0d-22&language=ja_JP\" ></a><img src=\"https://ir-jp.amazon-adsystem.com/e/ir?t=oshimayuki0d-22&amp;language=ja_JP&amp;l=li1&amp;o=9&amp;a=B00UX9VJGW\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\"></p>\n<p><a href=\"https://www.amazon.co.jp/dp/4822298485?&linkCode=li1&tag=oshimayuki0d-22&linkId=1f5d033f39a39b8b5125d5e9a06df697&language=ja_JP&ref_=as_li_ss_il\" target=\"_blank\"><img border=\"0\" src=\"//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=4822298485&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=oshimayuki0d-22&language=ja_JP\" ></a><img src=\"https://ir-jp.amazon-adsystem.com/e/ir?t=oshimayuki0d-22&amp;language=ja_JP&amp;l=li1&amp;o=9&amp;a=4822298485\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\"></p>\n<p><a href=\"https://www.amazon.co.jp/dp/B07FSBHS2V?&linkCode=li1&tag=oshimayuki0d-22&linkId=d5fa680059a8d97efd390bb0072f4ad1&language=ja_JP&ref_=as_li_ss_il\" target=\"_blank\"><img border=\"0\" src=\"//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B07FSBHS2V&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=oshimayuki0d-22&language=ja_JP\" ></a><img src=\"https://ir-jp.amazon-adsystem.com/e/ir?t=oshimayuki0d-22&amp;language=ja_JP&amp;l=li1&amp;o=9&amp;a=B07FSBHS2V\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\"></p>\n<p><a href=\"https://www.amazon.co.jp/dp/B082WXZVPC?&linkCode=li1&tag=oshimayuki0d-22&linkId=d41efaf2049af2e64b3cd75cd7802cb5&language=ja_JP&ref_=as_li_ss_il\" target=\"_blank\"><img border=\"0\" src=\"//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B082WXZVPC&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=oshimayuki0d-22&language=ja_JP\" ></a><img src=\"https://ir-jp.amazon-adsystem.com/e/ir?t=oshimayuki0d-22&amp;language=ja_JP&amp;l=li1&amp;o=9&amp;a=B082WXZVPC\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\"></p>\n<p><a href=\"https://www.amazon.co.jp/dp/B07S675HVM?&linkCode=li1&tag=oshimayuki0d-22&linkId=2ea832e09e739b30f288416d5eb39d98&language=ja_JP&ref_=as_li_ss_il\" target=\"_blank\"><img border=\"0\" src=\"//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&ASIN=B07S675HVM&Format=_SL110_&ID=AsinImage&MarketPlace=JP&ServiceVersion=20070822&WS=1&tag=oshimayuki0d-22&language=ja_JP\" ></a><img src=\"https://ir-jp.amazon-adsystem.com/e/ir?t=oshimayuki0d-22&amp;language=ja_JP&amp;l=li1&amp;o=9&amp;a=B07S675HVM\" width=\"1\" height=\"1\" border=\"0\" alt=\"\" style=\"border:none !important; margin:0px !important;\"></p>\n<h2 id=\"関連記事\" style=\"position:relative;\"><a href=\"#%E9%96%A2%E9%80%A3%E8%A8%98%E4%BA%8B\" aria-label=\"関連記事 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>関連記事</h2>\n<p>以下、自分が過去に書いた関連記事です。</p>\n<ul>\n<li><a href=\"https://qiita.com/os1ma/items/7a229585ebdd8b7d86c2\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">MVC、3 層アーキテクチャから設計を学び始めるための基礎知識</a></li>\n<li><a href=\"https://qiita.com/os1ma/items/25725edfe3c2af93d735\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">「ビジネスロジック」とは何か、どう実装するのか</a></li>\n<li><a href=\"https://qiita.com/os1ma/items/66fb47f229896b32b2e8\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">「Controller にビジネスロジックを書くな」の対応パターン</a></li>\n<li><a href=\"https://www.kanzennirikaisita.com/posts/what-is-service-class\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">「サービスクラス」は 3 種類ある</a></li>\n</ul>","fields":{"slug":"/posts/data-access-patterns","tagSlugs":["/tag/architecture/"],"autoRecommendPosts":["what-is-service-class","ddd-books","application-architecture-books","mlops-books"]},"frontmatter":{"date":"2021-12-01T02:09:43.952Z","description":"アプリケーション・アーキテクチャについて議論する中で、最近は DDD の戦術的設計やクリーンアーキテクチャなどがキーワードとして解説されることが多いです。\nこの記事では、データアクセスのパターンについて改めて整理し、よく見かける議論の 1 つである「Rails の ActiveRecord や Laravel の Eloquant による Repository の実装」についても考察してみます。","tags":["architecture"],"title":"データアクセスのパターンと、ActiveRecord や Eloquant による Repository の実装について","socialImage":null,"recommendPosts":null}}},"pageContext":{"slug":"/posts/data-access-patterns"}},"staticQueryHashes":["251939775","3942705351","401334301"]}