I am applying the Hexagonal Architecture (Ports and Adapters) to my system and I have noticed a dependency from my primary (driver) side adapter to the secondary (driven) side port. This doesn't seem right; there should be way to handle this.
Let's say I have two very basic ports in my domain; one is at the driver side and one is at the driven side.
// Primary Port
interface ForecastGenerating {
Forecast[] generateForecastsForAllLocations();
Forecast[] generateForecastsForLocation(Location location);
}
// Secondary Port
interface LocationFetching {
Location[] fetchAllLocations();
Location fetchLocationbyId(String locationId);
}
I then have my domain logic as below. It expects a concrete implementation of the LocationFetching
port.
// Domain Implementation
class ApplicationForecastGenerator implements ForecastGenerating {
private LocationFetching locationFetching;
public ApplicationForecastGenerator(LocationFetching locationFetching) {
this.locationFetching = locationFetching
}
Forecast[] generateForecastsForAllLocations() {
Location[] locations = this.locationFetching.fetchAllLocations();
// Do my domain thing and generate forecasts
}
Forecast[] generateForecastsForLocation(Location location) {
// Do my domain thing and generate forecasts
}
}
And finally, we have the primary adapter that is tying this all together:
// Primary Adapter Implementation
class UIBasedForecastGenerator {
private ForecastGenerating forecastGenerating;
public UIBasedForecastGenerator(ForecastGenerating forecastGenerating) {
this.forecastGenerating = forecastGenerating;
}
public void userTappedOnGenerateButton() {
Location location; // How does the primary adapter get its hands on the Location object?
Forecast[] forecasts = this.forecastGenerating.generateForecastsForLocation(location);
System.out.println(forecasts);
}
}
The question in the primary adapter implementation is that how do I get a reference to the Location
object? I can definitely use the LocationFetching
port and have a dependency on it but that sounds a bit odd to me; a driver side adapter having a dependency on the driven side port. I feel like domain should be responsible for providing this object but the ForecastGenerating
port shouldn't expose such a functionality; it seems to be out of scope of forecast generation.
How do we handle such dependencies in this architecture?