例外を伴うビジネスルールの表現


16

私はそれが高価であることを知っていますが、(IMO)それは非常に良い習慣だと思います。たとえば、営業担当者でない場合は請求書を保存できないなどのルールについて話しているので、その場合は「あなたは許可されていません」などの例外をスローします...

別のアプローチは、ステータスなどのオブジェクトを持つことです

他のアプローチはありますか?それについてどう思いますか?

回答:


15

例外を使用して個々のビジネスルールチェックを表すことを意味する場合、それは非常に良い考えだとは思いません。多くの場合、複数の失敗した状態を報告する必要があり、最初の状態で停止することはありません。

一方、私がチェックすることを信じていないすべてのルールや、その後の要約で例外をスローすることをお勧めします。


1
それはまさに私のアプリでそれを処理する方法です。FluentValidationを使用して私の生活を楽にし、ValidateAndThrowメソッドを使用すると時間を節約できます。
マッテオモスカ

UIアプリでは完全に同意しますが、サービス層アプリでは、ビジネスルールに準拠していないオブジェクトが渡されると例外が生成されます。この2つを組み合わせて使用​​している場合、最後の文でマティアシャが説明しているように、検証関数または複雑なエラーを追加することがあります。
ビル

8
ドメイン固有の例外をスローします。これにより、私たちのものそうでないものをより高く分けることができます。

@ThorbjørnRavn Andersen +1「ドメイン固有」の素晴らしい追加
ジャスティンオームズ

1
@JamesPoulsonのJamesPoulsonExceptionサブクラスとして作成しRuntimeException、元の例外をとして提供するだけで十分な場合がありますcause。その後、単にif (exception instanceof JamesPoulsonException)... 区別するように言うことができ ます。getCause()メソッドを使用して、元の例外に到達します。

9

あなたが私たちに与えた例では、例外を上げることは悪い考えだと思います。ユーザーが作業を開始する前に承認されていないことがわかっていても、ユーザーが何らかの機能を実行できるようにし、既にタスクを完了した後にメッセージを叩くことができる場合、それは悪い設計です。

例外を使用してビジネスルールを実施することは、適切な設計ではありません。


あなたが言ったことについて私が理解しているのは、UIに同意しないということです。大丈夫です。はるかに使いやすいUIでは、許可されていないものを更新しようとはしないことに同意します。しかし、それはビジネスコアでの検証と例外チェックが不要であることを意味しません。それどころか、彼らは必見だと思います。正しくプログラムされていないUIがBLの誤用を許可しないようにするために必要です。
フェデ

8
@Fede:懸念の分離の問題です。UIは、ユーザーの意図を収集し、ビジネスレイヤーからのフィードバックを報告します。ビジネスレイヤーの仕事は、UIによって収集された情報を分析し、それを分析して、UIにレポートを返すか、データレイヤーにデータを保持するよう要求することです。これらのレイヤー間の疎結合のみが存在する必要があります。例外は、疎結合に対する貧弱なアプローチです。レイヤー間で実際のクラスを共有することを意味するだけでなく、予期しない障害を処理するためのメカニズムも呼び出します。
アダムクロスランド

@Adam-よく言って、まさにその通りです。
ウォルター

1
@Adam-懸念事項の分離の問題についてフォローしてはいけません。UIの誰もCustomerNameInLowercaseExceptionを処理することを期待していません(例外が存在しないことを願っています!)。一般的なValidationExceptionを処理するだけです。その上、私はUIが情報だけを収集するべきであるとあなたと100%です。前に言ったことは、UIで何をしても、BLはすべての入力が正常であると仮定すべきではないということです。それは単なる防御的なプログラミングです。
フェデ

@Fede:すべての入力が正常であることを保証するのはビジネスレイヤーの仕事です。UIが実行している場合、ビジネスロジックを実装しています。ここで、入力フィールドが数字に制限され、BLがアルファ文字を認識する場合 必ず 例外 スロー ます。コンポーネントが別のコンポーネントから無効な 入力を受け取るたびに、例外をスローすることは論理的で正しいことです。インターフェイスが壊れており、システムが壊れています。ただし、入力の検証は、ビジネスロジックの実行とは大きく異なります。2つの非常に異なるもの。
アダムクロスランド

5

優れたビジネスロジックを作成する上で、例外をスローすることの価値がわかりません。システムの運用における予期しない状況に対処することを目的としたシステムの使用を伴わないビジネスロジックの処理には、多数のアプローチがあります。

ビジネスロジックでは、条件が満たされないことが予想されます。それがそもそもそれを持っている理由であり、予期しないI / Oエラー、メモリ不足エラー、null参照を処理するのと同じメカニズムに便乗したくありません。これらはシステムの障害ですが、満たされていないビジネス条件を検出することは、システムの正常な動作です。

さらに、意図しない結果が発生する可能性のあるシステムです。ある時点で例外をキャッチする必要があるため、意図しない場所でキャッチされる新しいビジネスルールの例外が発生したり、実際に意図されていない例外をキャッチするビジネスルールを探すコードが見つかる可能性がありますそれのための。はい、これらの条件は優れたコーディング慣行で説明できますが、複数の開発者が作業している自明ではないシステムでは、間違いが発生するため、コストのかかる間違いではないことを期待する必要があります。


1
私は同意します、例外は起こると予想されないので、例外と呼ばれます。一方、例外を使用してサービス層にビジネスルールを適用することは必ずしも間違っていません。それが使用されることを期待するのではなく、クライアントが操作を呼び出し、有効な条件を満たすデータのみを送信することを期待します。しかし、クライアントコーディングでも間違いが発生する可能性があることを知っているため、保護層を構築する必要があります。データベースで外部キー制約を使用するようなものです。データを正しく挿入および更新することを期待しますが、プログラミングエラーが原因で失敗する可能性があることは知っています。
ジェレミー

2

ビジネスルールを表現することと実装することは別です

ユーザーエクスペリエンスについて考えます。ユーザーが営業担当者ではない場合、「請求書を作成する」というボタンをすべて提供するのはなぜですか?


1
あなたがボタンを与えないからといって、それは彼らがとにかくあなたに何かをするためのメッセージを送らないという意味ではありません。必要なのはセキュリティルールだけだと考えてください。
jmoreno12年

ユーザーがXの実行を許可されていない場合、「Do X」というボタンをユーザーに提供しないでください。最高のセキュリティは無知です-自分ができないことをユーザーに伝えないでください;)
スティーブンA.ロウ

1

それは完全に何が行われているかに依存します。

まず、あなたが望む実際の動作は何ですか?誰かが自分の情報を入力している場合、拒否と、基本的に「それはできません」というダイアログボックスが正しいでしょう。これがデータ入力者であり、フォームの山から作業している場合、ダイアログボックスもおそらく適切であり、データ入力者は無効なフォームを特別な山に入れることができます。バッチ処理を実行している場合、物事を停止させるのではなく、フラグを立てて次の処理に進みます。

動作を取得したら、それをどのように実装するかを決定する必要があります。例外をスローするビジネスルールチェッカーを使用することをお勧めします。戻りコードを返し、それを引き継ぐことは、間違った方向に進む可能性のある何かであり、間違いのあるエントリがさらに先に進むことは望ましくありません。

パフォーマンスの費用を心配しないでください。個人がデータを入力する場合、関連する他の時間と比較して簡単です。通常、人間はそのシステムで最も時間がかかります。バッチジョブの場合、例外がパフォーマンスの問題である場合、非常に多くの不良レコードを入力していることになり、実際にはそれらすべてを処理および再入力することは、例外よりも多くの問題になります。


0

一貫性のある堅牢で適切に設計された例外APIを持つことは非常に適切です。これを使用してビジネスルールを適用することも適切です。実際、私の経験では、ビジネスルールが複雑になるほど、この方法で処理される可能性が高くなります。権限のある分岐ロジックを作成するよりも、例外が予想されるシステムを作成する方が簡単ではないにしても、同じくらい簡単です。

これは、単一の文で記述できる単純なルールは、一般に、それがどれであるかに応じて、予防的または信頼できる方法で実装されるべきだということです。ただし、多次元であり、3つまたは4つ以上の要因を必要とするルールがある場合(特に、これらの要因の選択が1つ以上の他の要因に基づいている場合)、例外のコーディングはより保守可能です。多くの場合、これらの場合、ロジックパスにはスローする必要がある多くの前兆例外があります(アクションを実行できない理由をチェックします)(またはその逆)セキュリティへのフォールスルーがあります(アクションが許可されていることをチェックします) )、チェックする必要がある信頼できる累積ロジックがいくつかある場合があります(子孫/祖先の可用性、オブジェクトを入れる必要があることを示す前駆体の状態など)。

このタイプの例外のスローから得られる利点の1つは、プロジェクトの複数の領域で前駆体例外を分離して再利用できることです。(これがアスペクト指向プログラミングの本質です。)これを行うことにより、自己完結型の保守可能なコンポーネントに一般的なビジネスルールの特定の側面をカプセル化できます。一般に、これらのコンポーネントは、スローされるエラーメッセージと1-1で対応します。(時には、いくつかの異なる例外をスローする1つのコンポーネントがありますが、複数のコンポーネントから同じ例外がスローされることはほとんどありません。)

私の意見では、例外ベースのシステムを設計することは難しく、最初の開発時間はNレベルすべてにわたって例外プロセスを構築する必要があるため、より長くなります。ただし、これらのシステムは一般的にはるかに安定しています。「失敗しない」システムを設計することは決してできませんが、例外ベースの設計の利点は、常に障害を予測していることです。ほとんどの人にとって、このプロセスは直感に反する可能性があります。それは、道順を尋ねて、誰かにあなたがオンにしてはいけないすべての道を教えてもらうようなものです。

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