なぜエンティティオブジェクトが必要なのですか?[閉まっている]


139

現在受け入れられているエンタープライズアプリケーション設計パラダイムのメリットについて、正直で思慮深い議論が必要です。

エンティティオブジェクトが存在する必要があるとは思いません。

エンティティオブジェクトとは、「個人」、「アカウント」、「注文」など、アプリケーションのために構築する傾向がある典型的なものを意味します。

私の現在の設計哲学はこれです:

  • すべてのデータベースアクセスは、ストアドプロシージャを介して実行する必要があります。
  • データが必要なときはいつでも、ストアドプロシージャを呼び出して、SqlDataReaderまたはDataTableの行を反復処理します

(注:Java EEを使用してエンタープライズアプリケーションも構築しました。Javaの人は、.NETの例を同等のものに置き換えてください)

私は反OOではありません。エンティティではなく、さまざまな目的で多くのクラスを作成します。私が書くクラスの大部分は静的ヘルパークラスであることを認めます。

私はおもちゃを作っていません。複数のマシンに展開された大規模で大量のトランザクションアプリケーションについて話している。Webアプリケーション、Windowsサービス、Webサービス、b2bインタラクション、という名前を付けます。

ORマッパーを使用しました。いくつか書いた。私はJava EEスタック、CSLA、および他のいくつかの同等のものを使用しました。私はそれらを使用しただけでなく、本番環境でこれらのアプリケーションを積極的に開発および保守しました。

私は、エンティティオブジェクトは、私たちの邪魔になっていることを戦いテストされたという結論になってきた、と私たちの生活は次のようになりますので、それらなしではるかに簡単。

この単純な例を考えてみましょう。正しく機能していないアプリケーションの特定のページに関するサポートコールがあり、フィールドの1つが本来のように永続化されていない可能性があります。私のモデルでは、問題を見つけるために割り当てられた開発者がちょうど3つのファイルを開きます。ASPX、ASPX.CS、およびストアドプロシージャを含むSQLファイル。この問題は、ストアード・プロシージャー呼び出しのパラメーターが欠落している可能性があるため、解決に数分かかります。しかし、どのエンティティモデルでも、必ずデバッガを起動し、コードをステップ実行し始めると、Visual Studioで15〜20個のファイルが開かれることになります。スタックの一番下に降りるまでに、開始した場所を忘れてしまいました。頭の中にあるのは、一度に多くの物だけです。ソフトウェアは、不要なレイヤーを追加することなく、非常に複雑です。

開発の複雑さとトラブルシューティングは、私の不満の片側にすぎません。

次に、スケーラビリティについて話しましょう。

開発者は、データベースと対話するコードを作成または変更するたびに、データベースへの正確な影響を徹底的に分析する必要があることを理解していますか?開発コピーだけでなく、本番を模倣しているので、オブジェクトに必要な追加の列が現在のクエリプランを無効にし、1秒で実行されていたレポートが2分で完了していることがわかります。選択リストに単一の列を追加したためですか?そして、現在必要なインデックスが非常に大きいため、DBAがファイルの物理レイアウトを変更する必要があることがわかりました。

抽象化によって物理データストアから離れすぎてしまうと、拡張が必要な​​アプリケーションで大混乱が発生します。

私は熱狂的ではありません。Linq to Sql、ADO.NET EF、Hibernate、Java EEなどへの強いプッシュがあるので、私が間違っていると私は確信している可能性があります。それが何であるか、なぜ私は自分の考えを変える必要があるのか​​を本当に知りたいのです。

[編集]

この質問が再び突然アクティブになったようです。新しいコメント機能が追加されたので、いくつかの回答に直接コメントしました。お返事ありがとうございます。これは健全な議論だと思います。

おそらく、私がエンタープライズアプリケーションについて話していることをもっと明確にすべきでした。たとえば、誰かのデスクトップやモバイルアプリで実行されているゲームについてはコメントできません。

いくつかの同様の答えに対応して私がここで一番上に置かなければならないことの1つは、エンティティ/ ORMに移行する理由として、直交性と懸念の分離がよく引用されます。ストアドプロシージャは、私が考えることができる懸念の分離の最良の例です。ストアドプロシージャ以外のデータベースへのアクセスをすべて許可しない場合は、理論的にはデータモデル全体を再設計し、ストアドプロシージャの入力と出力を維持している限り、コードを壊さないようにすることができます。これらは契約によるプログラミングの完璧な例です( "select *"を避けて結果セットを文書化する限り)。

業界に長く住んでいて、長命のアプリケーションを扱ってきた人に聞いてください。データベースが存続している間に、アプリケーションとUIのレイヤーがいくつ消えてしまったのでしょうか。データを取得するためにSQLを生成する4つまたは5つの異なる永続化レイヤーがある場合、データベースのチューニングとリファクタリングはどれほど難しいですか?何も変更できません!ORMまたはSQLを生成するコードは、データベースを完全にロックします


あなたの質問を読んで、私たちは非常に似ています。私は何年もまったく同じことを疑問に思っています(サードパーティのエンティティフレームワーク、そして現在はMicrosoftのフレームワークについて聞いた後)
pearcewg

1
ビジネスロジックはヘルパーオブジェクトですか、それともストアドプロシージャですか?多くの人があなたが後者を言っていると思っているように思えます...しかしあなたが言っていると思うのは、コード化されたオブジェクトにまだビジネスロジックがあり、データベースから直接データを取得し、そのデータを使用しているということですORMまたはデータを保持するための特殊なオブジェクトへのマッピングではなく、私も同じように感じる傾向がありますが、現在EF4を評価して、それが価値があるかどうかを確認しています。
錬金術

「イノベーターの消費者は、しばしば、めちゃくちゃになる人たちです。」-経験を持った人
UğurGümüşhan

2500以上のSPROCを備えたシステムを継承しました。アプリケーションは、SPROCをアクティブ化し、その出力を理解するための単なる手段と見なされています。読み書きされるすべてのデータには、独自のSPROCがあります。制御の中心点はありません。それは恐ろしく、花崗岩と同じくらい順応性があります。データベースの最適化を検討しています。2500 SPROCSのおかげで私が私の立場になりました。よく整理されたドメインレイヤーと再利用可能なDALコードを備えたシステムと比較すると、見かけが悪く、サポートの悪夢です。単純な仕事は何時間もかかり、魂を破壊します。SPROCは高負荷または特殊な方法に使用する必要がありますIMO
trucker_jim '19年

「デバッグ」の例について:単体テストを使用すると、問題がどこにあるのかをはるかにすばやく知ることができます。
MarioDS 16

回答:


59

アプリケーションの「ロジック」がいかに複雑で、どこに実装したかが問題だと思います。すべてのロジックがストアドプロシージャにあり、アプリケーションがそれらのプロシージャを呼び出して結果を表示するだけの場合、エンティティオブジェクトの開発は確かに時間の無駄です。しかし、オブジェクトが相互に豊富な相互作用を持ち、データベースが永続化メカニズムにすぎないアプリケーションの場合、それらのオブジェクトを持つことには価値があります。

したがって、万能な答えはありません。開発者は、OOになりすぎようとすると、解決できない問題が発生する可能性があることに注意する必要があります。


クリストファー、別の質問からリンクしてこの質問を復活させたようです。「リッチインタラクション」とはどういう意味か、オブジェクトなしで実装するのは実際的ではないのではないか。
エリックZビアード

4
オブジェクトで実行できることはすべて、オブジェクトなしでも実行できます。OOの設計は、通常、OO以外の方法よりも「複雑な」ことを行うための方法よりもはるかに簡単であることがわかりますが、すべての人にとってうまくいくとは限りません。
クリストファージョンソン

同意します。「オブジェクトを使用するタイミング」の答えは、オブジェクトのプロパティがアクションまたはビジネスロジックの変更を必要とするかどうかによって異なります。たとえば、UserまたはPersonインスタンスには、PasswordとLoginNameがある場合があります。コードアクションは、それらの値に応じて変化します。逆にProductがある場合は、dbからDataSetを取得してGUIを構築するだけで表示(それ以上、他のアクションはありません)する必要があります。
ヨルダンゲオルギエフ

5
バランスがあります。宗教を避けて、うまくいくものを選びましょう。
ジェフデイビス

27

理論によると、非常にまとまりがあり、疎結合の実装が将来の方法であるとしています。

ですから、あなたはそのアプローチ、つまり懸念の分離に疑問を抱いていると思います。

私のaspx.csファイルはデータベースと対話し、sprocを呼び出し、IDataReaderを理解する必要がありますか?

チーム環境では、特にアプリケーションのaspx部分を扱う技術者の数が少ない場合、これらの人々がこの要素に「触れる」ことができる必要はありません。

ドメインをデータベースから分離することで、データベースの構造的な変更から保護されます。確かにデータベースの有効性は絶対に重要です。そのため、システムの残りの部分にできるだけ影響を与えずに、その分野で最も優れた人が1か所でその問題に対処できるようにします。

私があなたのアプローチを誤解していない限り、データベースの1つの構造変更は、アプリケーションの表面に大きな影響を与える可能性があります。この懸念の分離により、私と私のチームはこれを最小限に抑えることができます。また、チームの新しいメンバーは、このアプローチをよりよく理解する必要があります。

また、あなたのアプローチはあなたのデータベースに常駐するようにあなたのアプリケーションのビジネスロジックを提唱しているようですか?これは私には間違っていると感じます。SQLはデータのクエリに本当に優れており、ビジネスロジックを表現するのではなく、私には不利です。

しかし、興味深い考えですが、aspxのSQLからは一歩離れているように感じますが、これは、私の古い古くて構造化されていないASP日から、恐怖でいっぱいになっています。


コードビハインド全体に多くの動的SQLを散在させることは悪いことだと私は同意します。Db呼び出しを明確かつ明確に保つ必要があります。静的ヘルパーメソッドでsproc呼び出しをラップすると、ORMルートをずっと下に行くことなく、一種の分離を実現できます。
Eric Z Beard

1
私はASP環境で働いたことはありませんが、それほど技術的でない人々はクライアントサイドのJavaScriptコードで靴下を吹き飛ばすでしょう、それは技術的なバックへのどんなくだらないインターフェイスに関係なく美しいユーザーエクスペリエンスをもたらします-終わり。
2010

私はここであなたに同意し、私もクライアント側のJavaScriptをいくつか実行することが知られています。そのため、私が自分でそう言ったとしても、ユーザーエクスペリエンスはそれほど粗末ではありません。私は、バックエンドのインターフェースがくだらないものではなく、クライアント側のプログラマーが心配する必要がないと考えたいのです。
nachojammers

2
「これは私には間違っていると感じます。SQLはデータのクエリに本当に優れており、ビジネスロジックを表現するのとは異なります。」-たとえば、PL / SQLを使用しない限り、SQLの上に豊富なプログラミング言語が追加され(SQLと緊密に統合され)、コードはデータベース内に格納されます。ネットワークのラウンドトリップを回避することにより、パフォーマンスを向上させます。また、どのクライアントがデータベースに接続するかに関係なく、ビジネスロジックをカプセル化します。
ObiWanKenobi 2010

25

1つの理由-ドメインモデルをデータベースモデルから分離する。

私が行うことは、テスト駆動開発を使用するため、最初にUIおよびモデルレイヤーを記述し、データレイヤーをモック化して、UIおよびモデルがドメイン固有のオブジェクトを中心に構築され、その後、これらのオブジェクトを、使用しているテクノロジーにマッピングしますデータレイヤー。データベース構造にアプリケーションの設計を決定させるのは悪い考えです。可能な場合は最初にアプリを作成し、それがデータベースの構造に影響を与えるようにします。


9
少なくともエンタープライズアプリケーションについては、私は本当にそうは思わない。データはアプリケーションです。
Eric Z Beard

3
同じデータの2つの別個のモデルが必要なのはなぜですか?
Seun Osewa 2008

3
目的によっては、モデルの1つの解釈の方が適している場合があるためです。一部のロジックは、行よりもオブジェクトの方がはるかに優れています。
Wouter Lievens、

1
十分に実装されていないのは良い考えだと思います。
ジェフデイビス

21

私にとっては、データがどのように格納されるかについてアプリケーションに関心を持たせたくないのです。私はおそらくこれを言って平手打ちされるでしょう...しかしあなたのアプリケーションはあなたのデータではありません、データはアプリケーションの人工物です。私のアプリケーションでは、DataSet、DataTable、DataRowsなどのテクノロジーではなく、顧客、注文、アイテムの観点から考えてほしいと思います。

常に一定量の結合があることに同意しますが、結合は下向きではなく上向きに到達することを好みます。木の幹を変更するよりも、手足や葉を簡単に微調整できます。

クエリはアプリケーションの一般的なデータアクセスよりも少し厄介な傾向があるため、レポート用にsprocを予約する傾向があります。

私はまた、そのシナリオの早い段階で適切な単体テストを行うことで、1つの列が永続化されていなくても問題がないように思われる傾向があります。


3
「あなたのアプリケーションはあなたのデータではなく、データはアプリケーションの成果物です。」-アプリケーションはデータがなければ価値がありません。データはアプリケーションなしで大きな価値があります。アプリケーションは常に行き来し(書き直され)、重要なアプリケーションのデータは常に保持されます。そして、データモデルは、時間の経過とともに驚くほど安定しています。
ObiWanKenobi 2010

16

エリック、あなたはもう行きません。本当にスケーラブルで、メンテナンスが簡単で、堅牢なアプリケーションの場合、唯一の真の答えは、すべてのゴミを省き、基本に固執することです。

私のキャリアも同様の軌跡をたどり、同じ結論に達しました。もちろん、私たちは異端者であると考えられており、おかしいです。しかし、私のものは機能し、うまく機能します。

コードのすべての行を疑って見る必要があります。


2
確かに、それは確かにいますが、人員のトンが資源をanjd得たときにうまく動作しますが、私はあなたが考える1人のチームであれば、「新しい」技術は、多くのことを助けることができると思います...
カール・Hörberg

10

あなたが提案したものに似た例で答えたいと思います。

私の会社では、製品の簡単なCRUDセクションを作成する必要があり、すべてのエンティティと個別のDALを作成しました。その後、別の開発者は関連テーブルを変更する必要があり、さらにいくつかのフィールドの名前を変更しました。フォームを更新するために変更する必要があった唯一のファイルは、そのテーブルのDALでした。

(私の意見では)エンティティがプロジェクトにもたらすものは次のとおりです。

直交性:1つのレイヤーでの変更は他のレイヤーに影響しない場合があります(もちろん、データベースに大きな変更を加えた場合、すべてのレイヤーに波及しますが、ほとんどの小さな変更は影響しません)。

テスト容易性:データベースに触れずにロジックをテストできます。これにより、テストのパフォーマンスが向上します(テストをより頻繁に実行できるようになります)。

懸念の分離:大きな製品では、データベースをDBAに割り当てることができます。DBAはデータベースを完全に最適化できます。モデルの設計に必要な知識を持つビジネスエキスパートにモデルを割り当てます。個々のフォームを、Webフォームなどの経験が豊富な開発者に割り当てます。

最後に、ほとんどのORMマッパーがストアドプロシージャをサポートしていることを追加したいと思います。

乾杯。


2
ストアドプロシージャは、おそらく、直交性と関心事の分離の最良の例です。正しく使用すると、データベースが完全にカプセル化されます。
Eric Z Beard

1
@Eric Z Beard:はい。ただし、ストアドプロシージャ内のロジックのみを分離しながら、ストアドプロシージャに関するユニットテストを作成するにはどうすればよいですか。ストアドプロシージャはデータベースと緊密に結合されており、ほとんどのORMタイプはそれを好みません。ストアドプロシージャの単体テストを作成するには、データベースに存在する特定のデータに依存する必要があります。また、データに依存しない限り、このテストを繰り返し実行することはできません。作成するテストは、単体テストではなく、統合テストになります。
7wp、2009年

8

私はあなたがこのトピックについて「あなたが噛むことができるよりも多く噛んでいる」かもしれないと思います。テッドニューアードは、それを「コンピュータサイエンスのベトナム」と呼んでいたとき、軽率ではありませんでした。

無数にある他のブログ、フォーラム、ポッドキャストなどで頻繁に証明されているように、私があなたに絶対に保証できることの1つは、問題に関する誰の見方も変えないということです。

議論の余地のあるトピックについてオープンなディスカッションとディベートを持っていることは確かに問題ありません。これは、これが何度も行われただけで、両方の「側面」が同意せず、ソフトウェアの作成に取り掛かっただけです。

両側でさらに読みたい場合は、テッドのブログ、Ayende Rahein、Jimmy Nilson、Scott Bellware、Alt.Net、Stephen Forte、Eric Evansなどの記事を参照してください。


1
そうですね、ほとんどの人は意見を変えません。Stack Overflowの焦点は客観的な質問になっていることに気づきましたが、主観的な質問はとても楽しいです!個人的に、私はこの議論から多くを学びました。
エリックZビアード

さまざまなアプローチはコンテキスト固有であり、この議論は、どのシナリオがさまざまな永続モデルに利益をもたらすか、または損なうかを明確にするのに役立つと私は思います。トピックの専門家が意見をすぐに変えることはありませんが、これは人々が他の経験を求める質問サイトです。
TheXenocide 2008

ワオ。+1は、ORMと非ORMのトピックについての優れた紹介がある「コンピュータサイエンスのベトナム」の記事へのリンクです。
lambacck 2010

7

@ダン、申し訳ありませんが、それは私が探しているようなものではありません。私は理論を知っています。「非常に悪い考えです」という発言は、実際の例では裏付けられていません。私たちは、より少ない時間で、より少ない人数で、より少ないミスでソフトウェアを開発することを試みており、簡単に変更を加える能力を求めています。あなたのマルチレイヤーモデルは、私の経験では、上記のすべてのカテゴリでネガティブです。特に、データモデルを最後にすることに関して。物理データモデルは、1日目からの重要な考慮事項である必要があります。


うわー、これについて私のように考える誰か...私のアプリはほとんど常にデータの操作に関するものです、それが彼らが実際に行うことです。
錬金術

これらの機能が利用できるようになったので、これはコメントとしてより良いでしょう
Casebash

1
知識を失ったことは許してください。しかし、これはよくある質問であり、あなたが犯した間違いはよくあるものなので、指摘した方がいいと思いました。「少ない時間」は正しいですが、「少ない人」と「少ないミス」は「少ない人」と「少ないミス」であるべきです。小麦粉が少ない場合は、クッキーを少なくすることができます。(また、小麦粉を使いすぎると、あまりにも多くのCookieが作成されます。これは、あまり一般的に見過ごされがちな区別です。)繰り返しますが、私の謝罪です。ただ役に立とうとしているだけです。
WCWedin、2011年

4

あなたの質問は本当に興味深いものでした。
通常、アプリケーションのビジネスロジックをカプセル化するエンティティオブジェクトが必要です。このロジックをデータレイヤーにプッシュするのは本当に複雑で不十分です。
これらのエンティティオブジェクトを回避するにはどうしますか?どのような解決策を考えていますか?


これはコメントとしてより良いでしょう
Casebash

4

エンティティオブジェクトは、アプリケーション層でのキャッシュを容易にします。データリーダーのキャッシュを頑張ってください。


4

また、エンティティとは何かという概念についても話し合う必要があります。この議論を読むと、ここにいるほとんどの人が貧血ドメインモデルの意味でエンティティを検討しているように見えます。多くの人々が貧血ドメインモデルをアンチパターンとして考えています!

リッチドメインモデルには価値があります。それがドメイン駆動設計のすべてです。私は個人的に、OOが複雑さを克服する方法であると信じています。これは、技術的な複雑さ(データアクセス、UIバインディング、セキュリティなど)だけでなく、ビジネスドメインの複雑さも意味します

ビジネス上の問題を分析、モデル化、設計、および実装するためにOO手法を適用できる場合、これは重要なアプリケーションの保守性と拡張性にとって非常に大きな利点です。

エンティティとテーブルの間には違いがあります。エンティティはモデルを表す必要があり、テーブルはモデルのデータアスペクトを表すだけです!

データはアプリよりも長く存続することは事実ですが、David Laribeeの次の引用を考慮しください。モデルは永久に存在します...データは幸せな副作用です。

このトピックに関するいくつかのリンク:


1
率直に言って、私はビジネスの真の理解に沿ってソフトウェアを設計することにほとんど注意が払われていないため、データがその周りのソフトウェアよりも長く存続すると信じ始めています。
flq 2009年

4

本当に面白い質問です。正直なところ、エンティティが優れている理由を証明できません。しかし、私はそれらが好きな理由を共有できます。のようなコード

void exportOrder(Order order, String fileName){...};

順序がどこから来たのかは関係ありません-DB、Webリクエスト、ユニットテストなどから。これにより、このメソッドは、DataRowを取得して期待する列とその型をドキュメント化する代わりに、正確に何が必要かを明確に宣言します。あります。ストアドプロシージャとして何らかの方法で実装する場合も同じです。レコードIDをプッシュする必要がありますが、DBに存在する必要はありません。

このメソッドの実装は、注文の抽象化に基づいて行われ、DBでの正確な表現に基づいて行われるのではありません。私が実装したそのような操作のほとんどは、実際にこのデータがどのように格納されるかに依存しません。一部の操作では、パフォーマンスとスケーラビリティの目的でDB構造との結合が必要であることを理解しています。私の経験では、操作の数は多くありません。私の経験では、Personが.getFirstName()がStringを返し、.getAddress()がAddressを返し、アドレスが.getZipCode()などを持っていることを知っていれば十分ですが、どのテーブルがそのデータを格納するために組み込まれているかは気にしません。 。

追加の列の区切りがパフォーマンスを報告するときなど、説明したような問題に対処する必要がある場合、タスクにとってDBは重要な部分であり、実際にできる限りそれに近いはずです。エンティティはいくつかの便利な抽象化を提供できますが、重要な詳細も隠すことができます。

スケーラビリティはここで興味深い点です-非常に高いスケーラビリティ(facebook、livejournal、flickrなど)を必要とするほとんどのWebサイトは、DBができるだけ使用されず、キャッシュ、特にRAMの使用によってスケーラビリティの問題が解決される場合、DB-asceticアプローチを使用する傾向があります。http://highscalability.com/には、興味深い記事がいくつかあります。


2
エンタープライズアプリケーションのスケーラビリティは、多くの場合、数百万行のテーブルのトランザクションデータを頻繁に変更するため、キャッシュでは解決できません。私はfacebookを見ます。al。大量のWebサイトと同様に、困難な部分が非常に多くのWebリクエストに対応しています。
エリックZビアード

4

抽象化と疎結合以外にも、エンティティオブジェクトには他にも理由があります。私が最も好きなことの1つは、DataReaderまたはDataTableでは取得できない強力なタイピングです。もう1つの理由は、適切なエンティティクラスを使用すると、フィールド名を使用した一連の文字列ではなく、コードを見ている人が理解しやすいドメイン固有の用語にファーストクラスのコンストラクトを使用することで、コードをよりメンテナンスしやすくなるためです。 DataRowのインデックスを作成します。ストアドプロシージャは、多くのマッピングフレームワークがsprocにマップする機能を提供するため、ORMの使用と実際に直交しています。

私はsprocs + datareadersを優れたORMの代わりとは考えていません。ストアドプロシージャを使用すると、呼び出し側のコードとは異なる型システムを使用するプロシージャの型シグネチャによって制約され、緊密に結合されます。ストアドプロシージャは、追加のオプションやスキーマの変更に対応するために変更される可能性があります。スキーマが変更される可能性がある場合のストアドプロシージャの代わりに、ビューを使用することができます。オブジェクトをビューにマップし、変更時にビューを基になるテーブルに再マップできます。

あなたの経験が主にJava EEとCSLAで構成されている場合、私はORMへの嫌悪を理解できます。LINQ to SQLは非常に軽量なフレームワークであり、主にデータベーステーブルとの1対1のマッピングですが、本格的なビジネスオブジェクトになるためには通常、わずかな拡張が必要です。LINQ to SQLは、入出力オブジェクトをストアドプロシージャのパラメーターと結果にマップすることもできます。

ADO.NETエンティティフレームワークには、データベーステーブルを相互に継承するエンティティクラス、または単一のエンティティに集約された複数のテーブルの列として表示できるという追加の利点があります。スキーマを変更する必要がある場合は、実際のアプリケーションコードを変更せずに、概念モデルからストレージスキーマへのマッピングを変更できます。ここでも、ストアドプロシージャを使用できます。

アプリケーションのスケーラビリティの問題よりも、コードの保守性が悪い、または開発者の生産性が低いため(たとえば、sproc書き込みとアプリ書き込みのコンテキスト切り替えが原因で発生する可能性がある)、企業のITプロジェクトの失敗が増えると思います。


ORMをストアドプロシージャにマッピングするのはよい妥協策だと思います。ただし、これは簡単にうまく行えない場合があります。各テーブルに4つのCRUDプロシージャを作成しただけでは、何も達成されていません。大きく粗いプロシージャをエンティティにマッピングできますか、それとも実際にはどこにも行きませんか?
Eric Z Beard

CRUD操作に加えて、Microsoft ORMを使用すると、エンティティクラスにメソッドを追加できます。エンティティクラスには、スローするストアドプロシージャに直接マップします(すべての入出力タイプがマップ可能である場合)。
マークシダーデ

3

また、両方のモデルを分離すると、アプリケーションを異なるデータベースサーバーまたはデータベースモデルでさえ実行できるようになるというDanの回答にも付け加えておきます。


3

複数のWebサーバーを負荷分散してアプリをスケーリングする必要がある場合はどうなりますか?すべてのWebサーバーに完全なアプリをインストールすることもできますが、より良い解決策は、Webサーバーにアプリケーションサーバーと通信させることです。

ただし、エンティティオブジェクトがない場合、それらについて話す必要はあまりありません。

シンプルで内部的な短寿命のアプリケーションの場合、モノリスを作成するべきではないと言っているのではありません。しかし、それが適度に複雑になるか、かなりの時間続くとすぐに、優れたデザインについて考える必要があります。

これはそれを維持することになると時間を節約できます。

アプリケーションロジックをプレゼンテーションロジックとデータアクセスから分割し、それらの間でDTOを渡すことにより、それらを分離します。個別に変更できるようにする。


3
多くの人々が分離を引き起こし、1つの層が他の層に影響を与えることなく変更できるようにしています。ストアドプロシージャは、これを他のORMよりも優れています。データモデルを根本的に変更でき、プロシージャが同じデータを返す限り、何も壊れません。
Eric Z Beard

2
私の意見では、ストアドプロシージャとエンティティモデルは相互に排他的ではありません。ストアドプロシージャは、エンティティモデルを格納するメカニズムを提供できます。問題は、ビジネスロジックがエンティティで機能するか、ストアドプロシージャに直接アクセスするかです。
jbandi 2008年

3

あなたはこれを見つけるかもしれませんcomp.objectに関する投稿は興味深い。

私は賛成または反対を主張しているわけではありませんが、それは興味深く、(私は)このトピックに関連しています。


それは素晴らしい投稿です。ORMについての私の考えをほぼ完全に要約します。
エリックZビアード

3

質問:すべてのビジネスロジックがデータベースに閉じ込められている場合、切断されたアプリケーションをどのように処理しますか?

私が関心を持っているエンタープライズアプリケーションのタイプでは、複数のサイトを処理する必要があります。それらのサイトのいくつかは、切断された状態で機能できる必要があります。
ビジネスロジックが、さまざまな種類のアプリケーションに簡単に組み込むことができるドメインレイヤーにカプセル化されている場合dll、ビジネスルールを認識し、必要に応じてローカルに適用できるアプリケーションを構築できます。

データベースのストアドプロシージャでドメインレイヤーを維持するには、データベースへの永続的な見通しを必要とする単一のタイプのアプリケーションに固執する必要があります。

特定のクラスの環境では問題ありませんが、エンタープライズアプリケーション全体を網羅しているわけではありません。


2

@jdecuyper、私がよく繰り返している格言の1つは、「ビジネスロジックがデータベースにない場合、それは単なる推奨事項です」です。ポール・ニールソンは彼の本の中でそれを言ったと思います。アプリケーションレイヤーとUIは出入りしますが、データは通常、非常に長期間存在します。

エンティティオブジェクトを回避するにはどうすればよいですか?主にストアドプロシージャ。また、ビジネスロジックは、意図したかどうかにかかわらず、アプリケーションのすべてのレイヤーに到達する傾向があることも認めます。ある程度のカップリングは固有であり、不可避です。


同意しますが、アプリケーションに含まれるビジネスロジックは、データを入力、削除、または変更する他の方法を説明できないことがよくあります。これは通常、データの整合性の問題を引き起こします。
HLGEM 2008

また、オブジェクトワールドとリレーショナルワールドの間の不一致を処理するために、常にサービスレイヤーを使用する必要があるのはなぜですか。ビジネスロジックがすべてのレイヤーに流れ込むことは、避けられないことではありません。
cdaq

2

最近、同じことをよく考えています。私はしばらくの間CSLAのヘビーユーザーでしたが、「すべてのビジネスロジック(または少なくとも合理的に可能な限り)はビジネスエンティティにカプセル化されている」と純粋に言っています。

ビジネスエンティティモデルは、データベースの設計がデータの操作方法と異なる場合に多くの価値を提供することを見てきました。これは、多くのビジネスソフトウェアの場合です。

たとえば、「顧客」のアイデアは、顧客テーブルのメインレコードと、顧客が行ったすべての注文、顧客のすべての従業員とその連絡先情報、および顧客とその子は、ルックアップテーブルから決定できます。ビジネスの観点から見ると、顧客の概念にはこれらのすべてが含まれており、関係がデータベースに適用される場合とされない場合があるため、開発の観点からは単一のエンティティとして顧客と連携できるのは本当に素晴らしいことです。

「ビジネスルールがデータベースにない場合、それは単なる提案である」という引用に感謝しますが、ビジネスルールを適用するようにデータベースを設計するのではなく、効率的で高速で正規化されたデータベースを設計する必要があると思います。

とはいえ、他の人が上で述べたように、「完璧なデザイン」は存在せず、ツールは仕事に適合しなければなりません。ただし、ビジネスエンティティを使用すると、ビジネスロジックを変更する場所がわかり、オブジェクトが現実世界の概念を直感的な方法でモデル化できるため、メンテナンスと生産性の向上に役立ちます。


2

エリック、

誰もがあなたが望むフレームワーク/アプローチを選択するのを妨げるものはありません。「データドリブン/ストアドプロシージャによる」パスを使用する場合は、ぜひお試しください。特にそれが本当にあれば、アプリケーションを仕様どおりに、時間通りに提供するのに役立ちます。

警告は(質問の裏返しです)、すべてのビジネスルールはストアドプロシージャに基づいている必要があり、アプリケーションはシンクライアントにすぎません。

そうは言っても、OOPでアプリケーションを実行する場合は同じルールが適用されます。OOPの理念に従います。これには、ドメインモデルを表すエンティティオブジェクトの作成含まれます。

ここでの唯一の本当のルールは一貫性という言葉です。誰もあなたをDB中心にすることを止めません。昔ながらの構造化(別名、機能的/手続き的)プログラムの実行を止める人はいません。地獄、誰もが誰かがCOBOLスタイルのコードを実行するのを止めているわけではありません。しかし、アプリケーションがある程度の成功を収めるには、このパスをたどると、非常に一貫性のあるアプリケーションである必要があります。


アプリ全体の一貫性に同意します。正直なところ、私はしばらく前に現在のプロジェクトの方向を変更しましたが、元のモデルを100%修正することはできず、混乱を招きました。良い決定は、早期に行うのが最善です。
Eric Z Beard

確かにエリック。私はかつてOOP熱狂者でしたが(このスレッドの他の人がそうであるように)、DB駆動のアプリの販売で非常に成功している会社を経営している人に会いました。それは私の世界を揺さぶった。私はまだOOP / TDDのマニアですが、DB中心のことはもう嫌いではありません。
Jon Limjap

問題は、時々人々が彼らのイデオロギーを過剰に売り、あなたがそれらをクランクアウトするための良い方法論を持っているならば、あなたは潜在的にhtmlとjavascriptのみのサイトを売って生計を立てることができるということです。
マークロジャース

2

「エンタープライズアプリケーション」について何を考えているのか本当にわかりません。しかし、RDBMSが適切に設定され、システムが内部または外部にかかわらず他のシステムと相互運用可能である必要がない内部アプリケーションとしてそれを定義しているという印象を受けています。

しかし、基本的なCRUD操作のためだけに各テーブルの4つのストアドプロシージャに相当する100のテーブルを持つデータベースがあり、400のストアドプロシージャであり、維持する必要があり、厳密に型指定されていないため、タイプミスの影響を受けたり、ユニットテストを実行できない場合はどうでしょうか。 。オープンソースエバンジェリストであり、RDBMSをSQL ServerからMySqlに変更したい新しいCTOを取得した場合はどうなりますか?

エンタープライズアプリケーションでも製品でもSOAを使用していて、Webサービスを公開するためのいくつかの要件がある今日のソフトウェアの多くは、少なくとも私が関与しているソフトウェアが関与しています。あなたのアプローチを使用すると、シリアル化されたDataTableまたはDataRowsを公開することになります。これで、クライアントが.NETであり、内部ネットワーク上にあることが保証されている場合、これは許容できると見なされます。ただし、クライアントが不明な場合は、直感的なAPIの設計に努める必要があり、ほとんどの場合、フルデータベーススキーマを公開する必要はありません。DataTableとは何か、それをどのように使用するかをJava開発者に説明したくありません。Bandwithとペイロードサイズ、およびシリアル化されたDataTablesの考慮事項もあります。DataSetsは非常に重いです。

ソフトウェア設計には特効薬はありません。それは、優先順位がどこにあるかに依存します。私にとっては、ユニットテスト可能なコードと、どのクライアントでも簡単に使用できる疎結合コンポーネントにあります。

ちょうど私の2セント


いいえ、エンタープライズアプリケーションの私の定義は反対です。スキーマは頻繁に変更され、dbを使用する多くのアプリケーションがあり、多くの外部パートナーと相互運用します。では、実際の企業のアプリ、あなたがなり、これまでに、これまで決して別のRDBMSに変更はありません。それは起こりません。
エリックZビアード

また、各テーブルに4つのプロシージャを作成することは悪い習慣です。ORMから生成されたsqlのように、データモデルと密接に結合するため、何も購入されません。プロシージャは、各テーブルのCRUDだけでなく、大まかなビジネスオペレーションである必要があります。
エリックZビアード

しかし、これが答えではありませんか?:記述する必要のあるコードが多いほど、大規模なプログラミングサポートのための機能が必要になります。カプセル化、文字列型付け、リファクタリング、洗練されたスタイルとエラーチェックなど。Javaと.NETはこの分野で豊富なサポートを提供していますが、ストアドプロシージャ言語はサポートしていません。
reinierpost 2009

2

OOとRDBの間の距離の問題に別の角度を提供したいと思います。それは履歴です。

どのソフトウェアにも、ある程度の現実の抽象化である現実のモデルがあります。現実の複雑さをすべて把握できるコンピュータプログラムはありません。プログラムは、現実からの一連の問題を解決するためだけに書かれています。したがって、どのソフトウェアモデルも現実を縮小したものです。時々、ソフトウェアモデルは現実を強制的に減少させます。レンタカー会社に青くて合金がある限り、どんな車でも予約してもらいたいが、要求がコンピューターに収まらないためにオペレーターが対応できないときのように。

RDBは、アカウンティングと呼ばれる、情報をテーブルに入れるという非常に古い伝統に基づいています。会計は紙で、次にパンチカードで、そしてコンピューターで行われた。しかし、会計はすでに現実の縮小です。会計は人々にそのシステムに従うことを余儀なくさせ、それが現実に受け入れられるようになりました。これが、会計用のコンピュータソフトウェアを作成するのが比較的簡単な理由です。会計は、コンピュータが登場するずっと前から情報モデルを持っていました。

優れた会計システムの重要性と、あらゆるビジネスマネージャーからの受け入れを考えると、これらのシステムは非常に高度になっています。データベースの基盤は非常に堅固になり、重要なデータを信頼できるものに保管することをためらうことはありません。

OOは、現実の他の側面が会計処理(すでにモデル化されている)よりもモデル化するのが難しいことに気付いたときに生まれたはずだと思います。OOは非常に成功したアイデアになりましたが、OOデータの永続性は比較的未発達です。RDB /アカウンティングは簡単に成功しましたが、オブジェクト指向ははるかに大きなフィールドです(基本的にはアカウンティングではないすべてのものです)。

私たちの多くはオブジェクト指向を使用したいと思っていましたが、それでもデータを安全に保管したいと考えています。尊敬される会計システムと同じ方法でデータを保存するよりも安全なものは何ですか?それは魅力的な展望ですが、私たちは皆同じ落とし穴に遭遇します。会計の伝統と地位の恩恵を受けてきたRDB業界による多大な努力と比較して、OOの永続性について考えるのに苦労した人はほとんどいません。

Prevaylerとdb4oはいくつかの提案です。聞いたことのない他のものも確かにありますが、たとえば休止状態のようにマスコミの半分を獲得しているようには見えません。

古き良きファイルにオブジェクトを保存することは、マルチユーザーアプリケーション、特にWebアプリケーションでは真剣に受け止められていないようです。

OOとRDBの間の裂け目を閉じるための毎日の闘いの中で、私はOOをできるだけ使用しますが、継承を最小限にとどめるようにしています。SPはあまり使用しません。アカウンティングのように見える側面でのみ、高度なクエリを使用します。

割れ目が完全に閉じているとき、私は喜んで喜ばれるでしょう。Oracleが「Oracle Object Instance Base」のようなものを起動するときに、ソリューションが来ると思います。本当に追いつくために、それは心強い名前を持たなければならないでしょう。


OOが有用であると見なされるためにORMは必要ないと思います。私はストアドプロシージャを使用し、多くの静的ヘルパークラスをコードに記述していますが、これらのクラスは、オブジェクトの素晴らしいコレクションである膨大な.NETフレームワークに基づいて構築されています。
Eric Z Beard

あなたの論理は理にかなっていますが、私はその前提が健全であるとは思いません。RDBでマッピングできないものは聞いたことがありません。
ジェフデイビス

1

現時点ではそれほど時間はかかりませんが、頭のてっぺんから...

エンティティモデルを使用すると、ストアドプロシージャのインターフェイスで実行できることを超えて、データベース(および他の可能なシステム)に一貫したインターフェイスを提供できます。全社規模のビジネスモデルを使用することで、すべてのアプリケーションがデータに一貫して影響することを確認できます。これは非常に重要なことです。そうしないと、悪いデータになってしまいます。これは単なる悪です。

アプリケーションが1つしかない場合、そのアプリケーションやデータの大きさに関係なく、実際には「エンタープライズ」システムはありません。その場合、あなたが話しているのと同じようなアプローチを使うことができます。将来システムを拡張することにした場合に必要となる作業に注意してください。

ただし、次の点に注意してください(IMO)。

  1. 生成されたSQLコードは不良です(例外が続く)。申し訳ありませんが、多くの人が時間を大幅に節約できると思っていることは知っていますが、私が書いたものよりも効率的なコードを生成できるシステムは見当たりません。また、使用されないSQLコードを大量に生成することもよくあります。ここでの例外は、ルックアップテーブルなどの非常に単純なパターンです。でも多くの人が夢中になっています。
  2. エンティティ<>テーブル(または必然的に論理データモデルエンティティ)。多くの場合、データモデルにはデータルールがあり、データベースのできるだけ近くに適用する必要があります。これには、テーブル行の相互関係に関するルールや、宣言型RIには複雑すぎる他の同様のルールを含めることができます。これらはストアドプロシージャで処理する必要があります。すべてのストアドプロシージャが単純なCRUDプロシージャである場合、それを行うことはできません。その上、CRUDモデルはネットワークを介したデータベースへの往復を最小限にしないため、通常、パフォーマンスの問題を引き起こします。多くの場合、これはエンタープライズアプリケーションの最大のボトルネックです。

生成されたSQLについて合意しました。それは常に解決する以上の問題を引き起こします。また、ストアドプロシージャを使用してCRUDレイヤーを単に作成することには大いに反対しています。プロシージャはできるだけ粗くす​​る必要があります。「1つのアプリケーション」の定義方法がわかりません。
エリックZビアード

1つのアプリケーションとは、組織内の1つのグループによって作成された1つのアプリケーションを意味します。私が今相談しているところでは、彼らは企業データベースを持っていて、それらの間の通信が制限された3つの異なるアプリケーションに取り組んでいる少なくとも3つの別々のグループによってアクセスされます。
トムH

1

場合によっては、アプリケーションとデータ層がそれほど密接に結合されていないことがあります。たとえば、電話の請求アプリケーションがあるとします。後で電話の使用状況を監視する別のアプリケーションを作成して、a)より適切に宣伝するb)電話プランを最適化します。

これらのアプリケーションにはさまざまな懸念事項とデータ要件があり(データが同じデータベースからのものであっても)、それらは異なる設計を推進します。データベースがコードを駆動するようにした場合、コードベースは(どちらのアプリケーションでも)完全な混乱と悪夢に陥る可能性があります。


1

ドメインロジックがデータストレージロジックから分離されているアプリケーションは、あらゆる種類のデータソース(データベースなど)またはUI(WebまたはWindows(またはLinuxなど))アプリケーションに適応できます。

現在のデータベースシステムに満足している会社の場合は、データベースにほとんど引っかかっています。ただし、データベースは時が経つにつれて進化するため、会社が使いたいと思っている本当にきちんとした新しいデータベースシステムが存在する可能性があります。データアクセスのWebサービスメソッドに切り替えたい場合はどうすればよいでしょう(サービス指向アーキテクチャーのように)。ストアドプロシージャをあちこちに移植しなければならない場合があります。

また、ドメインロジックはUIを抽象化します。これは、UIが進化し続けている大規模で複雑なシステムでは特に重要になる可能性があります(特に、常により多くの顧客を探している場合)。

また、ストアドプロシージャとドメインロジックの問題に対する明確な回答はないことに同意します。複雑なストアドプロシージャは複雑なドメインロジックよりも維持するのが難しいと思うので、私はドメインロジックキャンプにいます(そして、彼らは時間とともに勝っています)。しかし、それはまったく別の議論です


0

あなたは、特定の種類のアプリケーションを作成し、特定の種類の問題を解決することに慣れていると思います。「データベース優先」の観点からこれを攻撃しているようです。データがDBに保持される開発者はたくさんいますが、パフォーマンスは最優先事項ではありません。多くの場合、永続化レイヤーに抽象化を適用すると、コードが大幅に簡略化され、パフォーマンスコストは問題になりません。

あなたが何をしていても、それはOOPではありません。それは間違いではありません、それは単にOOPではありません、そしてあなたのソリューションをそこにある他のすべての問題に適用するのは意味がありません。


データは常に最初に来ます。あなたがそもそもコンピュータプログラムを持っているのはその理由です。したがって、「データベースファースト」は、アプリを設計するための唯一の有効なアプローチです。
gbjbaanb 2008年

0

興味深い質問です。いくつかの考え:

  1. すべてのビジネスロジックがデータベースにある場合、どのようにユニットテストを行いますか?
  2. データベース構造の変更、具体的にはアプリの複数のページに影響を与えるものは、アプリ全体で変更するための大きな手間ではないでしょうか。

0

良い質問!

私が好む1つのアプローチは、特定のコンテキストに関連するオブジェクトのインスタンスを生成するイテレーター/ジェネレーターオブジェクトを作成することです。通常、このオブジェクトは基礎となるデータベースアクセス関連のものをラップしますが、使用するときにそれを知る必要はありません。

例えば、

AnswerIteratorオブジェクトはAnswerIterator.Answerオブジェクトを生成します。内部では、SQLステートメントを反復してすべての回答をフェッチし、別のSQLステートメントを使用してすべての関連コメントをフェッチしています。ただし、イテレータを使用するときは、このコンテキストの最小限のプロパティを持つAnswerオブジェクトを使用します。ほんの少しのスケルトンコードで、これはほとんど取るに足らないことになります。

これは、作業する巨大なデータセットがある場合にうまく機能することを発見しました。正しく実行すると、比較的簡単にテストできる小さな一時的なオブジェクトが得られます。

それは基本的にデータベースアクセスに関するものよりも薄いベニアですが、必要なときに抽象化する柔軟性を私に与えます。


0

アプリ内のオブジェクトは1対1でデータベースに関連付けられる傾向にありますが、sprocsではなくLinq To Sqlを使用すると、複雑なクエリの記述がはるかに簡単になり、特に遅延実行を使用してそれらを構築できるようになります。たとえば、Images.User.Ratingsのrからなど。これにより、SQLでいくつかの結合ステートメントを作成する手間が省け、ページングにスキップとテイクを使用すると、row_numberと「over」コードを埋め込む必要がなく、コードが簡素化されます。


この方法で物事を行うには大きな危険があります。ほとんどの複雑なクエリは、スケーリングするためにDBAが完全に書き直す必要があります。インデックスのチューニングでは、クエリを変更することで実行できることを実行できません。このタイプのLinq2Sqlは、非常に密な結合です。
エリックZビアード

0

エンティティオブジェクトで停止する理由 エンタープライズレベルのアプリでエンティティオブジェクトの値が表示されない場合は、純粋に機能的/手続き型の言語でデータアクセスを行い、それをUIに接続します。オブジェクト指向の「綿毛」をすべて切り取らないのはなぜですか?


私はOOを「ふわふわ」と見なしていません。過去10年ほどの間に、MSFT、Sunなどが必要とするオブジェクトの99%を書き込んだだけです。フレームワークの上に多くの静的クラスを記述したからといって、OOを使用していないという意味ではありません。
エリックZビアード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.