古くからの質問。ビジネスロジックを、ストアドプロシージャ(またはパッケージ)としてデータベースに配置するか、アプリケーション/中間層のどこに配置する必要がありますか?そしてもっと重要なのは、なぜですか?
データベースの独立性は目標ではないと想定します。
データの一貫性と正確性を確保するために、データベースに十分なビジネスロジックを配置します。
ただし、ユーザーエクスペリエンスを向上させるために、このロジックの一部を別のレベルで複製する必要があることを恐れないでください。
コードの保守性は、ビジネスロジックをどこに配置するかを決定する際に常に大きな懸念事項です。
統合されたデバッグツールとより強力なIDEにより、一般に、ストアドプロシージャ内の同じコードよりも中間層コードの保守が容易になります。特に理由がない限り、ストアドプロシージャではなく、中間層/アプリケーションのビジネスロジックから始める必要があります。
ただし、レポート作成やデータマイニング/検索に関しては、多くの場合、ストアドプロシージャの方が適しています。これは、データベースの集約/フィルタリング機能の能力と、データのソースに非常に近い処理を続けているという事実のおかげです。しかし、これはとにかく古典的なビジネスロジックを最も考慮しているものではないかもしれません。
非常に単純なケースでは、ビジネスロジックをストアドプロシージャに入れることができます。通常、単純なケースでさえ、時間の経過とともに複雑になる傾向があります。データベースにビジネスロジックを入れない理由は次のとおりです。
ビジネスロジックをデータベースに配置すると、ビジネスロジックがデータベースの技術的な実装と緊密に結合されます。テーブルを変更すると、多くのストアドプロシージャが再び変更され、多くの追加のバグと追加のテストが発生します。
通常、UIは検証などのビジネスロジックに依存します。これらのものをデータベースに配置すると、データベースとUIが緊密に結合されるか、場合によっては、これら2つの間で検証ロジックが重複します。
同じデータベースで複数のアプリケーションを動作させるのは難しくなります。 1つのアプリケーションを変更すると、他のアプリケーションが破損します。これはすぐにメンテナンスの悪夢に変わる可能性があります。したがって、実際にはスケーリングしません。
より実際的には、SQLはビジネスロジックを理解できる方法で実装するのに適した言語ではありません。 SQLはセットベースの操作には最適ですが、大量のストアドプロシージャを維持するのが難しい「大規模なプログラミング」の構成が欠落しています。現代のOO言語は、これにより適していて、より柔軟です。
これは、ストアドプロシージャとビューを使用できないという意味ではありません。テーブルとアプリケーションの間にストアドプロシージャとビューの追加レイヤーを配置して、2つを分離することをお勧めする場合があると思います。これにより、外部インターフェイスを変更せずにデータベースのレイアウトを変更できるため、データベースを個別にリファクタリングできます。
それは本当にあなた次第です、あなたが一貫している限り。
データベースレイヤーに配置する理由の1つは、クライアントがデータベースのバックエンドを変更しないことがかなり確実な場合です。
それをアプリケーション層に配置する1つの理由は、アプリケーションに複数の永続化テクノロジーをターゲットにしている場合です。
また、コアコンピテンシーも考慮する必要があります。あなたの開発者は主にアプリケーション層の開発者ですか、それとも主にDBAタイプですか?
アプリケーション層にビジネスロジックを配置することには確かに利点がありますが、言語/フレームワークはデータベースよりも頻繁に変更されるように思われることを指摘したいと思います。
私がサポートしているシステムのいくつかは、過去10〜15年間に次のUIを通過しました:Oracle Forms/Visual Basic/Perl CGI/ASP/Javaサーブレット。変更されなかったのは、リレーショナルデータベースとストアドプロシージャです。
この場合、質問者が考慮事項として除外するデータベースの独立性は、データベースからロジックを取り出すための最も強力な議論です。データベースの独立性についての最も強力な議論は、データベースバックエンドを独自に好む企業にソフトウェアを販売する能力についてです。
したがって、データベースからストアドプロシージャを取り出すための主要な議論は、技術的なものではなく、商用のものであると考えています。技術的な理由があるかもしれませんが、それを維持するための技術的な理由もあります。たとえば、パフォーマンス、整合性、複数のアプリケーションが同じAPIを使用できるようにする機能などです。
SPを使用するかどうかは、使用するデータベースにも大きく影響されます。データベースの独立性を考慮に入れていない場合、T-SQLまたはPL/SQLを使用すると非常に異なるエクスペリエンスが発生します。
Oracleを使用してアプリケーションを開発している場合、PL/SQLは言語として当然の選択です。これはデータと非常に緊密に結合されており、リリースごとに継続的に改善されており、適切な開発ツールはPL/SQL開発をCVSやSubversionなどと統合します。
OracleのWebベースのApplicationExpress開発環境は、PL/SQLを使用して100%構築されています。
正しい答えは1つではありませんが、問題のプロジェクトによって異なりますが、Eric Evansが「 ドメイン駆動設計 n」で提唱しているアプローチをお勧めします。このアプローチでは、ビジネスロジックは、データベースコードを含めることができるインフラストラクチャ層の上にある独自の層(ドメイン層)と、要求をドメイン層に送信するアプリケーション層の下に分離されます。履行を求め、完了の確認をリッスンして、アプリケーションを効果的に推進します。
このように、ビジネスロジックは、技術的な問題は別としてビジネスを理解している人と話し合うことができるモデルに取り込まれ、ビジネスルール自体の変更、技術的な実装の問題、およびビジネス(ドメイン)モデルと相互作用するアプリケーション。
この純粋な理想が実際のコードやプロジェクトの現実の世界で実際にどのように近似できるかを説明するのに非常に優れているので、機会があれば上記の本を読むことをお勧めします。
データの整合性に影響を与えるものはすべて、データベースレベルに配置する必要があります。ユーザーインターフェイス以外にも、インポート、価格設定スキームを変更するための一括更新、ホットフィックスなど、データベースにデータを入れたり、データベースからデータを更新または削除したりすることがよくあります。ルールが常に守られていることを確認する必要がある場合は、ロジックをデフォルトにします。とトリガー。
これは、ユーザーインターフェイスにもそれを含めるのが良い考えではないということではありません(データベースが受け入れない情報をわざわざ送信する理由)が、データベースでこれらのことを無視することは、災害を法廷で行うことです。
最近では、ストアドプロシージャコードをSubversionに送信し、優れたツールサポートを使用してこのコードをデバッグすることができます。
SQLステートメントを組み合わせたストアドプロシージャを使用すると、アプリケーションとデータベース間のデータトラフィックの量を減らし、データベース呼び出しの数を減らして、パフォーマンスを大幅に向上させることができます。
C#でビルドを開始すると、ストアドプロシージャを使用しないことを決定しましたが、現在はストアドプロシージャにコードを移動することが増えています。特にバッチ処理。
ただし、トリガーは使用せず、ストアドプロシージャまたはより優れたパッケージを使用してください。トリガーは保守性を低下させます。
データベースの独立性が必要な場合は、アプリケーション層で利用可能な標準がデータベース層で利用可能な標準よりもはるかに普及しているため、すべてのビジネスロジックをアプリケーション層に配置することをお勧めします。
ただし、データベースの独立性が最大の要因ではなく、チームのスキルセットに強力なデータベーススキルが含まれている場合は、ビジネスロジックをデータベースに配置することが最善の解決策になる可能性があります。アプリケーション担当者にアプリケーション固有のことを実行させ、データベース担当者にすべてのクエリが確実に実行されるようにすることができます。
もちろん、SQLステートメントをまとめることができることと、「強力なデータベーススキル」を持つことには大きな違いがあります。チームが後者よりも前者に近い場合は、この世界の休止状態の1つを使用してアプリケーションにロジックを配置します。 (またはチームを変更してください!)。
私の経験では、エンタープライズ環境では、この領域に単一のターゲットデータベースとスキルがあります。この場合、データベースにできることはすべて入れてください。ソフトウェアを販売するビジネスをしている場合、データベースライセンスのコストがデータベースの独立性を最大の要因にし、アプリケーション層で可能なすべてを実装することになります。
お役に立てば幸いです。
コードをアプリケーション層に配置すると、DBに依存しないアプリケーションになります。
パフォーマンス上の理由から、ストアドプロシージャを使用する方がよい場合があります。
それは(いつものように)アプリケーションの要件に依存します。
データベースに入るのはデータだけです。
ストアドプロシージャは、メンテナンスの悪夢です。それらはデータではなく、データベースに属していません。開発者とDBAの間の無限の調整は、組織の摩擦にすぎません。
ストアドプロシージャのバージョン管理を適切に維持することは困難です。データベース外のコードは非常に簡単にインストールできます。バージョンが間違っていると思われる場合は、SVN UP(おそらくインストール)を実行するだけで、アプリケーションが既知の状態に戻ります。環境変数、ディレクトリリンク、およびアプリケーションに対する多くの環境制御があります。
簡単なPATH
操作で、さまざまな状況(トレーニング、テスト、QA、本番、顧客固有の拡張機能など)に対応するバリアントソフトウェアを利用できます。
ただし、データベース内のコードは管理がはるかに困難です。使用されているソフトウェアを使用可能に制御するための適切な環境(「PATH」、ディレクトリリンク、またはその他の環境変数)はありません。データベースに永続的なグローバルにバインドされたアプリケーションソフトウェアのセットがあり、データと結合しています。
トリガーはさらに悪いです。それらはメンテナンスとデバッグの悪夢の両方です。彼らがどのような問題を解決するのかわかりません。それらは、誰かが利用可能なクラス(または関数ライブラリ)を正しく使用することを気にすることができなかった、不適切に設計されたアプリケーションを回避する方法のようです。
一部の人々はパフォーマンスの議論を説得力があると感じていますが、ストアドプロシージャがそれほど高速であることを私に納得させるのに十分なベンチマークデータをまだ見ていません。誰もが逸話を持っていますが、アルゴリズムが多かれ少なかれ同じであるサイドバイサイドコードを持っている人は誰もいません。
[私が見た例では、古いアプリケーションは設計が不十分でした。ストアドプロシージャが作成されると、アプリケーションは再設計されました。プラットフォームの変更よりも、設計の変更の方が影響が大きかったと思います。]
私の経験における答えは、通常、組織のスキルがどこにあるかによって決定されるさまざまな価値観にあります。
DBMSは非常に強力な獣です。つまり、適切または不適切な治療は大きな利益または大きな危険をもたらします。悲しいことに、あまりにも多くの組織では、プログラミングスタッフに主な注意が払われています。 dbmsスキル、特に(管理ではなく)クエリ開発スキルは無視されます。これは、dbmsスキルを評価する機能もおそらく欠落しているという事実によって悪化します。
また、データベースについて理解していないことを十分に理解しているプログラマーはほとんどいません。
したがって、Active RecordsやLINQなどの次善の概念の人気(明らかなバイアスを投入するため)。しかし、それらはおそらくそのような組織にとって最良の答えです。
ただし、大規模な組織は、データストアの効果的な使用により多くの注意を払う傾向があることに注意してください。
ビジネスロジックは、最初の選択肢としてアプリケーション/中間層に配置する必要があります。このようにして、ドメインモデルの形式で表現したり、ソース管理に配置したり、分割したり、関連するコードと組み合わせたり(リファクタリング)したりできます。また、データベースベンダーの独立性も得られます。
オブジェクト指向の言語は、保存されたプロシージャよりもはるかに表現力があり、何が起こるべきかをコードでより適切かつ簡単に記述することができます。
ストアドプロシージャにコードを配置する唯一の理由は、そうすることでパフォーマンスが大幅に向上する場合、または同じビジネスコードを複数のプラットフォーム(Java、C#、PHP)で実行する必要がある場合です。複数のプラットフォームを使用している場合でも、機能の共有により適している可能性のあるWebサービスなどの代替手段があります。
この質問に対する独立した正しい答えはありません。それはあなたのアプリの要件、あなたの開発者の好みとスキル、そして月の満ち欠けに依存します。
ビジネスロジックは、データベースではなくアプリケーション層に配置されます。その理由は、データベースのストアドプロシージャは、使用するデータベース製品に常に依存しているためです。これは、3層モデルの利点の1つを壊します。このデータベース製品に追加のストアドプロシージャを提供しない限り、他のデータベースに簡単に変更することはできません。一方、パフォーマンスを最適化するために、ロジックをストアドプロシージャに組み込むことが理にかなっている場合もあります。
私が言いたいのは、ビジネスロジックはアプリケーション層に配置されることですが、例外があります(主にパフォーマンス上の理由)
私見では。リレーショナルデータベース駆動型アプリのどこにビジネスロジックを配置するかを決定することには、2つの相反する懸念があります。
再。保守性:効率的な将来の開発を可能にするために、ビジネスロジックは、デバッグとバージョン管理が最も簡単なアプリケーションの部分に属しています。
再。信頼性:不整合の重大なリスクがある場合、ビジネスロジックはデータベースレイヤーに属します。リレーショナルデータベースは、データの制約をチェックするように設計できます。特定の列などでNULL値を許可しない。アプリケーションの設計で、一部のデータを複雑すぎてこれらの単純な制約で表現できない特定の状態にする必要があるシナリオが発生した場合は、トリガーなどを使用するのが理にかなっています。データベース層で。
トリガーは最新の状態に保つのが面倒です。特に、アプリがクライアントシステムで実行されることになっている場合は、アクセスすらできません。しかし、それはそれらを追跡したり更新したりすることが不可能であることを意味するものではありません。それは苦痛で面倒であるという彼の答えのS.Lottの議論は完全に有効です、私はそれを2番目にし、そこにもいました。ただし、最初にデータレイヤーを設計するときにこれらの制限を念頭に置いて、管理可能な絶対的な必需品以外の目的でトリガーや関数を使用しないようにしてください。
私たちのアプリケーションでは、ほとんどのビジネスロジックはアプリケーションのモデルレイヤーに含まれています。請求書は、特定の販売注文から自分自身を初期化する方法を知っています。このような複雑な一連の変更のためにさまざまなものが順番に変更される場合、ストアドプロシージャを選択する代わりに、一貫性を維持するためにそれらをトランザクションにロールアップします。合計などの計算はすべてモデルレイヤーのメソッドを使用して行われます。ただし、パフォーマンスのために何かを非正規化するか、すべてのクライアントが使用する「変更」テーブルにデータを挿入して、セッションキャッシュで期限切れにする必要があるオブジェクトを特定する必要がある場合は、データベースレイヤーのトリガー/関数を使用して新しい行を挿入しますこのトリガーから通知(Postgresのリッスン/通知)を送信します。
私たちのアプリを約1年間フィールドに置いて、毎日何百人もの顧客が使用した後、ゼロから始める場合に変更する唯一のことは、データベース関数(またはストアドプロシージャ)を作成するためのシステムを設計することです。最初からバージョン管理と更新を念頭に置いて、それらを呼び出したい)。
ありがたいことに、スキーマのバージョンを追跡するためのシステムがいくつか用意されているので、その上にデータベース関数の置き換えを処理するための何かを構築しました。ただし、最初から交換する必要があると考えていれば、時間を節約できたはずです。
もちろん、RDBMSの領域を超えて、Amazon SimpleDBやGoogleのBigTableなどのタプルストレージシステムに入ると、すべてが変わります。しかし、それは別の話です:)
ビジネスアプリケーションの「レイヤー」は次のとおりです。
これは、ビジネスユーザーのh(is/er)ジョブのビューを実装します。ユーザーが精通している用語を使用します。
ここで計算とデータ操作が行われます。データの変更を伴うビジネスロジックはすべてここに実装されます。
これは次のようになります。正規化されたシーケンシャルデータベース(標準のSQLベースのDBMS)。ビジネスデータをラップするオブジェクトを格納するオブジェクト指向データベース。等.
上記のレイヤーに到達するには、必要な分析と設計を行う必要があります。これは、ビジネスロジックが最適に実装される場所を示します。データの整合性ルールとデータ更新に関する同時実行/リアルタイムの問題は、通常、計算フィールドと同じように、データのできるだけ近くに実装されます。これは良い指針ですデータの整合性とトランザクション制御が絶対に必要なストアドプロシージャ/トリガーへ。
データの意味と使用を含むビジネスルールは、ほとんどの場合、処理レイヤーに実装されますが、ユーザーのワークフローとしてユーザーインターフェイスにも表示されます。さまざまなプロセスを、ユーザーの仕事。
それは連続体です。私見最大の要因はスピードです。保守性、パフォーマンス、スケーラビリティ、セキュリティ、信頼性などのプログラミングの優れたテナントを守りながら、この吸盤をできるだけ早く起動して実行するにはどうすればよいですか。多くの場合、SQLは何かを表現するための最も簡潔な方法であり、たまたま文字列操作などを除いて、何度も最もパフォーマンスが高くなりますが、CLRProcsが役立つ場合があります。私の信念は、目前の事業に最適だと思うところならどこでも、ビジネスロジックを自由にまき散らすことです。 SQLを見るときにたわごとをするアプリケーション開発者がたくさんいる場合は、アプリロジックを使用させます。大規模なデータセットを使用して高性能アプリケーションを本当に作成したい場合は、DBにできるだけ多くのロジックを配置してください。 DBAを起動し、開発者に開発データベースに対する究極の自由を与えます。その仕事に最適な答えやツールはありません。複数のツールがあるので、アプリケーションのすべてのレベルで専門家になると、必要に応じて簡潔で表現力豊かなSQLを記述したり、アプリケーション層を使用したりすることに多くの時間を費やしていることにすぐに気付くでしょう。私にとって、最終的には、コードの行数を減らすことが単純さにつながります。たった2500行のアプリコードと1000行のSQLを備えたSQLリッチアプリケーションを、以前のSQLリッチアプリが行っていたことを実現するために、15500行のアプリコードと2500行のSQLを備えたドメインモデルに変換しました。コードの6倍の増加を「簡略化」として正当化できる場合は、先に進んでください。
ストアドプロシージャには多くのビジネスロジックを配置しています。これは理想的ではありませんが、パフォーマンスと信頼性のバランスが取れていることがよくあります。
そして、何エーカーものソリューションやコードベースを検索しなくても、どこにあるかがわかります。
スケーラビリティは、データベース層よりも中間層またはアプリ層でビジネスロジックを使用するための非常に重要な要素でもあります。DatabaseLayerは、データベースとやり取りするためだけのものであり、データベースとの間でやり取りされるものを操作するためのものではないことを理解してください。
どこかで、すべてがある程度ビジネスロジックの一部になる可能性があることを指摘した記事を読んだことを覚えています。そのため、この質問は無意味です。
与えられた例は、画面上の請求書の表示だったと思います。期限切れのものを赤でマークするという決定は、ビジネス上の決定です...
これは素晴らしい質問です!私はすでに同様の質問をした後にこれを見つけました 質問 、しかしこれはより具体的です。それは、私が関わっていなかった設計変更の決定の結果として思いついたものです。
基本的に、データベーステーブルに数百万行のデータがある場合は、ビジネスロジックをストアドプロシージャとトリガーに配置することを検討してください。 Javaコードが複雑になったため、Javaアプリを保守性のためにストアドプロシージャに変換することで、現在行っていることです。
私はこの記事を次の場所で見つけました: ビジネスロジックウォーズ 著者はテーブル引数に100万行を作成しましたが、これは興味深いと思いました。彼はまた、クライアント側でビジネスロジック層の外側にあるjavascriptにビジネスロジックを追加しました。サーバー側の検証に加えて、検証にjavascriptを何年も使用してきましたが、これについてはこれまで考えていませんでした。
私の意見では、経験則としてアプリケーション/中間層のビジネスロジックが必要ですが、データベースに配置することが理にかなっている場合は軽視しないでください。
最後に、私が現在取り組んでいる別のグループがあり、研究のために大規模なデータベース作業を行っており、彼らが扱っているデータの量は膨大です。それでも、彼らにとっては、データベース自体にビジネスロジックはありませんが、アプリケーション/中間層に保持します。彼らの設計では、アプリケーション/中間層が適切な場所であったため、設計上の考慮事項としてテーブルのサイズを使用することはしませんでした。
ビジネスロジックは通常、オブジェクトと、カプセル化、継承、およびポリモーフィズムのさまざまな言語構造によって具体化されます。たとえば、銀行のアプリケーションがお金を回している場合、「お金」とは何かというビジネス要素を定義するMoneyタイプが存在する可能性があります。これは、お金を表すためにプリミティブな小数を使用するのとは対照的です。このため、適切に設計されたOOPは、厳密にはどの層にも存在しない「ビジネスロジック」が存在する場所です。