データベースにどの程度のビジネスロジックを実装する必要がありますか?


107

私は、ほとんどのビジネスロジックがデータベースに実装されているプロジェクト(主にストアドプロシージャを使用)で働いてきました。一方、仲間のプログラマーからは、これは悪い習慣だと聞いたことがあります(「データベースはデータを保存するためにあります。アプリケーションは残りを行うためにあります」)。

これらのアプローチのどれが一般的に優れていますか?

私が考えることができるDBにビジネスロジックを実装することの長所は次のとおりです。

  • ビジネスロジックの集中化。
  • アプリケーションの種類、プログラミング言語、OSなどの独立性。
  • データベースは、テクノロジーの移行や大きなリファクタリング(AFAIK)を受けにくい傾向があります。
  • アプリケーションテクノロジの移行に関する手直しはありません(例:.NETからJava、PerlからPythonなど)。

短所:

  • SQLは、ほとんどのアプリケーション指向言語が提供するライブラリと言語構成の欠如により、ビジネスロジックプログラミングの生産性が低く、より複雑です。
  • ライブラリ経由でのコードの再利用がより困難です(可能な場合)。
  • 生産性の低いIDE。

注:私が話しているデータベースは、SQL Server、Oracle、MySqlなどのリレーショナルで人気のあるデータベースです。

ありがとう!


3
この質問への答えが役に立つかもしれません。
Blrfl

7
この議論はすでに徹底的に議論されています。ここで会話にさらに意味のあるものを追加できますか?
ロバートハーベイ

2
@gnat:近くさえありません。
ロバートハーヴェイ


7
データベースがアプリケーションをはるかに(はるかに)存続することを考慮してください。データベースは、アプリケーションを記述する言語よりも長持ちする場合があります。通常、データ自体ビジネスであり、データベースは含まれるデータの整合性を保護できる必要があります。その意味で、すべての外部キー制約は、率直に言って、ビジネスルールの実装です。リレーショナルデータベース内のすべてのリレーショナル制約を削除しない限り、データベースからビジネスロジックを完全に取り出すことはできません
クレイグ

回答:


82

ビジネスロジックがデータベースに入らない

多層アプリケーションについて話している場合、特定のエンタープライズを実行する一種のインテリジェンスであるビジネスロジックは、データアクセスレイヤーではなくビジネスロジックレイヤーに属していることは明らかです。

データベースはいくつかのことを非常にうまく行います。

  1. データを保存および取得します
  2. 異なるデータエンティティ間の関係を確立し、強制します
  3. それらは、回答を得るためにデータを照会する手段を提供します
  4. これらはパフォーマンスの最適化を提供します。
  5. アクセス制御を提供します

もちろん、ビジネス上の懸念に関連するあらゆる種類の事柄、たとえば税率、割引、操作コード、カテゴリなどをデータベースに体系化できます。ただし、そのデータに対して実行されるビジネスアクションは、他の人が既に述べたあらゆる種類の理由により、通常はデータベースにコーディングされません。ただし、データベースでアクションを選択し、他の場所で実行できます。

そしてもちろん、パフォーマンスやその他の理由でデータベースで実行されることがあります。

  1. 会計期間の終了
  2. 数値計算
  3. 夜間バッチ処理
  4. フェイルオーバー

当然、石には何も刻まれていません。ストアドプロシージャは、データベースサーバー上に存在し、特定の長所と利点があるため、幅広いタスクに適しています。

どこでもストアドプロシージャ

ストアドプロシージャですべてのデータストレージ、管理、検索タスクをコーディングし、結果のデータサービスを単純​​に消費することには、特定の魅力があります。確かに、データベースサーバーが提供できる最大限のパフォーマンスとセキュリティの最適化の恩恵を受けるでしょう。それは決して小さなことではありません。

しかし、あなたは何を危険にさらしていますか?

  1. ベンダーロックイン
  2. 特別なスキルセットを持つ開発者の必要性
  3. スパルタプログラミングツール、全体
  4. 非常に緊密なソフトウェアカップリング
  5. 懸念の分離なし

そしてもちろん、Webサービスが必要な場合(おそらくこれがすべての方向に向かっていると思われます)、それでもビルドする必要があります。

それでは、典型的なプラクティスは何ですか?

典型的な現代的なアプローチは、オブジェクトリレーショナルマッパー(Entity Frameworkなど)を使用して、テーブルをモデル化するクラスを作成することです。その後、オブジェクトのコレクションを返すリポジトリを介してデータベースと対話できます。これは、有能なソフトウェア開発者なら誰でもよく知っている状況です。ORMは、データモデルと要求された情報に対応するSQLを動的に生成し、データベースサーバーはそれを処理してクエリ結果を返します。

これはどれくらいうまく機能しますか?ストアドプロシージャやビューを書くよりもはるかに迅速に処理できます。これは通常、データアクセス要件の約80%をカバーし、ほとんどがCRUDです。他の20%をカバーするものは何ですか?ご想像のとおり、すべての主要なORMが直接サポートしているストアドプロシージャです。

ORMと同じことを行うが、ストアドプロシージャを使用するコードジェネレーターを作成できますか?もちろんできます。しかし、ORMは一般にベンダーに依存せず、誰もがよく理解しており、より適切にサポートされています。


3
@Robert Harveyのすばらしい回答をありがとう。しかし、私は「ベンダーロックイン」引数について考えていました。特定のテクノロジー(たとえば、.NETまたはJavaスタック)を使用して、アプリケーションをベンダーロックインも構築しないのですか?または、DBに比べてアプリ指向のスタックベンダーロックインの利点はありますか?
ラファエル

3
@RobertHarvey、しかし、.NETにあるアプリケーションロジックの部分は、まだ.NETに固定されています。PHPとJavaについても同様です。
Pacerier 14

2
@Pacerier:ベンダーロックインとは、データベースベンダーのことです。実際には、データベース(およびプログラミングスタック)はめったに置き換えられません。
ロバートハーベイ14

2
@kai:両方の方法でそれを行うことはできません。スタブとモックを使用して、テストが人為的であるという事実に沿って生活するか、現実的で少し遅れてテストを作成します。ただし、あなたのトレードオフは10分対30秒であるとは思いません。
ロバートハーヴェイ

3
遅れるかもしれませんが、ビジネスロジックを実装するストアドプロシージャは、データ層ではなくビジネスロジック層に属していると思います。ORMを必要としない、一種の独立した言語です。
パラライフ

16

私は、ビジネスロジックを可能な限りデータベースに入れないことを強く信じています。しかし、私の会社のパフォーマンス開発者として、時には良いパフォーマンスを達成する必要があることを感謝しています。しかし、人々が主張するよりもはるかに少ない頻度で必要だと思います。

長所と短所に異議を唱えます。

あなたはそれがあなたのビジネスロジックを集中化すると主張します。それどころか、分散化されていると思います。現在取り組んでいる製品では、多くのビジネスロジックにストアドプロシージャを使用しています。パフォーマンスの問題の多くは、関数を繰り返し呼び出すことに起因しています。例えば

select <whatever>
from group g
where fn_invoker_has_access_to_group(g.group_id)

このアプローチの問題は、一般に(これがfalseである場合もある)、データベースに関数を1行に1回、N回実行させることです。その機能は高価な場合があります。一部のデータベースは関数インデックスをサポートしています。ただし、考えられるすべての入力に対して、考えられるすべての関数にインデックスを付けることはできません。それともできますか?

上記の問題の一般的な解決策は、関数からロジックを抽出し、クエリにマージすることです。これで、カプセル化が壊れ、ロジックが複製されました。

私が見る別の問題は、ストアドプロシージャの結果セットを結合または交差させる方法がないため、ループ内でストアドプロシージャを呼び出すことです。

declare some_cursor
while some_cursor has rows
    exec some_other_proc
end

ネストされたprocからコードを引き出すと、再び分散化されます。したがって、カプセル化とパフォーマンスのどちらかを選択する必要があります。

一般的に、私はデータベースが次の点で悪いことを知っています。

  1. 計算
  2. 反復(それらは集合演算用に最適化されています)
  3. 負荷分散
  4. 解析

データベースの得意分野:

  1. ロックとロック解除
  2. データとその関係の維持
  3. 整合性の確保

ループや文字列解析などの高価な操作をアプリケーション層に保持することにより、アプリケーションを水平方向にスケーリングしてパフォーマンスを向上させることができます。通常、ロードバランサーの背後に複数のアプリサーバーを追加する方が、データベースレプリケーションをセットアップするよりもはるかに安価です。

ただし、ビジネスロジックをアプリケーションのプログラミング言語から切り離すことは正しいのですが、なぜそれが利点なのかわかりません。Javaアプリがある場合は、Javaアプリがあります。多数のJavaコードをストアドプロシージャに変換しても、Javaアプリがあるという事実は変わりません。

私の好みは、データベースコードを永続性に集中させることです。新しいウィジェットをどのように作成しますか?3つのテーブルに挿入する必要があり、それらはトランザクション内にある必要があります。それはストアドプロシージャに属します。

ウィジェットにできることと、ウィジェットを見つけるためのビジネスルールを定義することは、アプリケーションに属します。


8
SQLサーバーでは、不完全に記述されたspsのみをループで呼び出す必要があり、パラメーターでデータのセットを送信し、セットベースのプロセスを実行できます。
HLGEM

2
SQL Serverは、WHERE句にUDFがある場合は常に最適でないクエリプランを生成します。
ジムG.

7
パフォーマンスの問題は、データベースとアプリのロジックの問題ではないようです。その問題は、ORMの世界でもまったく同じです。ORMは、CRUD操作以外の本当の頭痛の種になる可能性があります。システムがデータを大量に処理し、システムのタイプを報告している場合は、注意してください。
サムイ14

それは本当です。パフォーマンスの問題のほとんどは、コードの記述が不十分で、アーキテクチャが複雑すぎるためです。しかし、間違った種類の作業をデータベースに入れたと今でも信じています。データベースに可能な限りコーディングすることで、データベースが得意ではないことを実行することになりました。
ブランドン14

1
この例は、ビジネスロジックのコア部分をDBに配置するための引数です。ペストのような反復アプローチ(セットベースの式の代わりにコードまたはカーソルループ)を避けるためです。プログラマは、オブジェクトのセットを反復的な方法(ループ、トラバース)で処理する傾向があり、不必要なロードや、多くの単一クエリラウンドトリップのSELECT N + 1問題につながる可能性があります。SQLまたは言語ベースの式(LINQなど)を使用することにより、可能な限り、代わりにセットベースのアプローチを使用する必要があります。
エリックハート

10

私はこのテーマに関して異なるビジョンを持った2つの異なる企業で働いてきました。

私の個人的な提案は、実行時間が重要なときにストアドプロシージャを使用することです(パフォーマンス)。ストアドプロシージャはコンパイルされているため、データをクエリする複雑なロジックがある場合は、データベース自体に保存することをお勧めします。また、最後にプログラムに最終データのみを送信します。

そうでなければ、プログラムのロジックは常にソフトウェア自体にあるべきだと思います。どうして?プログラムはテスト可能である必要があり、ストアドプロシージャを単体テストする簡単な方法はないと思います。忘れないでください、テストされていないプログラムは悪いプログラムです。

そのため、必要に応じてストアドプロシージャを注意して使用してください。


3
ストアドプロシージャはユニットテスト可能です。いくつかのテクニックについてはこちらをご覧ください。
ロバートハーベイ

4
afaik、単体テストはデータベースやファイルを決して使用しません。したがって、技術的には、ストアドプロシージャの「単体テスト」は単体テストではなく、非常に遅くなります。単体テストスイートは、開発中の任意の時点で数秒(または非常に大きなアプリケーションでは数分)で実行する必要があります。
ジャンフランソワコテ

1
OPは「ビジネスロジック」について話していましたが、ビジネスロジックはユニットテストする必要があります。ストアドプロシージャに配置することにより、データベースクエリと混合してプロセス全体を遅くします。先ほど言ったように、ストアドプロシージャを使用できます(犯罪ではありません)が、ビジネスロジックとデータベースレイヤーの境界線があいまいになります。慎重に使用してください:)
ジャンフランソワコテ

1
dbと必要なオブジェクト、sp、テストを作成し、その後それを破棄する場合、それは単体テストです。作業単位をテストします。
トニーホプキンソン

2
ストアドプロシージャの神話によるパフォーマンスの向上は明らかにされていませんか?
ジェフ

9

見つける必要がある中間点があります。私は、プログラマーがデータベースを高価なキー/値ストアにすぎないものとして使用する恐ろしいプロジェクトを見てきました。プログラマが外部キーとインデックスを使用できない他の人を見てきました。スペクトルの反対側では、すべてではないにしてもほとんどのビジネスロジックがデータベースコードで実装されているプロジェクトを見てきました。

既に述べたように、T-SQL(または他の一般的なRDBMSの同等物)は、複雑なビジネスロジックをコーディングするのに最適な場所ではありません。

適切なデータモデルを構築し、データベースの機能を使用してそのモデルに関する前提(FKや制約など)を保護し、データベースコードを控えめに使用しようとしています。データベースコードは、データベースが非常に得意とする何か(つまり合計)が必要な場合に役立ち、不要なときに膨大な数のレコードをネットワーク上で移動する手間を省くことができます。


2
NoSQL実践者の大勢が証明するように、データベースを「高値の」キー/値ストアとして使用することは完全に有効な手法です。
ロバートハーベイ

1
@RobertHarvey確かに正しいのですが、キー/バリューストアだけが必要な場合、データベースよりも単純/安価/高速なソリューションが必要であると、私の腸は何とか主張し続けます。NoSQLについてさらに学ぶ必要があります。
ダンピチェルマン

2
設計が不十分なデータベースの解決策としてストアドプロシージャを使用することはありません。
JeffO

2
@RobertHarvey、私は「高価なキー/値ストア」を文字通り読んだ。MongoDBのようなオプションが無料で利用できる場合、そのようなもののためにOracleまたはSQL Serverのライセンスを支払うと、お金を浪費しているように見えます。
ラファエル

@RaphaelまたはPostgreSQL useを使用できます
デミ

9

データベースシステムはセットオペレーションの実行に非常に優れているため、ビジネスロジックにセットオペレーションが含まれる場合は、データベース内に配置するのが最も適切です。

http://en.wikipedia.org/wiki/Set_operations_(SQL)

データベースは実際にはループと計算用に設計されていないため、ビジネスロジックに何らかの計算が含まれる場合、おそらくデータベース/ストアプロシージャの外部に属します。

これらは難しくて速い規則ではありませんが、良い出発点です。


6

これに対する正しい答えはありません。データベースの用途によって異なります。エンタープライズアプリケーションでは、すべての可能なアプリケーションがコードを共有する唯一の場所であるため、外部キー、制約、トリガーなどを介したデータベースのロジックが必要です。さらに、必要なロジックをコードに含めることは、通常、データベースの一貫性がなく、データの品質が低いことを意味します。GUIの動作方法にのみ関心があるアプリケーション開発者にとっては些細なことのように思えるかもしれませんが、コンプライアンスレポートでデータを使用しようとする人々は、データがなかったために10億ドルの罰金を科せられると、非常に迷惑で費用がかかることを保証しますルールを正しく守らないでください。

レコードのセット全体をあまり気にせず、1つまたは2つのアプリケーションだけがデータベースにヒットする非規制環境では、すべてをアプリケーション内に保持しておけばよいでしょう。


3

数年後、質問はまだ重要です...

単純な経験則:論理制約またはユビキタス式(単一ステートメント)の場合は、データベースに配置します(はい、外部キーとチェック制約もビジネスロジックです!)。手続き型の場合、ループと条件分岐を含めることで(実際には式に変更することはできません)、コードに入れます。

ゴミ捨て場DBを避ける

アプリケーションコードに実際にすべてのビジネスロジックを配置しようとすると、(リレーショナル)データベースがごみ捨て場に退化する可能性があります。 、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などのプログラミング言語で通常作成される手続き型コードとは大きく異なるためです。


2

それは本当にビジネス、その文化と遺産に依存しています。技術的な考慮事項は別として(これらは両方の側面から説明されています)、与えられた答えは、人々がどこから来ているのかということです。一部の組織では、データが重要であり、DBAは強力な人物です。これは典型的な集中環境であり、多数の端末が接続されたデータセンターです。このタイプの環境での優先度は明らかです。データセンターで何かが変更される前に、デスクトップは何度も根本的に変更されることがあり、その間にはほとんどありません。

スペクトルのもう一方の端は、純粋な3層アーキテクチャです。または、Web指向のビジネスの多層かもしれません。あなたはおそらくここで別の話を聞くでしょう。DBAは、もしあれば、いくつかの管理タスクを実行する相棒になります。

現代のアプリケーション開発者は、2番目のモデルとの親和性が高くなります。あなたが大規模なクライアントサーバーシステムで育ったなら、おそらく他のキャンプにいるでしょう。

ここには多くの場合、非技術的環境に関連する要素が非常に多く含まれているため、この質問に対する一般的な答えはありません。


2

ビジネスロジックという用語は解釈されやすい。システムを構築するとき、データベースとそのコンテンツの整合性を確保したいと考えています。最初のステップとして、さまざまなユーザーアクセス許可を設定する必要があります。非常に簡単な例として、ATMアプリケーションを考えてみましょう。

アカウントの残高を取得するには、適切なビューで選択を行うと問題ありません。ただし、資金を転送するには、トランザクションをストアドプロシージャでカプセル化する必要があります。ビジネスロジックが、貸方と借方の金額のテーブルを直接更新することを許可しないでください。

この例では、ビジネスロジックは、転送を要求する前に残高を確認するか、単に転送のためにストアドプロシージャを呼び出して失敗を報告します。この例のビジネスロジックであるIMHOは、十分な資金が利用可能であること、およびターゲットアカウントが存在することを先制的に確認してから、振込資金を呼び出す必要があります。最初のステップとストアドプロシージャ呼び出しの間に別の借方が発生した場合、エラーが返されます。


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