I am working with an API that is used for registering bookings in a ticket system. Some of the calls I have to make take complex XML objects as arguments. Some data points in these objects have to be retrieved via multiple API calls in-between which a transformation is necessary before this data is combined with existing user data.
This preparation process too complex for one class and therefore distributed over multiple classes with their own, single responsibility.
So far I created a class Booking
that holds all data that belongs to one booking request. This class is passed around between modules in the process of preparing the data for the final call.
Doing so is working but couples all modules to the Booking
class.
If Booking
changes, a lot of other classes have to change which is a violation of the single responsibility principle as far as I understand it.
I have considered just passing the data around as arguments between the modules but I definitely see this getting messy and prone to errors. Every method involved would have 4-6 arguments that in some cases might be null or optional.
How do I deal with having to aggregate multiple data points that all have to feed into one API-method call without coupling all modules to one class?
Edit:
These are the data points needed in every step. I considered defining classes for every set of arguments but I think this would be kind of hard to maintain because it becomes very intransparent what object is responsible for what data and how the data flows between the modules.
Availability
- rates
- rate quantities
- date, either from user request or retrieved via additional API call
→ returns BookingComponents
Start Booking
- booking key
- promo code
- BookingComponents
- first name
- last name
→ returns booking id, expected total
Credit Card Payment
- booking id
- credit card token
- total amount
→ returns boolean
PayPal Payment
Commit
- booking id
SettlePayment
- total amount
- paypalNonce
- paypalOrderId
Record Payment
- booking id
- total amount
- payment method string
- paypalOrder id
Edit - Added Context for follow-up questions
Modules (Example #1)
The class AvailabilityManager
has the responsibility of getting the availability for tours either in the booking process or in order to display availability on the website. (Relies on very similar calls to the API but has to be done before the booking can be processed)
Is this meant by passing behaviour? (Example #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);
}
}