Consider the case where we might want to make use of a service, such as
class MyService {
public double calculateSomethingVeryComplex();
}
These kind of functional-looking classes (that contain only a single method) tend to show up only a single public method, although we know (or imagine, a least), they are composed by a lot of smaller methods internally:
class MyService {
public double calculateSomethingVeryComplex()
private double getA();
private double getB();
private double getC();
...
}
and, although the main method could usually pass its objects to getA()
, getB()
, ...
, through method arguments, we generally tend to define them as class attributes (fields), to get the job done:
class MyService {
private double val1;
private double val2;
private double val3;
public double calculateSomethingVeryComplex()
private double getA();
private double getB();
private double getC();
...
}
If not using dependency-injection, each time we need something very complex to be calculated, we simply instantiate a new MyService
, call its only method, and we're done.
When using dependency-injection we have the apparent problem of wanting to instantiate MyService
in the Composition Root, which is almost okay, although things can get messy with those private fields (for instance, in a multi-threaded scenario).
I see 3 main options here:
- Create a
MyServiceFactory
that I have as dependency to any class that wishes to useMyService
. I don't like this approach as it may in certain kind of applications to skyrocket the number of classes and apparent complexity of the system. - Encapsulate the current
MyService
class in another one, that has the responsibility of instantiatingMyService
, running it, and then returning the calculated value from it. This seems nice as the public API of the class is the same as the original and we happily use dependency-injection with no trouble. - Let it be just as it is. If we try to run 2 concurrent calculations we may have concurrency problems. If we try to run the same method twice one after another, we may have problems with field reuse, also.
The second point seems a clear winner. Is there any other better alternative to point 2, or any of the shown points?