While doing code reviews, I usually come across DI framework (ex: Spring) managed beans with no constructor. I myself have done this many times (and still for POCs).
What you can see in these classes is, fields are annotated with @Autowired, @Resource, @Inject, etc. How do they write unit tests then? They will for example use @InjectMocks using mock framework.
As I am not a fan of this approach I ask the reasons why are you creating classes like this and use constructors. However, many will not agree with me giving these kinds of reasons.
Reasons to use field injection
- We are using a DI framework (Spring), do not need to worry about this.
- The unit testing framework we use support field mocking (InjectMocks).
- We can use reflection in unit tests.
- Different developers have different practices, you need to accept that fact and respect them.
- This is how the previous developer coded.
- This is how our internal framework use.
- I'm senior than you, do as I say :P.
While those can be accepted for a very small project, I fully disagree for a medium to large projects. Even for a small project, I would say don't do that.
While I do not want to answer above, I would like to highlight the problems.
There are multiple disadvantages when we use field injection.
Disadvantages of field injection
- DI is bound to the framework.
- Unit tests have to rely on mock framework's injecting mechanism.
- Field injection has performance cost when creating beans.
- Introduces hidden dependencies.
- Object is not created with mandatory fields.
- Can introduce NullPointerException.
- Domain is polluted with external libraries.
- Domain depends on external libraries.
- In long run, you are unable to move with new technologies.
Do you want to live with those? Or will you switch to constructor injection? In addtion to avoid above disadvantages we get other advantages as well.
Advantages of construtor injection
- Pure Java class
- Cleaner designs
- Clean unit tests
- Domain is properly isolated from external frameworks
- Switch to other technologies quickly
- Relevant framwork updates with minimum change
One can argue that class get unneccerily bigger due to constructors, getter, setter. For this I would use Lombok, yes external library but it has no impact on domain.
How about bean creation if we are not allowed to use DI annotations (ex: @Service)? You can use @Bean as it is outside of the domain. Still not interested in creating many beans? Then use custom annotation. (lazy to describe at the moment).
Happy coding :)
Post a Comment