8

データ検証に関して、次の 2 つのパターンのどちらかを決定しようとしています。

  1. 公称ワークフローに従い、モデルとサービスによってスローされた例外をキャッチしようとします: 一意/外部制約違反、空のフィールド、無効な引数など... (!! キャッチすべき例外のみをキャッチします)

    • 長所:コントローラーとサービスに記述するコードがほとんどない: 例外を処理し、それらをユーザーが理解できるメッセージに転記するだけです。非常にシンプルで読みやすいコード

    • 短所:特定の例外を記述する必要があります。これは、さまざまな例外になる場合があります。また、データベース例外 (制約違反など) の一般的な PDO/Doctrine 例外をキャッチして解析し、それらを意味のある例外 (例: ) に変換する必要がありますDuplicateEntryExceptionまた、いくつかの検証をバイパスすることもできません。モデルのオブジェクトがロックされているとマークされているとしましょう。削除しようとすると例外が発生します。ただし、強制的に削除したい場合があります(たとえば、確認ポップアップを使用)。ここで例外をバイパスすることはできません。

  2. コードと DB クエリを使用して、すべてを明示的にテストし、事前検証します。たとえば、モデルで属性として設定する前に、何かが null ではなく整数であることをテストします。または、DB クエリを作成して、重複するエントリを作成しないことを確認します。

    • 長所:特定の例外を記述する必要はありません。なぜなら、すべてを事前検証するため、とにかく多くの try/catch を実行するべきではないからです。また、必要に応じて検証をバイパスすることもできます。

    • 短所:コントローラー、サービス、およびモデルに書き込むための多くのテストと検証。さらにクエリを実行します(検証部分)。DBは、null列ではなく、外部キー、一意の制約の検証をすでに行っています...それを無視して自分で再コーディングするべきではありません。また、これは非常に退屈なコードにつながります!

物事をできるだけシンプルに保つために、ミックスではなく、どちらかのパターンを使用したいと思います。

最初の解決策は私には最高のように思えますが、それはある種のアンチパターンではないでしょうか? それとも、その理論的な単純さの裏に、非常に扱いにくい状況が隠されているのでしょうか?

4

1 に答える 1

2

データ検証は、アプリケーションの境界で行う必要があることをお勧めします。つまり、入ってくるデータはすべて、期待を満たしていることを確認するためにチェックする必要があります。アプリケーションへのアクセスが許可されると、検証されなくなりますが、コンテキスト(DB、電子メールなど)に応じて常にエスケープされます。これにより、すべての検証をまとめて、検証作業の潜在的な重複を回避できます(簡単に実行できます)。両方がそれを使用する2つのモデルによってデータを2回検証できる例を挙げてください。)Joe Armstrongは、Erlangに関する彼の本でこのアプローチを推進しており、彼がtelcomステーション用に作成したソフトウェアは、再起動せずに何年も実行されるため、うまく機能しているようです。 )。

さらに、モデルの期待値は、特定のインターフェースによって確立された期待値と常に完全に一致するとは限りません(フォームが潜在的なオプションのサブセットのみを示しているか、インターフェースに米国の州のドロップダウンがあり、モデルに多くの州が格納されている可能性があります)さまざまな国など)複雑なインターフェイスによって、ユーザーエクスペリエンスを向上させる方法で複数の異なるモデルオブジェクトを統合できる場合があります。ユーザーにとっては便利ですが、例外アプローチを使用したこれらのモデルの相互作用は、どちらのモデルだけでも検証できないハイブリッド入力である可能性があるため、処理が非常に難しい場合があります。検証が何よりもまずUIの期待に一致することを常に確認する必要があります。また、2番目のアプローチでは、最も複雑なインターフェイスでもこれを実行できます。

また、例外処理はサイクルの点で比較的高価です。検証の問題は非常に頻繁に発生する可能性があり、問題を処理するためのこのような費用のかかる操作は、非常に頻繁に発生する可能性があるよりも避けようとします。

最後に、モデルにはいくつかの検証は実際には必要ありませんが、攻撃を防ぐためにあります。これをモデルに追加することはできますが、追加された機能によってモデルコードがすぐに混乱する可能性があります。

したがって、これら2つのアプローチのうち、2番目のアプローチをお勧めします。理由は次のとおりです。

  1. アプリの境界を明確にすることができます。
  2. すべての検証は1つの場所にあり、共有できます。
  3. 2つ以上のモデルが同じ入力を使用する場合、検証の重複はありません。
  4. モデルは、抽象エンティティの知識をアプリケーションの状態にマッピングするという、得意なことに焦点を当てることができます。
  5. 最も複雑なUIでも適切に検証できます。
  6. プリエンプションの方が効率的です。
  7. 実際にはどのモデルにも属していないセキュリティに焦点を当てた検証タスクをアプリにきれいに追加できます。
于 2012-10-26T18:53:14.920 に答える