web-dev-qa-db-ja.com

データベーステーブルごとのモデル?

私はcodeigniterを使用しており、Modelメソッドを繰り返した同様の状況に陥っています。コントローラごとにモデルを作成しています。しかし、データベーステーブルごとにモデルを作成することは良い方法と考えられますか?そうすれば、メソッドが2回記述されることはありません。

コントローラーごとのモデルまたは共有されているいくつかの小さなモデルの代わり。

モデルメソッドget_user($ user_id)の例は、users_models.phpに記述できます...

これについて私が目にする欠点の1つは、単にcontrollername_models.phpではなく、いくつかのモデルを呼び出さなければならない可能性があることです。

コントローラからいくつかのメソッドが使用されない可能性がある複数のモデルをロードすると、パフォーマンスと速度に影響を与える可能性がありますか?これに取り組むための最良の方法は何でしょうか?

注:同様の質問がありますが、データベーステーブルごとのモデルの根拠については取り上げていません。

11
Howard Steff

テーブルごとのモデルは、クラス構造でデータベースを再作成しているだけだと私は言います。 貧血モデル と呼ばれ、アンチパターンと見なされます。これは、クラスがデータと動作の両方を持つことを目的としているためです。モデルを単一のテーブルに制限する場合、複数のテーブルのデータと動作を処理する必要があるコード(動作)をどこに配置しますか?その場合、コントローラーには、これらの「テーブル」モデルの1つ以上を使用するモデルが必要になります...したがって、最も基本的なアプリを除いて、このアプローチから得られるメリットはほとんどありません。

8
Marjan Venema

一般に、モデルはテーブルごとやコントローラーごとではなく、ビジネスオブジェクトごとに作成する必要があります。場合によっては、テーブル構造またはコントローラーとの1対1の関係かもしれませんが、必須ではありません。

あなたの例では、いくつかのコントローラーから呼び出される1つのusers_modelクラスがある場合があります。これは問題なく、時には望ましいことです。ただし、ほとんどの場合、users_modelクラスは複数のテーブルからデータを取得します。
たとえば、last_login_dateクラスのusers_modelプロパティは、(not must)を別のメインのusersテーブルと1対多の関係があるuser_auditテーブル。

また、ビジネスオブジェクトごとに1つのSQLテーブルがある場合、データベース構造が正規化されていない可能性が高いと言えます。

7
Dime

ビジネスオブジェクトごとにモデルを作成するというダイムの答えにほぼ同意します。ビジネスが解決しようとしている問題は、モデルクラスの作成方法を促進するはずです。実際には、テーブルごとに1つのモデルを作成することから始めるのがよいことがわかりました。適切に設計されたスキーマは、アプリケーションコードでモデル化する必要があるビジネスプロセス(ドメインモデルとも呼ばれる)を模倣している可能性があります。

オブジェクト/リレーショナルマッピングレイヤーを使用すると、ドメインモデルにデータベーススキーマと同じ関係が含まれ、データアクセスレイヤーを繰り返し呼び出す必要がなくなります。チェックアウト Eloquent PHPの例として。スキーマとドメインモデルの両方がビジネスプロセスをサポートするように設計されている必要があります。

これは、Marjan Venemaの回答の最初の部分につながります。

テーブルごとのモデルは、クラス構造でデータベースを再作成しているだけだと言います。これは貧血モデルとして知られており、アンチパターンと見なされています。

貧血領域モデル はアンチパターンです。 Venemaが示唆する「テーブルごとのモデル」は「データベースの再作成」と見なすことができますが、これだけが貧血ドメインモデルであると言うのはまったく正しくありません。

マーティン・ファウラーから:

Anemic Domain Modelの基本的な症状は、最初は赤面することで本物のように見えることです。ドメイン空間には名詞にちなんで名付けられたオブジェクトがあり、これらのオブジェクトは、真のドメインモデルが持つ豊富な関係と構造に関連付けられています。キャッチは、動作を見るときに発生し、これらのオブジェクトにはほとんど動作がないことに気付き、ゲッターのバッグとセッター。

(強調、私の)

貧血ドメインモデルの重要な要素は、ドメインモデルクラスに動作またはメソッドがないことです。

これは、クラスがデータと動作の両方を持つことを目的としているためです。モデルを単一のテーブルに制限する場合、複数のテーブルのデータと動作を処理する必要があるコード(動作)をどこに配置しますか?

ここでも、ドメインモデルが1つのテーブルにしかマッピングされていない場合でも、ドメインモデルに動作を設定できます。複数のテーブルに影響を与える動作は、実際には複数のテーブルにマッピングされる複数のオブジェクトに影響を与えます。 ドメイン駆動設計 は、Venemaが述べたまったく同じ問題へのアプローチです。「複数のテーブルからのデータと動作を処理する必要があるコード(動作)をどこに置くのですか?」

そして答えは Aggregate Root です。マーティンファウラーは次のように述べています。

集計は、ドメイン駆動設計のパターンです。 DDD集約は、単一のユニットとして扱うことができるドメインオブジェクトのクラスターです。例として、注文とその明細があります。これらは、別々のオブジェクトである必要がありますが、オーダーを(そのラインアイテムと一緒に)1つの集約として扱うと便利です。

(強調、私の)

「ドメインオブジェクトのクラスター」は、「複数のテーブルにマップするドメインモデル」と見なすこともできます。複数のテーブルに影響を与える動作は、集約ルート-複数のテーブルまたはオブジェクトに影響を与える「もの」をカプセル化するクラスで定義する必要があります。

もう一度、マーティン・ファウラーから:

多くの場合、集計には、単純なフィールドとともに複数のコレクションが含まれます。

OPの元の質問に答えるには:

...データベーステーブルごとにモデルを作成することをお勧めしますか?そうすれば、メソッドが2回記述されることはありません。

ここから始めるのが良いと思いますが、スキーマとオブジェクトモデルが100%一致している必要はないことに注意してください。オブジェクトモデルは、ビジネスルールの実装と適用にさらに注意する必要があります。スキーマは、ビジネスデータをモジュール化されたスケーラブルな方法で格納することに、より重点を置く必要があります。

does Controllerレイヤーに適合するView Modelと呼ばれるモデルのバリエーションがありますが、コントローラーごとのモデルは良い習慣ではありません。 モデルの表示 は、WebアプリケーションやGUIアプリケーションのフォームなど、特定の種類の表示に合わせてドメインモデルを再編成したものです。

3
Greg Burghardt