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


12

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

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

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

時期尚早な最適化なしで、推奨されるアプローチまたはこの質問を扱っているボブおじさんの記事は何ですか?または、「問題になるまでドメインで検証する」と言いますか?

最も基本的な使用例以外の良い例やサンプルを見つけるのに苦労しています。

更新:

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

特に、クライアント向けのREST APIと内部使用機能のためのREST APIを構築するコンテキストでクリーンスタイルアーキテクチャを検討しています。この場合、ビジネスルールの多くは、ネットで目にするすべての例よりもはるかに複雑になる可能性があります。(Clean / Hexアーキテクチャの開発者自身によっても)。

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

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

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

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


2
多くの場合、「正しい」ことと「実用的」であることには違いがあります。選択肢を考えると、どちらを好みますか?
ロバートハーベイ

「すべてのアイテムのリストをロードする」はビジネスルールのようには見えません。実装の詳細を詳しく調べすぎているようです。何もロードせずに、dbクエリを使用してルールを満たすことができる場合、なぜルールは「ロード」と言うのですか?
モニカへの危害を停止する2017

回答:


31

データ入力の検証は、誰もが純粋でクリーンなものにしようと試み始め、(それについて賢明であれば)結局あきらめるものの1つです。これは、非常に多くの競合する懸念があるためです。

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

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

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

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

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

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

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

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

  • 検証の一部の形式は、サードパーティのサービスでのみ実行できます。たとえば、郵便番号と都市名が一緒になっていることを検証する場合などです。

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

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

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


すべてのユーザーのフィードバックをUIで管理していると考える場合、検証チェックのほとんどをデータベースにプッシュして、ビジネスレイヤーで実行できないことだけを維持できます。非常に詳細なメッセージのトラブルシューティングを使用して完全なバックエンドAPIを設計すると、問題が発生します。
Walfrat 2017年

2

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

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

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


2

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

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


0

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

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