1

私は常に、サービス層を介して永続層を違反から「保護」する傾向があります。しかし、それが本当に必要なのか疑問に思い始めています。データベースを堅牢にし、関係を構築し、データの整合性を構築するのに時間をかける意味はありません。

たとえば、フィールドUserに一意の制約があるテーブルを考えてみましょう。当然のことながら、何かを追加しようとする前Emailに、追加する電子メールがデータベースにまだ存在しないことを確認するために、サービス層にブロッカー コードを書きたいと思います。過去に、私は実際に何か悪いことを見たことはありませんが、より多くのベストプラクティス/設計原則にさらされているため、このアプローチはあまりDRYではないと感じています.

では、永続化レイヤーに送信されるデータが実際に「有効」であることを常に確認するのは正しいのでしょうか?それとも、無効なデータをデータベースに送信してエラーを処理する方が自然なのでしょうか?

4

3 に答える 3

2

お願い、それはやめて。

キーなどの「単純な」制約を実装することは、並行環境では明らかに重要です。たとえば、あるステップでデータベースにクエリを実行し、最初のステップで空の結果が返された場合にのみ別のステップで挿入を許可するだけでは不十分です。ステップ1と2?データの重複につながる可能性のある競合状態があります。おそらくこれに対する最も簡単な解決策は、トランザクションをシリアル化するためにグローバルロックを設定することですが、そうするとスケーラビリティが窓の外に出てしまいます...

キーに対する INSERT / UPDATE / DELETE 操作の他の組み合わせ、および外部キーや場合によっては CHECK などの他の種類の制約についても、同様の考慮事項があります。

DBMS は、このような状況で正しくパフォーマンスを発揮できるように、数十年にわたって非常に巧妙な方法を考案してきましたが、宣言的な方法で制約を簡単に定義できるため、間違いの可能性を最小限に抑えることができます。また、同じデータベースにアクセスするすべてのアプリケーションは、これらの集中化された制約から自動的に恩恵を受けます。

データを検証しないコード層を絶対に選択する必要がある場合は、データベースを最後の選択肢にする必要があります。

では、永続層に送られるデータが実際に「有効」(サービス層) であることを常に確認するのは正しいのでしょうか?それとも、無効なデータをデータベースに渡してエラーを処理する方が自然なのでしょうか?

できる限り正しいデータを想定せず、常にデータベース レベルで検証してください。

コードの上位レイヤーでも検証するかどうかは状況によって異なりますが、キー違反の場合は、データベースに面倒な作業を任せます。

于 2012-09-10T22:31:22.807 に答える
1

決定的な答えはありませんが、素晴らしい質問だと思います。

まず、私はデータベースに少なくとも基本的な検証を含め、データベースに得意なことをさせることを強く支持しています。少なくとも、これは外部キー、NOT NULL必要に応じて強く型付けされたフィールド (整数が属するテキスト フィールドを配置しないなど)、一意の制約などを意味します。 out) であり、トランザクションの原子性はデータベースが所有する必要があります。

これが適度に冗長である場合は、そうではありません。検証が少なすぎるよりも、多すぎる方がよいでしょう。

ただし、ビジネス層は、ロジックがデータベース内に存在する場合でも、実行している検証を認識しておく必要があると私は考えています。

  • 例外と検証エラーを区別する方が簡単な場合があります。ほとんどの言語では、失敗したデータ操作はおそらく何らかの例外として現れます。ほとんどの人 (私を含む) は、通常のプログラム フローに例外を使用するのは良くないと考えており、電子メール検証の失敗 (たとえば) は「例外的な」ケースではないと主張します。

    もっとばかげたレベルにすると、ユーザーがフォームのすべての必須フィールドに入力したかどうかを判断するためだけにデータベースにアクセスすることを想像してみてください。

    言い換えれば、IsEmailValid()スローされたデータベース エラーが、電子メールが他の誰かによって既に使用されていることを意味するかどうかを判断するよりも、メソッドを呼び出してブール値を受け取るほうがよいということです。

    このアプローチはパフォーマンスも向上し、INSERT が失敗したために ID がスキップされるなどの煩わしさを回避できます (SQL Server の観点から言えば)。

    電子メールを検証するためのロジックは、単純な一意の制約よりも複雑である場合、再利用可能なストアド プロシージャに含まれている可能性があります。

    そして最終的には、その単純な一意の制約により、ビジネス層がミスを犯した場合の最終的な保護が提供されます。

  • 一部の検証では、データベースが簡単に処理できたとしても、成功するためにデータベース呼び出しを行う必要はありません。

  • 一部の検証は、データベース構造/関数のみを使用して表現できるよりも複雑です。

  • アプリケーション間のビジネス ルールは、同じ (完全に有効な) データに対しても異なる場合があります。

  • 一部の検証は非常に重要または費用がかかるため、データ アクセスの前に実行する必要があります。

  • フィールドの型/長さなどのいくつかの単純な制約は自動化できます (ORM を介して実行されるものは、おそらくある程度の自動化が利用可能です)。

于 2012-09-11T00:48:09.460 に答える
1

そうする2つの理由。データベースは別のアプリケーションからアクセスできます。

コードに小さなエラーが発生し、データベースにデータが配置される可能性があります。これは、サービス層がこれが決して起こらないという前提で動作するため、運が良ければフォールオーバーし、サイレント データ破損が最悪のケースです。

私は常に、コードを間違えたという非常にまれな機会のバックストップとして、DB のルールを調べてきました。:)

覚えておくべきことは、必要に応じて、いつでも制約を緩和できるということです。ユーザーがデータを入力するのに多大な労力を費やした後に制約を厳しくすると、はるかに問題が大きくなります。

IT では、それはあなたが望んでいたよりもはるかに早いことを意味します。

于 2012-09-10T22:16:21.843 に答える