web-dev-qa-db-ja.com

モジュールをパラメーターオブジェクトに結合せずに複雑なAPI呼び出しのデータを集計する

私は、チケットシステムで予約を登録するために使用されるAPIを使用しています。私がしなければならない呼び出しのいくつかは、引数として複雑なXMLオブジェクトを取ります。これらのオブジェクトの一部のデータポイントは、このデータが既存のユーザーデータと結合される前に変換が必要な複数のAPI呼び出しを介して取得する必要があります。

この準備プロセスは1つのクラスには複雑すぎるため、独自の単一の責任を持つ複数のクラスに分散されます。

これまでのところ、1つの予約リクエストに属するすべてのデータを保持するクラスBookingを作成しました。このクラスは、最後の呼び出しのためにデータを準備する過程でモジュール間で渡されます。

これは機能しますが、すべてのモジュールをBookingクラスに結合します。 Bookingが変更されると、他の多くのクラスも変更する必要があり、私が理解している限り、これは単一責任の原則に違反します。

私はモジュール間で引数としてデータを渡すことを検討しましたが、これが乱雑になり、エラーが発生しやすくなることは間違いありません。関係するすべてのメソッドには4〜6個の引数があり、場合によってはnullまたはオプションになることがあります。

すべてのモジュールを1つのクラスに結合せずに、すべてが1つのAPIメソッド呼び出しにフィードする必要がある複数のデータポイントを集約する必要がある場合、どのように対処しますか?

編集:

これらは、すべてのステップで必要なデータポイントです。引数のセットごとにクラスを定義することを検討しましたが、どのオブジェクトがどのデータを担当し、どのようにデータがモジュール間を流れるのかが非常に不透明になるため、これを維持するのは少し難しいと思います。

可用性

  • 料金
  • レート数量
  • ユーザー要求から、または追加のAPI呼び出しを介して取得した日付

→BookingComponentsを返します

予約を開始

  • 予約キー
  • プロモーションコード
  • BookingComponents
  • eメール
  • ファーストネーム
  • 苗字

→予約ID、予想合計を返します

クレジットカード決済

  • 予約ID
  • クレジットカードトークン
  • 合計金額

→ブール値を返す

Paypal支払い

コミット

  • 予約ID

SettlePayment

  • 合計金額
  • paypalNonce
  • paypalOrderId

支払いの記録

  • 予約ID
  • 合計金額
  • 支払い方法文字列
  • paypalOrder ID

編集-フォローアップ質問のコンテキストを追加

モジュール(例#1)

Modules involved in booking process

クラスAvailabilityManagerは、予約プロセスで、またはWebサイトに空席状況を表示するために、ツアーの空席状況を取得する責任があります。 (APIへの非常に類似した呼び出しに依存しますが、予約を処理する前に実行する必要があります)

これは動作を渡すことを意味しますか? (例#2)

    class InitialBooking{
        protected $date;
        protected $rates;
        protected $quantities;

        //the actual operation is more complex, involves more methods 
        // and will be needed outside of the Booking process as well
        public function verifyAvailability(): BookingComponent
        {
            $availabilityResult = $this->api->getAvailability($date, $rates, $quantities)
            return $this->bookingComponentTransformer->transform($availabilityResult);
        }
    }
1

あなたはすでにデータの受け渡しを検討していると書いていますが、それは面倒になります。 動作を通過するという反対を検討しましたか?

あなたの説明から正しい振る舞いを理解するのは本当に難しいですが、ここにいくつかの考えがあります:

  • オブジェクトからステートマシンを作成しないでください。状態ごとに異なるオブジェクト、できれば不変なオブジェクトを返します。物事について考えたりテストしたりすることがはるかに簡単になります。 APIユーザーにとっても簡単です。
  • データを引き渡さないようにしてください(つまり、getter)。これは、回避しようとしている維持不可能な混乱につながります。
  • 一般に、クライアントに「フロー」を駆動させます。あなたの責任は、クライアントが無効な呼び出しシーケンスを構築できないようにAPIを設計することです。基本的にguide正しいフローを構築するためのユーザー。

おそらく、クライアントが何を書く必要があるかを想像することから始めることができます。

_new Booking("Double Room")     // returns Booking
   .checkAvailability()        // returns AvailableBooking or Exceptions
   .withPromocode("...")       // same
   .withEmail("...")           // same
   .pay(new CreditCard(...))   // returns PayedBooking or whatever
_

これらはそれぞれ不変であり、プロセスの完全に異なる部分に責任があります。ユーザーはフローを操作しますが、意味のあるオプションしかありません。たとえば、彼女はcheckAvailability()を呼び出す必要があります。これが予約を続行する唯一の方法であり、他の場所では利用できないため、他の場所で呼び出すことはできません。

それは役に立ちますか?

1