I had a discussion with a colleague and we don't seem to be able to agree. Can someone help me understand his arguments?
Initial situation:
We have an adapter in our application which queries other internal services and constructs out of those request an object for our service. Currently every time we want to use this adapter we have to pass the adapters to communicate with those services into the constructor. Creating and using our adapter looks something like this (we use a builder):
UserAdapter UserAdapter = UserAdapter
.builder()
.amisAdapter(
(AMISAdapter) AdapterFactory.getInstance(
ServiceConfiguration.AMIS.code()
).getAdapter(AdapterType.AM)
).build()
;
LocationAdapter locationAdapter = LocationAdapter
.builder()
.bdisAdapter(
(BDISAdapter) AdapterFactory.getInstance(
ServiceConfiguration.BDIS.code()
).getAdapter(AdapterType.BD)
).businessPartnerAdapter(businessPartnerAdapter)
.build()
;
//Create our custom adapter and inject the adapter dependencies
OurCustomAdapter ourCustomAdapter = OurCustomAdapter
.builder()
.lnisAdapter(
(LNISAdapter) AdapterFactory.getInstance(
ServiceConfiguration.LNIS.code()
).getAdapter(AdapterType.LN)
).UserAdapter(UserAdapter)
.locationAdapter(locationAdapter)
.build()
;
//Query services with given adapters and construct our custom domain entity
ourCustomAdapter.getCustomDomainObject();
This exact same code 1:1 copied appears at the moment a total of 4 times. And this new service is in its early development; in the end we will use this adapter probably at dozens of places. Every time we want to use this adapter we currently have to copy this exact code. 12 lines of identical code every time we want to create the adapter...
My solution
I thought this cant be good and created a "factoryMethod" or however you want to call it. Basically there is a static method (createNew()) on OurCustomAdapter which will create a new instance of our adapter. My idea was to prevent all this duplicate code. Instead of all this code above creating and using our adapter would look like this:
//Query services with given adapters and construct our custom domain entity
OurCustomAdapter.createNew().getCustomDomainObject();
Response from colleague:
My PR was then blocked because: "We wanted to keep this class as decoupled as possible. Therefore, we used dependency injection. Now it’s not only coupled to what’s needed for minimum, but to AdapterFactory, AdapterType, and ServiceConfiguration as well."
When I asked what benefit this provides with an actual example, the only thing we could come up is "that it is better testable" (you can mock those dependencies).
But IMO this argument does not apply, if you really want to mock those adapters. You still can use the old constructor, it still exists.
Some alternative solutions floated around. E.g. using a factory. But they were then discarded, because if the factory uses those adapters you can't test the factory...
I would greatly appreciate some additional unbiased opinion.