web-dev-qa-db-ja.com

クライアント側とサーバー側の検証を1か所で管理する

shoulddefinitely がクライアント側とサーバー側の両方のデータ検証を使用する場合、私は100%オンボードです。

しかし、私が取り組んだフレームワークと環境では、私が見たアプローチは決してDRYではありませんでした。ほとんどの場合、計画やパターンはありません。検証はモデル仕様に記述され、検証はビューのフォームに記述されます。 (注:私の直接の経験のほとんどは、Rails、Sinatra、およびPHP w/jQuery)での経験です)

まとめると、一連の検証(例:モデル名、フィールド、条件)を指定して、必要なクライアント側とサーバー側の両方のマテリアルを生成できるジェネレーターを作成することは難しくないようです。あるいは、このようなツールはサーバー側の検証(ActiveRecordモデルのvalidatesコードなど)を取り、クライアント側の検証(jQueryプラグインなど)を生成して、フォームに適用することもできます。

明らかに、上記は単なる「私がこのアイデアを持っている」ことを考えさせるものであり、正式な提案ではありません。この種のことは、アイデアが思いついたときよりも確かに困難です。

データ検証のための「一度だけ書き込み、サーバーとクライアントで実行する」手法の設計にどのように取り組みますか?

関連サブトピック:特定のフレームワークまたはクライアント/サーバーテクノロジーにそのようなツールはありますか? 1セットの検証のみを維持しようとする場合の主な問題点または課題は何ですか?

17
asfallows

私の限られた経験では、検証が必要なポイントは

  1. HTMLを使用したプレゼンテーションレベル、
  2. プレゼンテーション後のレベル(つまり、JavaScript検証)
  3. 複数のフィールド間の相互作用を一緒に検証する必要がある組み合わせレベルで、
  4. ビジネスロジックレベルで
  5. データベースレベルで。

それぞれに異なる言語、タイミング、トリガーがあります。たとえば、レコード全体が一貫した状態になる前にフィールドを検証するのはほとんど意味がありませんnless 1つだけを検証したい場合。データベースレベルでの制約は、コミット前の最後にのみ適用可能である必要があり、簡単に分割することはできません。

関連する概念は、データの表現が各レベル間で異なるということです。簡単な例としては、WebブラウザがテキストをおそらくCP1290として表すのに対し、データベースはそれをUTF-8で表す場合です。 2つの文字列の長さが異なるため、長さの制約を強制するのは面倒です。

6
BobDalgleish

ソリューションを制限することが多い考慮事項の1つは、ネットワークの往復です。クライアントは、ネットワーク経由でメッセージを送信せずにユーザーデータを検証することになっています。つまり、ユーザーが送信ボタンを押すと、クライアントはローカルでデータを検証することになっています。

まず、この制限がないと仮定しましょう。検証の問題を明確に表現できるネットワークエンドポイントと通信できます。たとえば、新しいユーザーレコードを送信すると、バニラHTTPエラーコードで応答するのではなく、問題を項目化した詳細なJSON応答が返され、クライアントは表示をスマートに更新して、発生した問題を反映します。エンドポイントは検証ゲートウェイの役割を果たします。

これはDRYですが、欠点がないわけではありません。最初に、クライアント側で処理された可能性のある検証でサーバーに負荷をかけるネットワークラウンドトリップに依存します。2番目に、設計は、すべてのCRUD操作がエンドポイントですが、開発者とプロセスが データベースに対して直接 を実行してデータアクセスレイヤーをバイパスする場合はどうでしょうか?

これらの欠点を克服するためのソリューションを再検討してみましょう。代わりに、検証をメタデータとして保存して通信します。

{field: 'username', type: 'required'}
{field: 'username', type: 'unique'} //requires a network roundtrip
{field: 'password', type: 'length', min: 10, max: 50}
{field: 'password', type: 'contains', characters: ['upper', 'special', 'letter', 'number']}

クライアントとサーバーの両方に、このデータを解釈して適用するための何らかのメカニズム(エンジンなど)があります。 (宣言部分をインタープリターから分離するため、これを無料モナドと呼ぶ人もいます。)JavaScriptでは、各情報を機能する関数にマップできます。起動するために、検証を一貫して実施するように、データベースを含むアーキテクチャの任意のレイヤーを教えることができます。

5
Mario T. Lanza

1つの方法は、サーバー側とクライアント側の両方で同じ言語/フレームワークを使用することです。

例えば。

Node.js :: JavaScriptのクライアント/サーバーGET :: Javaのクライアント/サーバー

この場合、検証を含むほとんどの「ドメインオブジェクト」コードが一般的です。フレームワークは必要に応じてコードを呼び出します。例えば。同じコードが「送信」前のブラウザーとサーバー側のWebサービスで呼び出されます。

編集(2014年6月):Java 8を使用すると、JS検証コードをJavaアプリケーションにも簡単に統合できます。Java 8には、より永続的な新しいJS実行エンジンがあります(例:invokeDynamicを利用します)。

2
Shamit Verma

私は同じ問題について考えていました。 ANTLRを使用して、C#とJavaScriptの両方で抽象的な構文ツリーを取得することを考えていました。そこから、ツリーウォーカーを使用して、言語で指定されたアクションを検証されるオブジェクトに適用します。

したがって、必要な検証の説明を好きな場所に(おそらくデータベースに)保存できます。

これが私が問題に取り組む方法です。

0
Marcus