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


17

私は間違いなくそうすべき ケースで100%乗っています、クライアント側とサーバー側の両方のデータ検証使用するます。

しかし、私が働いてきたフレームワークと環境では、私が見たアプローチは決して乾いたことはありませんでした。ほとんどの場合、計画やパターンはありません。検証はモデルの仕様に記述され、検証はビューのフォームに記述されます。(注:私の実際の経験のほとんどは、Rails、Sinatra、およびjQueryを使用したPHPに関するものです)

それを熟考すると、検証のセット(モデル名、フィールド、条件など)が与えられると、必要なクライアント側とサーバー側の両方のマテリアルを生成できるジェネレーターを作成することは難しくないようです。あるいは、そのようなツールはサーバー側の検証(たとえば、validates ActiveRecordモデルのコード取得し、クライアント側の検証(フォームに適用されるjQueryプラグインなど)を生成できます。

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

それで、データ検証のための「1回だけ書き込み、サーバーとクライアントで実行する」技術の設計にどのようにアプローチしますか?

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

回答:


6

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

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

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

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


うん、異なる言語とフレームワークはこれを非実用的にします。十分なリソースがあれば実行できるため、「元に戻す」ことはできませんが、自動コンバーターを言語間および言語間で作成するのは大変な作業です。妥当な時間内にそれを実行し、関連する技術の変化に応じてそれを維持するのは大変な作業です。
マイケルデュラント14年

多くのサーバー側の検証(フィールドの一意性など)をブラウザー内で実行できないことは間違いありません。ただし、クライアントを信頼できないため、サーバーでクライアント側の検証を繰り返す必要があることも事実です。それは私が物事を乾燥させることが特に有用であると思うところです。たとえば、Railsを拡張してform_for、クライアント側の検証コードを自動的に提供するgem が非常に役立つことがわかりました。
ダン

5

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

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

乾燥していますが、欠点がないわけではありません。まず、クライアント側で処理できた検証でサーバーに負荷をかけるネットワーク往復に依存します。第二に、設計ではすべての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では、各情報を作業関数にマッピングできます。起動するために、データベースを含むアーキテクチャの任意のレイヤーを教えて、一貫して検証を実施できます。


Webブラウザー、トランスポート、実装言語、およびデータベースでフィールドの表現が異なる場合、どのようにフィールドを記述しますか?たとえば、文字列フィールドを表すのに必要なバイト数は、CP1290(IE)、UTF-8(JSON)、UTF-8(C#)、またはUCS-16(Oracle)を使用する場合に異なります。長さの制約とはどういう意味ですか?ブラウザにとってより重要なことは、文字表現がブラウザとオペレーティングシステムに依存する場合ですか?
BobDalgleish 14年

これらの制約は、人間のメンタルモデルを目的としています。プログラマーとしてのあなたの仕事は、機械の違いを抽象化して、技術的な違いを気にする必要がないようにすることです。
マリオT.ランザ14年

あなたはポイントを完全に逃しました。これまでのところ、1つの仕様で、エンドツーエンドの検証を可能にする抽象化を提示した人はいませんでした。OPから、「1回だけ書き込む」とは、異なるステージに対応する異なる句を使用しても資格がないことを意味します。同様に、フィールド間検証またはオブジェクト間検証に対処する検証案には何も表示されません。
BobDalgleish 14年

フィールド間/オブジェクトの検証はそれほど長くありません。メタデータは関係を表すだけです。一度書き込みとは、単一の検証を一度書き込み、それを複数のサイトで強制することを意味します。テーブルにメタデータを追加します。そのメタデータはどのサイトでも受信され、単純なクラス/ユーティリティ/エンジンが制約を実施します。
マリオT.ランザ

1
このような検証言語は非常に便利です。UI集約型Webアプリケーションに関係するコードの3分の1を置き換える可能性があります。
BobDalgleish 14年

2

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

例えば

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

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

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


SQLデータベースに関しては、これがどのように機能するかはわかりません。
マイケルデュラント14年

また、ブラウザとオペレーティングシステムが入力ドメインに影響するという問題も解決しません。
BobDalgleish

@Micheal Durrant、データベースの検証は、DB制約(外部キー、一意など)として実装されます。BobDalgleish、1。ブラウザ/ OS互換性の問題は、ブラウザ(Senchaなど)に応じてランタイムを調整するライブラリを使用することで緩和できます。 DOM / UIレンダリング周辺。
シャミットヴァーマ14

0

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

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

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

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