web-dev-qa-db-ja.com

OOP PHP:テーブルごとに各クラスを回避する方法

オンラインサービスプロバイダーのプロジェクトに取り組んでいます。

管理者、エージェント、顧客のテーブルと、都市、サービス、カテゴリ、サブカテゴリ、性別などのデータストレージのテーブルがあります。

admincustomeragentのクラスを作成しました。しかし、cityservicescategoryなどのクラスを作成するか、admincustomerおよびagent

注:-CRUDcityservicessub-categorycategoryテーブルに対してgender操作を実行したい。

データベース内のテーブルごとに1つのクラスを用意するとよいでしょうか。そうでない場合は、この状況を回避する方法を説明してください。データストレージにクラスの代わりに列挙型またはArrayListを使用できますか?

4
prasam mehta

それらを独自のクラス(都市、サービス、カテゴリ、サブカテゴリ、性別)に配置します。なんでだろう?データストレージとやり取りするクラスが多すぎるという懸念はありますか?

これらのエンティティのいずれかを拡張する場合は、顧客、エージェント、または管理者クラスを変更する理由はありません。これは、顧客が何らかのリスト/配列で多くの都市に関連付けられないことを意味するわけではありませんが、都市自体を管理することになると、なぜ顧客コードを気にする必要があるのでしょうか。都市を国、教区、または地方に関連付ける場合は、他のものを台無しにしないようにしてください。

数か月後、あなたまたは新規または追加の開発者が、カテゴリまたはサブカテゴリの動作を変更する必要がある場合があるので、それらのクラスから始めるのはかなり簡単ではないでしょうか?

データベースの設計ではなかった場合、どのように処理しますか? OOPの多くの支持者は、ビジネスロジックと要件が確立されるまでデータベース/ストレージの決定を延期することを提案します。

3
JeffO

別の視点から考えてみてください。特効薬のデザインはないことを思い出してください。

あなたのデザインで何を達成しようとしていますか?データを完全に一貫させるか、パフォーマンスを最適化しますか?

管理者、エージェント、顧客のテーブルと、都市、サービス、カテゴリ、サブカテゴリ、性別などのデータストレージのテーブルがあります。

管理者、エージェント、顧客は、ドメイン内のエンティティのように聞こえます。それらの周りにいくつかのビジネスロジックを実装するため、適切なクラスを定義することは理にかなっています。通常、このような各クラスのデータは、DBの単一のテーブル内に含まれています(派生エンティティの場合は当てはまりません)。

街の様子は違って見えるかもしれません。市には、参照toサービスやカテゴリ(正確にはこの関係の方向)などの国の名前など、いくつかのプロパティがありますか? DBから都市を削除しようとする場合、都市に関連付けられているすべての顧客を削除するか、少なくとも都市の削除を防ぐ必要がありますか?これらの質問の答えが「はい」の場合、都市にはいくつかのプロパティがあるため、ビジネスドメインのエンティティであり、クラスとして定義する必要があります。答えが「いいえ」で、ドメインの都市が都市の名前であることがわかっている場合は、都市をクラスとして定義する必要はありません。

プログラミングの観点から、$customer->getCity()->getName()(エンティティとして定義された都市)または$customer->getCity()(文字列として定義された都市)などを使用しますか?最初のケースでは、DBからの_$customer_のフェッチ中(熱心な戦略)またはgetCity()の呼び出し中(遅延戦略)のいずれかの時点で、常にJOINが発生します。 2番目のケースでは、市は顧客と同じテーブルにインライン化されるため、ORMを使用して10Kの顧客をフェッチするなど、一括操作のパフォーマンスが向上します。

わかりました。市は、問題のドメインを知らずに話し合うのはかなり複雑なエンティティですが、たとえば性別は、クラスとして定義する価値がありません。システムで性別を変更する頻度はどれくらいですか?あなたは本当にそれのためにCRUDが必要ですか、それとも十分な性別のリストを得ていますか?私の開発経験から、性別のリストに変更を加えることなく、3年間列挙型として性別を保持していました。列挙型として定義できるのはかなり安全な賭けです。

性別などの列挙型をプロパティに接続する具体的なメカニズムは、選択するフレームワークによって異なります。例えば。 in Doctrineあなたは https://github.com/fre5h/DoctrineEnumBundle/ を使用してプロパティの抽象列挙型を実装できます。列挙型の選択の具体的な値は、たとえば、キャッシュのウォームアップやアプリの初期化中のデータベース。

相互接続されたエンティティが多いほど、今後すべてのパフォーマンスの問題が発生することを覚えておいてください(すべてのクエリ中にJOINが実行されるため)。結局のところ、設計は進化する可能性があり、アプリケーションのあらゆる段階でデータベースを適切に設計すれば(少なくとも、ドメインを反映する主キーと外部キーがある場合)、データ移行の実行はそれほど難しくありません。アプリ/データベースの設計を開始する最良の方法は次のとおりです。

  1. 問題のドメインを理解します(存在するエンティティ、データフローなど)。
  2. ビジネスドメインのERDを構築します(このトピックに関する優れたスターターブックは、ヒューウィリアムズ、セイドタハゴギによる「Learning MySQL」かもしれません)。
  3. データベーススキーマの最初のバージョンを作成し、今後のビジネス要件に応じて時間とともに進化させます。
  4. データベース設計に適合するようにアプリとデータベースの接続コードを追加します(通常、データベースはコードよりも長く存続します)。

読むのに適したもう1つの本は、スコットW.アンブラー、プラモドクマールJ.サダラージュによる「データベースのリファクタリング:進化的データベースの設計」です。

TL; DRお持ちのツールに合わせてデザインを適合させないでください。代わりに、自分に適したデザインを作成してください問題領域とそれを実装するのに役立つツールを選択します。

これがいくつかの洞察を提供することを願っています。

1
metamaker

はい、通常、クラスとテーブルの間で1対1のマッピングを行うことをお勧めします。

あなたが言及するオブジェクトのタイプは、それらが「実際の」ものを表すという点で「エンティティオブジェクト」と見なされます。その多くは存在し、それぞれが異なるが必ずしも異なるデータではありません。

たとえば、データベースに多数の顧客がいて、コードで顧客を操作したい場合は、顧客オブジェクトをインスタンス化し、データベースからデータを入力して渡し、メソッドを呼び出します。

このルールに従わない他のタイプのオブジェクトを使用できます。たとえば、MailSenderService.SendMailToCity(City city)のようなメソッドを持つMailSenderServiceがあるとします。

MailSenderServiceテーブルは意味がありません。メールを送信するために使用されるいくつかのロジックを持つ1つのオブジェクトです。

1
Ewan