web-dev-qa-db-ja.com

ドメイン対データ永続性レイヤーのアーキテクチャ検証をクリーンアップしますか?

私はクリーンについて研究しており、その結果、ソフトウェアの設計と作成の方法について、かなり劇的に再考しています。

しかし、私がまだ取り組んでいることは、「一部のアイテムへの更新を保存する、最初に読み込む、表示/編集する権限のあるアイテムのすべてのリスト、このアイテムがリストにあることを確認する、そして、そのアイテムカテゴリは現在使用できないようにロックされていません(および他のルールなど) "。それは(複雑だが非定型ではない)ビジネスルールであり、ビジネスロジックをプッシュするのではなく、アプリケーションドメインで処理する必要があるためdb/persistenceレイヤー。

ただし、これらの条件を効率的に確認するには、すべてのデータをアプリケーションドメインにロードするのではなく、巧妙に作成されたdbクエリで処理するのが最善のようです...

早すぎる最適化がなければ、このアプローチを推奨するアプローチやボブおじさんの記事は何ですか?または、「問題が発生するまでドメインで検証する」と言いますか?

最も基本的なユースケース以外の良い例/サンプルを見つけるのに本当に苦労しています。

更新:

こんにちは、返信ありがとうございます。私はもっ​​と明確で、長い間(主にWebアプリ)のソフトウェアを書いていて、まとめて記述したすべてのトピックを確実に経験して同意しているはずです(バックエンドで検証し、クライアントデータを信頼しない、一般的に言って)必要な場合のみ生の効率を追跡しますが、利用可能な場合はdbツールの強みなどを認識し、「まとめて投げる」という開発者の学習ライフサイクルを経て、「N層アプリケーションで巨大な脂肪コントローラーを構築する」コードトレンド、そして今は基本的にクリーンで単一の責任のスタイルなどを非常に気に入って調査しています。最近のいくつかのプロジェクトの結果として、プロジェクトが進化し、クライアントの要件がさらに明らかになるにつれて、非常に不格好で広く分散したビジネスルールに発展しました。

特に、REST APIs for client-facingとinternal-usage機能の構築のコンテキストで、クリーンなスタイルのアーキテクチャを調べています。ビジネスルールの多くはmuch基本的にネットで見られるすべての例よりも複雑です(Clean/Hexアーキテクチャの人たちによっても)。

だから私は、CleanとREST apiがどのように共存するかについて、私は本当に質問しました(そして明確に述べられなかった)と思います。 .NETでは)、しかし、私の「検証」ルールの多くはそれほど「50文字未満の文字列」ではありませんが、「このユーザーはこのユーザーケース/インタラクターを呼び出して、このデータのコレクションに対してこの操作を実行できます」一部の関連オブジェクトは現在、月末などまでチームXによってロックされています...」という、ビジネスドメインオブジェクトとドメインルールの多くが適用される、非常に複雑な検証のようなものです。

これらのルールを特定の種類のValidatorオブジェクトタイプにスピンアウトして、各ユースケースインタラクター(FluentValidatorプロジェクトからインスピレーションを得たものの、より多くのビジネスロジックとデータアクセスが含まれる)に付随させる必要がある場合、検証をゲートウェイのように扱う必要があります。これらの検証をゲートウェイ(間違っていると思います)などに配置します。

参考までに、私は this のようないくつかの記事を書きますが、Mattiaは検証についてあまり議論していません。

しかし、私の質問への短い答えは、私が受け入れた答えに非常に似ていると思います:「それは決して簡単ではなく、それは依存します」。

12
Dale Holborow

データ入力の検証は、誰もがそれを純粋でクリーンにしようと試み始め、(それについて賢明であれば)結局あきらめるものの1つです。

  • UIレイヤーは、ユーザーにリアルタイムのフィードバックを提供するために、クライアントページ/フォーム上で何らかの検証を行う必要があります。それ以外の場合、トランザクションがネットワーク全体に送信される間、ユーザーは多くの時間をフィードバックの待機に費やします。

  • クライアントは信頼できないマシン(たとえば、ほぼすべてのWebアプリケーション)で実行されることが多いため、これらの検証ルーチンは、コードが信頼されているサーバー側で再度実行する必要があります。

  • 入力制約のため、一部の検証形式は暗黙的です。たとえば、テキストボックスでは数値のみ入力できます。これは、「数値ですか?」ページ上のバリデーターですが、UIの制約が回避される可能性があるため(たとえば、JavaScriptを無効にすることにより)、バックエンドのどこかにまだバリデーターが必要です。

  • インジェクション攻撃やその他の悪意のある形式のデータ入力からシステムを隔離するために、UIレイヤーはサービス境界(Webアプリケーションのサーバー側コードなど)で何らかの検証を行う必要があります。時々、この検証はあなたのコードベースにさえありません、例えば。 ASP.NETリクエストの検証

  • UIレイヤーは、ユーザーが入力したデータをビジネスレイヤーが理解できる形式に変換するためだけに、何らかの検証を行う必要があります。たとえば、文字列 "6/26/2017"を適切なタイムゾーンのDateTimeオブジェクトに変換する必要があります。

  • 理論上はビジネスレイヤーはビジネスレイヤーに属しているため、ビジネスレイヤーはほとんどの形式の検証を実行する必要があります。

  • 特に参照整合性チェックが必要な場合(たとえば、状態コードが50の有効な状態のリストに含まれていることを確認するため)、一部の形式の検証はデータベースレイヤーでより効率的です。

  • 検証のいくつかの形式は、同時実行性の問題により、データベーストランザクションのコンテキストで発生する必要があります。一意のユーザー名の予約はアトミックである必要があるため、処理中に他のユーザーがそれを取得することはありません。

  • 一部の形式の検証は、サードパーティのサービスでのみ実行できます。郵便番号と都市名が一致することを検証するとき。

  • システム全体で、コードの欠陥がある場合に妥当な障害モードを保証するために、ヌルチェックとデータ変換チェックが複数の層で行われる場合があります。

一部の開発者がビジネスレイヤーのすべての検証ルールを体系化し、他のレイヤーにそれを呼び出してビジネスルールを抽出し、別のレイヤーで検証を再構築するのを見てきました。理論的には、これは真実の単一のソースに終わるため、素晴らしいでしょう。しかし、私はこのアプローチがソリューションを不必要に複雑にする以外のことをしたことは一度もありません。

したがって、検証コードがどこに行くのかを突き止めようとして自殺している場合は、助言してください。中程度に複雑な問題の実用的な解決策では、検証コードはいくつかの場所に行き着きます。

31
John Wu

検証はビジネス層の一部です。

重要なのは、DAOのビジネスロジックはDAOの概念を無効にすることです。上位層で検証を行うと、別のユースケースからビジネスオペレーションを呼び出す場合、検証が冗長になります。

たぶん、UIのセキュリティを評価します。ただし、保護されたドメインオブジェクトが重要な役割を果たすため、これはオプションです。 UIでは、現在ログインしているユーザーの権限に応じて、コンポーネントを表示または非表示にします。ただし、これはユーザーエクスペリエンスの一部にすぎません。ユーザーが許可されていないアクションを実行しようとするたびに、ユーザーがセキュリティ例外に遭遇しないようにする必要があります。

2
oopexpert

検証に対して誰が何をしているのかについての見方を確認したい場合があります。 DBを使用していることがわかっているのはDBですか?または、それはサービスです(たまたま、DB操作によってバックアップおよび制御されます)。私のプロジェクトでは、すべての集約ルートに、それを読み取ることができるグループのリストと修飾子のリストがあります。コードが特定のルートまたはユーザーが見ることができるルートのリストを探すとき、すべての詳細は、ユーザーIDと、タイルが「何とか」で始まる場所などのルックアップコンテキストの追加部分を受け取るサービスの背後に隠されます。コードは、DBが存在チェックを実行して、ユーザーのグループが読者のグループに存在するかどうかを確認しません。契約によってのみ定義されるサービスが提供するものに基づいて、コンテンツの有無にかかわらずリストを期待するだけです。

これは下のレイヤーすべてに適用されます。検証の均一性が重要です。できるだけ多くの検証をドメインに配置します。 APIで制約を返します。 XライブラリやZストレージからの制約ではなく、サービスからの制約については考えていません。

2
Virmundi

検証ロジックがデータベースクエリの形式で最も単純かつ最も明確に表現されている場合は、先に進んでください。ただし、効率は、既知のパフォーマンスの問題がある場合にのみ問題になるはずです。そうでない場合は、時期尚早の最適化です。

0
JacquesB