🦝

「LaravelのModel」=「モデル」ではない、という話

に公開

はじめに

「LaravelのModel」は、LaravelというWebアプリケーションフレームワークの世界の中ではもちろん「モデル」なのですが、Laravelの世界の外では「モデル」とはならないことが多々あります。Laravelでの開発しか経験していないと、ついつい「LaravelのModel」=「モデル」と捉えてしまいがちですが、具体的に何を「モデル」とするのかは、設計やアーキテクチャー、フレームワークなどによって変わるものです。

ドメイン駆動設計で見る「LaravelのModel」

では、「LaravelのModel」はLaravelの世界の外では何になるのか、という具体例として、ドメイン駆動設計に登場する用語を使うと「LaravelのModel」が何になるのかを見ていきます。

話を単純化するため、以下の2つのことができるだけの極めてシンプルなアプリケーションを作成することを考えてみてください。

  • 記事を作成する
  • 指定されたIDの記事を返す

ここでいう「記事(=Article)」も、「題名(=title)」と「本文(=body)」というただの文字列のプロパティを持っているだけのような、極めてシンプルなオブジェクトとしてください。

第1段階

上記のアプリケーションをLaravelで作成する場合、まずは \App\Models\Article という「LaravelのModel」を作り、その上で以下のような流れの処理を作ることになるはずです。

  • 記事を作成する
    1. ユーザーが作成したい「記事」の「題名」と「本文」を入力し、入力した内容を送信する
    2. コントローラーがユーザーが送信した内容を受け取る
    3. 受け取った内容で \App\Models\Article のインスタンスを作成し、保存する
    4. 保存した \App\Models\Article のインスタンスを使ってHTMLやJSONのデータを生成し、ユーザーに返す
  • 指定されたIDの記事を返す
    1. ユーザーが取得したい「記事」のIDを入力し、入力したIDを送信する
    2. コントローラーがユーザーが送信したIDを受け取る
    3. 受け取ったIDに対応する \App\Models\Article のインスタンスを取得する
    4. 取得した \App\Models\Article のインスタンスを使ってHTMLやJSONのデータを生成し、ユーザーに返す

第2段階

Laravelのアプリケーションのコードとしては上記のような処理を書けば十分だと思いますが、 3. の \App\Models\Article のインスタンスの保存や取得は、実際はデータベースに対して行われます。そしてこのデータベースに対して行われる操作は「Laravelのモデル」が内部的に行っているわけですが、このときの処理を分解すると、以下のようになります。

  • 記事を作成する
    1. ユーザーが作成したい「記事」の「題名」と「本文」を入力し、入力した内容を送信する
    2. コントローラーがユーザーが送信した内容を受け取る
    3. 受け取った内容で \App\Models\Article のインスタンスを作成する
    4. \App\Models\Article のインスタンスから、データベースにレコードを追加するSQL文を生成する
    5. 生成したSQL文を実行し、データベースにレコードを追加する
    6. 保存した \App\Models\Article のインスタンスを使ってHTMLやJSONのデータを生成し、ユーザーに返す
  • 指定されたIDの記事を返す
    1. ユーザーが取得したい「記事」のIDを入力し、入力したIDを送信する
    2. コントローラーがユーザーが送信したIDを受け取る
    3. 受け取ったIDに対応するレコードをデータベースから取得するSQL文を生成する
    4. 生成したSQL文を実行し、データベースからレコードを取得する
    5. 取得したレコードの内容で \App\Models\Article のインスタンスを作成する
    6. 作成した \App\Models\Article のインスタンスを使ってHTMLやJSONのデータを生成し、ユーザーに返す

第3段階

ドメイン駆動設計では、「記事」のようなオブジェクトのことを 「エンティティ」 と呼び、この「エンティティ」の保存や、保存した「エンティティ」の取得をする役割のものとして、 「リポジトリ」 というオブジェクトが登場します。

これらの用語を使って上記の処理を言い換えると、以下のようになります。

  • 記事を作成する
    1. ユーザーが作成したい「記事」の「題名」と「本文」を入力し、入力した内容を送信する
    2. コントローラーがユーザーが送信した内容を受け取る
    3. 受け取った内容で「記事エンティティ」のインスタンスを作成する
    4. 作成した「記事エンティティ」のインスタンスを「記事リポジトリ」に渡し、保存させる
      1. 「記事リポジトリ」が、受け取った「記事エンティティ」からデータベースにレコードを追加するSQL文を生成する
      2. 生成したSQL文を実行し、データベースにレコードを追加する
    5. 保存した「記事エンティティ」のインスタンスを使ってHTMLやJSONのデータを生成し、ユーザーに返す
  • 指定されたIDの記事を返す
    1. ユーザーが取得したい「記事」のIDを入力し、入力したIDを送信する
    2. コントローラーがユーザーが送信したIDを受け取る
    3. 受け取ったIDを「記事リポジトリ」に渡し、対応する「記事エンティティ」を取得させる
      1. 「記事リポジトリ」が、受け取ったIDに対応するレコードをデータベースから取得するSQL文を生成する
      2. 生成したSQL文を実行し、データベースからレコードを取得する
      3. 取得したレコードの内容で「記事エンティティ」のインスタンスを作成し、作成した「記事エンティティ」を返す
    4. 取得した「記事エンティティ」のインスタンスを使ってHTMLやJSONのデータを生成し、ユーザーに返す

\App\Models\Article という「LaravelのModel」がすべて「エンティティ」と「リポジトリ」に置き換わっていますが、処理の内容は本質的には何も変わっていません。このことから「LaravelのModel」は、ドメイン駆動設計の「エンティティ」と「リポジトリ」の性質や役割を1つにまとめたものだ、ということができます。

最後に

同じものを別の単語で表現する、別のものを同じ単語で表現する、あるいは1つのものを複数のものに分割して表現する、複数のものを1つにまとめて表現する、ということは日常生活でもよくありますが、ソフトウェアの開発では「モデル」という単語がよく登場し、何を「モデル」とするのかは設計やアーキテクチャー、フレームワークなどによってまちまちです。更に「モデル」はその中でもかなり根幹となる要素になることが多いので、「LaravelのModel」のイメージに縛られることなく「モデル」という単語の意味を捉えることが必要になります。

GitHubで編集を提案

Discussion