web-dev-qa-db-ja.com

ビジネスモデルでサブトランザクションを実行できるソリューションはありますか?

私の質問はヘッダーにあります。ビジネスモデルでネストされたトランザクションを実行できるアーキテクチャソリューションがあるかどうかを知りたいです。説明させてください-Webサービスの標準フローは

  • 入力データを検証する
  • プロセスリクエスト
  • 結果を持続させる
  • 応答を書き込む

ただし、リクエストが処理される前にデータを検証できない場合があります。つまり、リクエストの実行後にシステムを検証する必要があります。このケースをinverted validation caseと呼びましょう。システムが無効になった場合-ビジネスモデルの変更を初期状態にロールバックしたいと思います。システムのパフォーマンスは良好である必要があることに注意してください。リクエストの処理は大量の計算能力を消費するため、変更を2回実行することはできません。1回は検証用、もう1回は実際のリクエスト処理用です。現時点では、リクエスト処理の結果に一時ストレージを使用していますが、合格した場合は検証を実行します。一時ストレージからビジネスモデルにデータを適用します。ただし、このソリューションは、トランザクションが1つある場合(つまり、inverted validationを1回だけ実行する必要があるが、別のinverted validationがある場合)はうまく機能します。これはスパゲッティコードになります。

次に例を示します。貨物の入力リストとして金額と出力を取得するロジスティクスサービスがあるとします。これは、貨物を保管できる各貨物の倉庫のリストです。各倉庫は、別の倉庫が残りを保管する貨物の一部のみを保管できます。たとえば、倉庫Aは貨物の10%を保管し、倉庫Bは貨物の50%を保管し、倉庫Cは貨物の40%を保管します。ウェアハウスのリストを計算するには、サーバーは大量の計算を実行する必要があります。貨物を10未満の倉庫に保管できない場合は、要求を拒否する必要があります。また、一部の貨物サプライヤーが十分な発見を持っていないことが判明する可能性があるため、このサプライヤーは拒否されるべきです。注システムは、現在の要求からすでに処理された貨物によって倉庫の容量を変更できることを考慮する必要があります。したがって、ここでは2つのトランザクションがあります。1つはリクエスト全体の大きなトランザクションで、2つはネストされています。倉庫がない場合と資金がない場合です。ご覧のとおり、ビジネスモデルに変更をすぐに適用することはできません。 [〜#〜] note [〜#〜]:例の問題はトイプロブレムです-実際の問題を示すためだけに作成しました。

2

私が見ているように、要求が予想される一連の操作、つまり、要求の検証、要求の処理、結果の永続化、応答の書き込みに従う場合に機能するパラダイムがあります。おそらく、各リクエストにはこれらのステップごとに個別の実装がありますが、ステップは一定のままです。

これで、手順が変わる可能性のある状況が発生します。これにはいくつかのアプローチがあります。リファクタリングは少なくて済みますが、最終的には2つのソリューションの柔軟性が低くなります。もう1つは、将来、このタイプの新しいタイプの問題に対処する可能性があります。両方を売り込みましょう。どちらを選ぶかを選択させていただきます。

イベントフックアプローチ

現在、これら4つの操作を呼び出すクラスがあります。この一連の操作を大部分は引き続き尊重する必要があると最終的に判断した場合、これは、検証の前に実行する必要のある処理を「検証の一部」と見なすことができることを意味します。ただし、私が正しく推測した場合の現在の検証は、おそらく要求入力を処理するためにのみ構築されています。

これを解決するには、最初はクラスに追加しても何もしないイベントフックを追加するだけです。これらのフックの例は次のとおりです。

onPreValidation, onPostValidation, onPreProcess, onPostProcess, etc.

クラスはそれぞれをそれぞれの順序で呼び出し、前のフェーズで返された情報をそのフェーズの実際の処理に渡します。次に、何もしないこれらのメソッドのスタブを作成するため、ほとんどのリクエストでは何も変更されません。

ただし、これにより、このクラスをオーバーライドして、各フェーズの前後に特別なアクションを実行できます。これは最小限のリファクタリングを必要とし、あなたの要求の「4段階」の考えに忠実です。必要に応じて、これから大きく逸脱しない特定のリクエストのカスタムフェーズを作成することもできます。

ただし、取得する必要のあるものが「4フェーズ」の考え方と大きく異なると感じる場合は、このアプローチを採用しないでください。根本的に新しい要求は根本的に異なる方法で処理する必要があり、それが2番目のアプローチにつながります。

抽象リクエストハンドラタイプ

これは、4フェーズクラスの概念を取り入れて抽象化します。理想的には、リクエストの入力を受け取り、レスポンスインスタンスを返すことができる必要があります。したがって、これはさまざまな方法で実装できる可能性があります。

次に、現在のクラスはこの抽象要求ハンドラーから派生し、呼び出されると、常に通常どおり実行される通常の4つのフェーズを実行し、応答インスタンスを潜在的にシリアル化して呼び出し元に返します。

このタイプを使用して、新しい反転検証ケースの新しいリクエストタイプを作成します。この新しいリクエストハンドラは、検証の前に必要な処理を実行します。適切に実行された場合、これらのフェーズの実際の実装は他の場所で実行する必要があるため、抽象ファクトリを使用して、これらの個々のフェーズを処理する具象クラスを作成する可能性があります。この抽象ファクトリは、おそらく抽象リクエストハンドラ自体によって提供されます。したがって、理想的には、リクエストハンドラのコンテキストでこれらのステップの変更されるのはステップのみおよび順序です。

これには最も多くのリファクタリングが必要になりますが、将来的には新しいタイプのリクエストの適切な基盤が作成されます。

結論

どちらのソリューションでも、実際の実装ではなく、リクエストのステップを抽象化していることを強調しておきます。これにより、将来の開発の良い基盤が作成され、将来新しいリクエストに対応できるようになります。

2
Neil