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


11

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

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

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

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

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

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

回答:


8

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


補遺のほんの少し-それはマーティン・ファウラーによってアンチパターンと考えられています。ここでフルストップ。彼はこのケースについてある程度の洞察を持っていますが、それが悪いことを意味しているわけではありません-God Objectとは異なり、それはほとんど常に悪いです。私はこれをアンチパターンとは全く考えていません。
T.サー

1
例として、「貧血モデル」はSOLIDに準拠しています-単一の目的(データの保存)を持つオブジェクトを持つことは本当に悪いことですか?私はファウラー氏が言う多くのことを尊重していますが、これはでたらめでした。
T. Sar

7

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

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

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


3

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

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

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

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

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

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

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

(強調、私の)

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

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

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

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

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

(強調、私の)

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

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

集合体には、単純なフィールドとともに、複数のコレクションが含まれることがよくあります。

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

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

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

ビューモデルと呼ばれるモデルの変動はあるものの、コントローラごとのモデルは、良い習慣ではないでしょうないコントローラー層にフィット。A ビューモデルは、ディスプレイの特定の種類に合わせてGUIアプリケーション内のWebページまたはフォームであることをドメインモデルの再編です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.