Suppose I have MyClass
with a very simple dependency. It uses constructor injection.
public class MyClass : IMyClass
{
private IA A;
public MyClass(IA a)
{
A = a;
}
}
This code get shipped and some other developers are using it.
At some point in the future I need to add in a second dependency, on IB.
How should I add this dependency on IB?
Some options, and why I disapprove:
- Just add it to the constructor
- Braking change.
- Inheritance or the decorator pattern.
- Extra classes and code bloat.
- New class will have boilerplate code passing around the IA.
- I have no guarantee that other developers will switch to using the new class.
- Use a service locator to populate the new IB field.
- I'm now using two different types of injection for extra confusion.
It seems to me that constructor injection is just not easily extensible.
2 Answers 2
- Create an implementation of
IB
that contains whatever behaviorMyClass
currently possesses that is being extracted, or ifIB
provides new functionality, then a sensible default implementation that preservesMyClass
's current semantics. - Add
IB
dependency toMyClass
via a new constructor. - Have the old constructor create an instance of the implementation of
IB
you made in step 1.
Old code still works, new code can provide alternate behavior as desired.
-
So you are saying, create an "empty" implementation of IB, which the old contructor can use?Swesus– Swesus05/08/2014 12:37:44Commented May 8, 2014 at 12:37
-
A couple of reasons why I'm not 100% happy with this solution. 1) Code bloat of this empty class. 2) I have no guarantee that other developers will switch to using the new non-empty class.Swesus– Swesus05/08/2014 12:52:58Commented May 8, 2014 at 12:52
-
1Isn't a "guarantee developers will switch" the definition of breaking change?Dan– Dan05/08/2014 13:01:17Commented May 8, 2014 at 13:01
-
The implementation doesn't have to be empty. I don't know what you're trying to do so I don't know what constitutes a sensible default implementation.Doval– Doval05/08/2014 14:10:21Commented May 8, 2014 at 14:10
If MyClass
needs to have an IB
to function, then there is not really a choice.
Any non-breaking change would just results in bugs because the others will keep using MyClass
without providing the required IB
object, so you can just as well prevent that and make the new dependency a required parameter of your constructor.
If the dependency on IB
is optional, then you have a few options:
- Derive a new
MyClass_version2
fromMyClass
and provide all the newIB
-related behavior from there. This will likely work best if there is little overlap between the existing behavior and the extensions. - Add the new
IB
dependency toMyClass
, but ensure to set it tonull
in the existing constructor and ensure that all methods can handle a nullIB
. Then add an overload of the constructorMyClass(IA a, IB b)
.
Explore related questions
See similar questions with these tags.
private IB B = new B();
, doesn't break anything. Only when we try to use constructor injection do we see a breaking change. Do you agree?