データ検証をサポートするORMの場合、データベースにも制約を適用する必要がありますか?


13

(ActiveRecord)モデルに加えて、常にデータベースレベルで制約を適用しています。しかし、私はこれが本当に必要かどうか疑問に思っていましたか?

少しの背景

私は最近、モデルの基本的な自動タイムスタンプ生成方法を単体テストする必要がありました。通常、テストはモデルのインスタンスを作成し、検証なしで保存します。ただし、テーブル定義でnullにできない他の必須フィールドがあります。つまり、ActiveRecord検証をスキップしてもインスタンスを保存できません。だから私はdb自体からそのような制約を削除し、ORMにそれらを処理させる必要があるかどうかを考えていますか?

db、imoの制約をスキップした場合に考えられる利点 -

  • データベースを移行することなく、モデル内の検証ルールを変更できます。
  • テストで検証をスキップできます。

考えられる不利益は?

ただし、ORM検証が失敗またはバイパスされる可能性がある場合、データベースは制約をチェックしません。

どう思いますか?

編集このケースでは、データベースからモデルを生成するYii Frameworkを使用しているため、データベースルールも生成されます(ただし、生成後はいつでも記述できます)。


3
ORMを使用せずにデータベース内のデータを定期的に変更できる場合(ORMを使用しない他のアプリ、またはさらに悪いことにユーザーによる直接dbアクセス)、検証は実際にデータベース内で行う必要があります。
マルジャンヴェネマ

回答:


16

あなたの指導原則は自分自身を繰り返さないください

ソフトウェアエンジニアリングでは、Do n't Repeat Yourself(DRY)は、あらゆる種類の情報の繰り返しを減らすことを目的としたソフトウェア開発の原則であり、特に多層アーキテクチャで役立ちます。DRYの原則は、「すべての知識がシステム内で単一の明確な権威ある表現を持たなければならない」と述べられています。

ORMは基本的に追加の層(または必要に応じて層)であり、アプリケーションとデータストレージの間に快適に座っています。制約は、ORM またはデータストレージの1か所で、1か所のみである必要があります。そうでなければ、すぐに別のバージョンを維持することになります。あなたは本当にそれをしたくありません。

ただし、実際には、ほとんどの適切なORMは、データスキーマから大量のモデルを自動的に生成します。重複はまだありますが、重複したORMコードは毎回同じパターンに従って生成されるため、メンテナンスヘルが発生する可能性は最小限です。重複するコードを持たないことが理想ですが、自動生成された制約が次善策です。

また、制約を1つの場所に配置することは、必ずしもすべての制約を同じ場所に配置する必要があるという意味ではありません。参照整合性制約など、一部はデータストレージにより適している場合があります(ただし、別のデータストレージに移動すると失われる可能性があります)。すべてのリンゴを同じバスケットに入れるのが望ましいでしょうが…

失敗

ORMの失敗に言及しています。それはあなたの質問とはまったく関係ありません。アプリケーションはORMとデータストレージを単一のエンティティとして考える必要があります。失敗した場合は失敗します。ORMをバイパスしてデータストレージと直接通信することはお勧めできません

ORMをバイパスして何か他のものにする

また、良いアイデアではありません。ただし、さまざまな理由で発生する可能性があります。

  1. ORMが導入される前にビルドされたアプリケーションのレガシー部分。

    それは難しい問題であり、まさに私が対処している状況です。したがって、「保守地獄」を繰り返し繰り返します。ORM以外の部分を維持するか、ORMを使用するようにそれらを書き換えます。最初は2番目のオプションの方が理にかなっているかもしれませんが、それはアプリケーションのこれらの部分が正確に何をしているか、そして長期的に完全な書き換えがどれだけ価値があるかだけに基づいた決定です。

    うまく設計されていない2 * 10 ^ 8行のMySQLテーブルでキーを変更してみて(ダウンタイムなし)、私がどこから来たのか理解できます。

  2. データストレージと直接通信する必要があるアプリケーションの非レガシー部分:

    さらにトリッキー。ORMは派手なツールであり、ほとんどすべてを処理しますが、時には邪魔になったり、まったく役に立たないことさえあります。流行語(実際に流行語)はオブジェクトとリレーショナルのインピーダンスの不一致です。単純に言うと、ORMがリレーショナルデータベースのすべてを行うことは技術的に不可能です。

コメント

データの整合性の点から、データベースに制約を設定する必要があり、アプリケーションに制約を設定する必要があります。Webおよびデスクトップアプリケーション、モバイルアプリ、またはWebサービスからアプリケーションにアクセスした場合はどうなりますか?– ルイスダミム

ここで追加のレイヤーを追加すると非常に役立ちます。Webアプリケーションの場合は、REST APIを使用します。過度に単純化した設計これについては次のようになります。

ここに画像の説明を入力してください

ORMはAPIとデータストレージの間に位置し、APIの背後にあるすべて(APIを含む)は、さまざまなアプリケーションからの単一のエンティティと見なされます。


通常は、ORMでスキーマを定義し、それをデータベースにミラーリングして、第2レベルの保証を確保します。
ジョシュK

2
@JoshK保証の第2レベルと言います、私はメンテナンス地獄と言います。あなたが
間違っ

理にかなっています。私は今このルートに従っています。ありがとう!
NA

1
1〜2人の開発者がコードデータベースの作業を行っているポイントを過ぎてしまうと、必要な悪になります。適切なORMを使用すると、移行も生成されます。専用のDBAが必要になるまで成長した場合、それを回避する方法はありません。制約なしにテーブルを浮かせることはできません。メールなしでユーザーがサインアップするのを防ぐ簡単な方法は、ストレージレベルに制限を加えることです。
ジョシュK

1
データの整合性の点から、データベースに制約を設定する必要があり、アプリケーションに制約を設定する必要があります。Webおよびデスクトップアプリケーション、モバイルアプリ、またはWebサービスからアプリケーションにアクセスした場合はどうなりますか?
ルイスダミム

20

これは実際には答えるのが非常に難しい質問であり、私はそれが非常に物議を醸す主題であることを発見しました。

Yannis Rizosが答えで指摘したように、データベースとORMレイヤーの両方に制約ロジックがあると、 DRYに違反しているように見えます。

ただし、次のいずれかの条件がある場合、データベースから制約ロジックを削除してORMレイヤーのみ保持することはできません。

  1. 手動DB更新(それらはすべての会社で発生するようです)

  2. 常にORM制約ロジックを簡単に共有できない別のシステムからのDB更新(例:ORMレイヤーがHibernateに実装され、日々のアクティビティのためにJavaアプリケーションによって使用されるときにルーチンタスクを実行するPerlスクリプト)

これは、DRY違反を防ぐために、制約ロジックをDBに追加し、ORMレイヤーから削除するだけであることを示唆しています。ただし、これにより、アプリケーションコードが実際の問題を正常にキャプチャできず、ユーザーに中継できない場合があります(ただし、開発者が問題をデバッグしている場合は可能です)。これは、一部のプロジェクトでは受け入れられない場合があります。

最後のオプションは、DB制約からORM(および他のシステム)の制約の作成自動化することです(実際には、その逆です)。最終的に2つ以上の制約の実装になりますが、「Pragmatic Programmer」で説明されているように、DRY違反を回避するためにコード生成の使用を推奨しているため、DRY原則に違反しません。もちろん、それはそれほど単純ではありません。たとえば、DB制約を変更すると、それを使用するすべてのアプリケーションの再構築と再デプロイが強制される可能性があるためです(自動化は簡単ではありません)。

実際には、ケースバイケースで評価する必要があります。これまでのところ、制約ロジックを繰り返さないことを提案すると、空白の視線に出会ったことがわかります。


2
仕事を辞めたばかりで、私の答えを多かれ少なかれ投稿したものに拡大しようと考えていました。いい答えです!
ヤニス

3

デフォルトのオプションとして、データベースに制約を間違いなく追加します。これは、企業にとってデータが最も重要であり、データ品質が最重要だからです。@Yannis RizosはDRYの原則を議論に持ち込みました。まあ別の原則は、多層防御です。データについては、この原則を使用します。

私はDBに30年前に作成されたデータがある実際の企業で働いてきました。COBOLアプリケーションからアクセスされていましたが、現在は.Netアプリケーションからアクセスされています。10年後には、ベンダーのアプリになるかもしれません。合併があり、数百万行のデータが変換され、SQLを使用して他社からこのデータベースに移行されました。ORMでこれを行うことはできません。一番下の行は、データが残る、アプリケーションが変わる、データが生成される方法が変わるということです。では、データ破損の可能性を減らしてみませんか?


2

両方ともある程度できると思います。

  • 主な制約はORM内に存在する必要があります。プログラミング言語ははるかに柔軟性が高く、テストが容易で、要件が変化したときに微調整が容易です。少なくともDDLの修正について心配する必要はありません。また、一般的に、データ回帰の問題をテストするのが難しいことを避けます。

  • いくつかの非常に厳しい制約もデータベースに存在する必要があります。たとえば、null不可の名前については話していません。参照整合性や、絶対に重要な識別子が必要なことなどについて話しています。コードが「注文に存在しない製品がある場合」に対処する必要がないようにするための構造的要件。


1

データベースはIMOであり、DRYに違反する唯一の場所です。何かがあなたのORMを迂回し、不正なデータを持っている場合、それがそれだからです。ゲームオーバー。破損したデータを持つことは致命的な打撃です。


データベースのみ?データがまったく保持されない場合でも、データに関連付けられた動作が複数のレイヤー(論理または物理)に存在する必要がある多くのケースを考えることができます。場合によっては、単一のソースコードを使用して、展開されたdllの「重複」を減らすことができます。
mike30
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.