私は、ほとんどのビジネスロジックがデータベースに実装されている(主にストアドプロシージャを介して)プロジェクトで働いてきました。反対に、一部の仲間のプログラマーから、これは悪い習慣だと聞いたことがあります(「データベースにはデータを保存するためのデータベースがあります。残りの作業を行うにはアプリケーションがあります」)。
これらのアプローチのどれが一般的に優れていますか?
私が考えることができるDBにビジネスロジックを実装する長所は次のとおりです。
短所:
注:私が話しているデータベースは、SQL Server、Oracle、MySQLなどのリレーショナルで人気のあるデータベースです。
ありがとう!
多層アプリケーションについて言えば、特定のエンタープライズを実行する一種のインテリジェンスであるビジネスロジックが、データアクセスレイヤーではなくビジネスロジックレイヤーに属していることは明らかです。
データベースはいくつかのことを本当にうまく行っています:
もちろん、税率、割引、オペレーションコード、カテゴリなど、ビジネス上の懸念事項に関連するあらゆる種類のものをデータベースで体系化できます。しかし、そのデータに対して行われるビジネスアクションは、他の人がすでに言及しているあらゆる種類の理由により、一般にデータベースにコード化されていませんが、アクションは選択されたデータベースと他の場所で実行されます。
そしてもちろん、パフォーマンスやその他の理由でデータベースで実行されることがあるかもしれません:
当然、石には何も刻まれていません。ストアドプロシージャは、データベースサーバー上に存在し、特定の長所と利点があるというだけの理由で、幅広いタスクに適しています。
すべてのデータストレージ、管理、および取得タスクをストアドプロシージャにコーディングして、結果として得られるデータサービスを単純に消費することに、一定の魅力があります。データベースサーバーが提供できる最大のパフォーマンスとセキュリティの最適化の恩恵を受けることは確かですが、それは決して小さなことではありません。
しかし、あなたは何を危険にさらしますか?
そしてもちろん、Webサービスが必要な場合(おそらくこれがすべての見出しになっているところです)、それでもビルドする必要があります。
典型的な最新のアプローチは、オブジェクトリレーショナルマッパー(Entity Frameworkなど)を使用して、テーブルをモデル化するクラスを作成することです。次に、オブジェクトのコレクションを返すリポジトリを介してデータベースにアクセスできます。これは、有能なソフトウェア開発者には非常によく知られている状況です。 ORMは、データモデルと要求された情報に対応するSQLを動的に生成し、データベースサーバーはそれを処理してクエリ結果を返します。
これはどのように機能しますか?非常によく、ストアドプロシージャとビューを作成するよりもはるかに高速です。これは通常、データアクセス要件の約80%、主にCRUDをカバーします。他の20%をカバーするものは何ですか?あなたはそれを推測しました:すべての主要なORMが直接サポートするストアドプロシージャ。
ORMと同じことを行うが、ストアドプロシージャを使用するコードジェネレーターを記述できますか?できますよ。しかし、ORMは一般にベンダーに依存せず、誰もが理解し、サポートが強化されています。
私は、ビジネスロジックをデータベースからできるだけ排除することを強く信じています。しかし、私の会社のパフォーマンス開発者として、良いパフォーマンスを達成する必要があることを感謝しています。しかし、私はそれが人々が主張するよりもはるかに少ない頻度で必要だと思います。
私はあなたの長所と短所を争います。
あなたはそれがあなたのビジネスロジックを集中化すると主張します。それどころか、分散化されていると思います。現在取り組んでいる製品では、多くのビジネスロジックにストアドプロシージャを使用しています。パフォーマンスの問題の多くは、関数を繰り返し呼び出すことから生じます。例えば
select <whatever>
from group g
where fn_invoker_has_access_to_group(g.group_id)
このアプローチの問題は、一般に(これがfalseである場合があります)、データベースに関数をN回、行ごとに1回実行させることです。時にはその機能は高価です。一部のデータベースは関数インデックスをサポートしています。ただし、考えられるすべての入力に対して、考えられるすべての関数にインデックスを付けることはできません。それともできますか?
上記の問題に対する一般的な解決策は、関数からロジックを抽出してクエリにマージすることです。これで、カプセル化が解除され、ロジックが重複しました。
もう1つの問題は、ストアドプロシージャの結果セットを結合または交差させる方法がないため、ループでストアドプロシージャを呼び出すことです。
declare some_cursor
while some_cursor has rows
exec some_other_proc
end
ネストされたプロシージャからコードをプルすると、再び分散化されます。したがって、カプセル化とパフォーマンスのどちらかを選択する必要があります。
一般的に、データベースは次の点で不利であることがわかりました。
データベースの得意分野:
ループや文字列の解析などの高価な操作を実行してアプリ層に保持することで、アプリケーションを水平方向にスケーリングしてパフォーマンスを向上させることができます。ロードバランサーの背後に複数のアプリサーバーを追加する方が、データベースレプリケーションを設定するよりもはるかに安価です。
ただし、それはアプリケーションのプログラミング言語からビジネスロジックを切り離すことは正しいですが、それが利点である理由はわかりません。 Javaアプリがある場合、Javaアプリがあります。Javaコードの束をストアドプロシージャに変換するJavaアプリを持っているという事実は変わりません。
私の好みは、永続性に焦点を当てたデータベースコードを維持することです。新しいウィジェットをどのように作成しますか? 3つのテーブルに挿入する必要があり、それらはトランザクション内にある必要があります。それはストアドプロシージャに属します。
ウィジェットに対して実行できること、およびウィジェットを見つけるためのビジネスルールを定義することは、アプリケーションに属しています。
私はこのテーマについて異なるビジョンを持つ2つの異なる会社で働いています。
私の個人的な提案は、実行時間が重要な場合(パフォーマンス)にストアドプロシージャを使用することです。ストアドプロシージャはコンパイルされるため、データをクエリするための複雑なロジックがある場合は、データベース自体に保持することをお勧めします。また、最後のデータのみをプログラムに送信します。
そうでなければ、プログラムのロジックは常にソフトウェア自体にあるべきだと思います。どうして?プログラムはテスト可能である必要があるため、ストアドプロシージャを単体テストする簡単な方法はないと思います。テストされていないプログラムは悪いプログラムです。
したがって、必要な場合は、注意してストアドプロシージャを使用してください。
あなたが見つける必要がある中立の立場があります。プログラマーが高額なキー/バリューストアとしてデータベースを使用する恐ろしいプロジェクトを見てきました。プログラマーが外部キーとインデックスを使用できない他の人を見てきました。逆に、すべてではないにしてもほとんどのビジネスロジックがデータベースコードに実装されているプロジェクトを見てきました。
お気づきのように、T-SQL(または他の一般的なRDBMSの同等物)は、複雑なビジネスロジックをコーディングするのに最適な場所ではありません。
かなりまともなデータモデルを構築し、データベースの機能を使用してそのモデルに関する仮定(つまり、FKと制約)を保護し、データベースコードを慎重に使用します。データベースコードは、データベースが非常に優れており、不要なときに何十億ものレコードをネットワーク経由で移動する手間を省くことができる何か(つまり、合計)が必要な場合に役立ちます。
ビジネスロジックに集合演算が含まれる場合、データベースシステムは集合演算の実行に非常に優れているため、おそらくデータベース内に配置するのが適切です。
http://en.wikipedia.org/wiki/Set_operations_(SQL)
ビジネスロジックになんらかの計算が含まれる場合、データベースは実際にはループと計算のために設計されていないため、おそらくデータベース/ストアプロシージャの外部に属しています。
これらは厳格で迅速なルールではありませんが、それは良い出発点です。
これに対する正しい答えはありません。データベースの用途によって異なります。エンタープライズアプリケーションでは、考えられるすべてのアプリケーションがコードを共有する唯一の場所であるため、外部キー、制約、トリガーなどを介したデータベースのロジックが必要です。さらに、必要なロジックをコードに含めることは、一般にデータベースに一貫性がなく、データの品質が低いことを意味します。 GUIのしくみだけを理解しているアプリケーション開発者にとってはそれは些細なことのように思えるかもしれませんが、コンプライアンスレポートでデータを使用しようとする人々は、データを収集して数十億ドルの罰金を科せられると非常に煩わしく、コストがかかることを保証します。ルールを正しく守っていません。
非規制環境では、レコードのセット全体をそれほど気にせず、1つまたは2つのアプリケーションのみがデータベースにアクセスする場合は、アプリケーション内にすべてを保持することで問題を回避できる可能性があります。
数年後、問題はまだ重要です...
単純な経験則:それが論理制約またはユビキタス式(単一ステートメント)の場合は、データベースに配置します(そう、外部キーとチェック制約もビジネスロジックです!)。手続き型の場合は、ループと条件付きブランチを含めることで(実際には式に変更できません)、コードに含めます。
ゴミ捨て場DBを避ける
実際にすべてのビジネスロジックをアプリケーションコードに配置しようとすると、(リレーショナル)データベースがゴミ捨て場に退化する可能性があります。この場合、リレーショナルデザインはほとんど完全に省略され、データに一貫性のない状態があり、正規化が失われます(多くの場合、主にXML、JSON)。 、CSVなどのゴミ箱の列)。
この種のアプリケーションのみのロジックは、おそらくNoSQLの台頭の主な理由の1つです。もちろん、アプリケーションは、何十年もの間リレーショナルDBに組み込まれてきたすべてのロジック自体を処理しなければならないという欠点があります。ただし、NoSQLデータベースは、この種のデータ処理に適しています。たとえば、データドキュメントは暗黙的に「リレーショナル整合性」を維持します。リレーショナルDBの場合、それは単に乱用であり、これまで以上に問題を引き起こしています。
手続き型コードの代わりに式(セットベース)
最良の場合、すべてのデータクエリまたは操作は、手続き型コードではなく、式としてコーディングする必要があります。これに対する優れたサポートは、プログラミング言語が.NETの世界でLINQなどの式をサポートしている場合です(残念ながら、現時点ではクエリのみで、操作はありません)。リレーショナルDB側では、手続き型カーソルループよりもSQLステートメント式を優先することが長い間教えられてきました。したがって、DBは最適化したり、操作を並列に実行したり、役立つものであれば何でも実行できます。
DBデータ整合性メカニズムを利用する
外部キーとチェック制約、計算列、場合によってはトリガーとビューを使用するRDBMSの場合、これはデータベースに基本的なビジネスロジックを格納する場所です。適切な正規化は、データの整合性を維持し、データの一意で異なるインスタンスを保証するのに役立ちます。コードやDBでそれを複製する必要がある場合でも、これらのデータ整合性の基本的なメカニズムは省略すべきではありません。
ストアドプロシージャ?
ストアドプロシージャが必要になることはほとんどありません。データベースはSQLのコンパイル済み実行プランを保持し、同じクエリが再び来たときに、異なるパラメーターでのみそれらを再利用するためです。そのため、SPのプリコンパイル引数は無効になりました。アプリケーションまたはORMにSQLクエリを保存または自動生成できます。これにより、ほとんどの場合、プリコンパイルされたクエリプランが見つかります。 SQLは、手続き型要素を明示的に使用しない限り、式言語です。したがって、最良のケースでは、SQLに変換できるコード式を使用します。
ストアドプロシージャとは異なり、生成されたORMを含むアプリケーション側のSQLはもはやデータベース内にありませんが、私はそれをデータベースコードとして数えます。 SQLとデータベースの知識(最も単純なCRUDを除く)が依然として必要であり、適切に適用された場合、C#やJavaなどのプログラミング言語で通常作成される手続き型コードとは大きく異なります。
それは本当にビジネス、文化、遺産に依存しています。技術的な考慮事項は別として(これらは両側からカバーされています)、与えられた回答は、それが人々がどこから来ているのかにかかっていることを示しています。一部の組織では、データは王様であり、DBAは強力な人物です。これは、典型的な集中環境であり、多数の端末が接続されたデータセンターです。このタイプの環境での選択は明らかです。デスクトップは、データセンターで何かが変更される前に何度も根本的に変更される可能性があり、その間にはほとんどありません。
もう一方の端は、純粋な3層アーキテクチャです。または多分ウェブ指向のビジネスの多層。ここで別の話を聞くでしょう。 DBAがいる場合、DBAはいくつかの管理タスクを実行する単なる相棒です。
現代のアプリケーション開発者は、2番目のモデルとの親和性が高くなります。大規模なクライアントサーバーシステムで育った場合は、おそらく別の陣営にいることでしょう。
多くの場合、技術に関係のない環境関連の要因が非常に多く含まれているため、この質問に対する一般的な回答はありません。
ビジネスロジックという用語は、解釈の余地があります。システムを構築するとき、データベースとその内容の整合性を確保したいと考えています。最初のステップとして、さまざまなユーザーアクセス許可を設定する必要があります。非常に単純な例として、ATMアプリケーションについて考えてみましょう。
アカウントの残高を取得するには、適切なビューで選択を行うと問題ありません。しかし、資金を転送するには、トランザクションをストアドプロシージャでカプセル化する必要があります。ビジネスロジックは、クレジットとデビットの金額のテーブルを直接更新することを許可されるべきではありません。
この例では、ビジネスロジックは転送を要求する前に残高を確認するか、転送のストアドプロシージャを呼び出して失敗を報告することができます。この例のビジネスロジックであるIMHOは、十分な資金が利用可能であること、およびターゲットアカウントが存在することを事前にチェックして、振替資金を呼び出す必要があります。最初のステップとストアドプロシージャの呼び出しの間に別の借方が発生した場合にのみ、エラーが返されます。