DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Introduction to Apache Kafka With Spring
  • A Practical Guide to Creating a Spring Modulith Project
  • Spring Application Listeners
  • Creating Application using Spring Roo and Deploying on Google App Engine

Trending

  • A Walk-Through of the DZone Article Editor
  • How to Write for DZone Publications: Trend Reports and Refcards
  • Docker Hardened Images Are Free Now — Here's What You Still Need to Build
  • Why DDoS Protection Is an Architectural Decision for Developers
  1. DZone
  2. Coding
  3. Frameworks
  4. Can I Have Too Many Dependency Injections?

Can I Have Too Many Dependency Injections?

Static analysis tools limit the parameters included with a method or class constructor. But are there cases where this needs to be adjusted?

By 
John Vester user avatar
John Vester
DZone Core CORE ·
Sep. 19, 19 · Opinion
Likes (1)
Comment
Save
Tweet
Share
70.7K Views

Join the DZone community and get the full member experience.

Join For Free

Is it possible to have too many?

Dependency injections — can you have too many?

Consider this scenario ...

You have the opportunity to work on a new API for your customer. The directive (or your decision) is to use Spring Boot and dependency injection. You start coding — inspired and excited for the new project.

You may also like: Spring Core: Dependency Injection

As a developer or designer, you want to make your services as focused as possible. Meaning if you have a CustomerService  class, it is not doing things with some widget in your application. You decide that the WidgetService class will handle such things. Seems logical.

Your design continues to thrive. Taking a step back, you can easily comprehend the responsibility for all of your service classes — by simply reviewing the list of class names from the file system. You don't even really have to open the Interface for the classes to have insight into a given classes responsibility.

To illustrate, here is an example:

services/
├─ AccountService.java
├─ CustomerService.java
├─ ...
├─ SalesService.java
├─ UserService.java
└─ WidgetService.java


You are proud. This application will be really easy to support and maintain.

Then Things Get Complicated

Imagine that the list of services is more than the five simple classes noted above. Maybe there are fifty or even one-hundred service classes in place when you finish the initial design.

Now, you get to the point where you need to introduce a service that provides cross-service functionality. Like perhaps some global reporting aspect of the application?

Your ReportService  class is introduced as an interface. The implementation class might look like this:

@Service
public class ReportServiceImpl implements ReportService {
private AccountService accountService;
private CustomerService customerService;
private DService dService;
private EService dService;
private FService fService;
private HService hService;
private IService iService;
private JService jService;
private MoreServicesService moreServicesService;
private SoMuchTypingService soMuchTyingService;
private SalesService salesService;
private UserService userService;
private WidgetService widgetService;

public ReportServiceImpl(@Lazy AccountService accountService, @Lazy CustomerService customerService, 
                         @Lazy DService dService, @Lazy EService eService, @Lazy FService fService, 
                         @Lazy GService gService, @Lazy HService hService, @Lazy IService idService, 
                         @Lazy JService jService, @Lazy MoreServicesService moreServicesService, 
                         @Lazy SooMuchTypingService soMuchTypingService, @Lazy SalesService salesService
                         @Lazy UserService userService, @Lazy WidgetService widgetService) {
    this.accountService = accountService;
    this.customerService = customerService;
    this.dService = dService;
    this.eService = eService;
    this.fService = fService;
    this.gService = gService;
    this.hService = hService;
    this.iService = iService;
    this.jService = jdService;
    this.moreServicesService = moreServicesService;
    this.soMuchTypingService = soMuchTypingService;
    this.salesService = salesService;
    this.userService = userService;
    this.widgetService = widgetService;
}

/**
     * {@inheritDoc}
     */
    @Override
    public List<SomeObject> someReportingServiceMethod() {
    // Here we go ....
    }
}


In the example above, there are quite a few dependency injections taking place. These don't have to all be services. In fact, most of them could be injections to interfaces defined as extensions to the JpaRepository  API.

However, static analysis tools (like CheckStyle) may report that there are too many parameters of a method or a constructor. With CheckStyle the default is 7, which represents about half of the parameters in the ReportServiceImpl()  constructor.

The ReportServiceImpl  class would fail to build if CheckStyle default functionality is required to pass in the CI/CD pipeline.

Approach Justification

For the example ReportService, assume there is a business need to reach into all of these aspects of the application (either via a service or a repository) in order to provide the expected results to the customer or client.

Time was taken to make sure each service is fine-grained and focused on performing aspects that match the name of the service. Again, making sure the CustomerService  is not doing something the WidgetService  should be doing.

With the reporting service, there is a need to reach into each of the injected services in order to retrieve data that will be reflected in the reporting. As a developer, I could have blurred the lines and said "all of the reporting data will be maintained in the report service" — but I would still end having to inject the repository interfaces to access the actual data.

Thinking outside the box, an alternative approach could place the burden on the client to make the necessary calls into each service of the API and build the report client-side. While this is certainly possible, some items to consider are noted below:

  • The potential to have duplicate reporting logic across multiple client applications, thus increasing the probability for incorrect data

  • The impact on network traffic to make several API calls to retrieve the necessary information

  • The impact on performance for making a client process logic that is probably better suited for (back-end) server-side processing

In the end, the reporting needs (or whatever the driver) must be provided in order to meet the functional needs of the application. Telling the product owner that requirements need to be changed or removed, because there is a goal to not deviate from default properties of a static analysis tool, just may not be acceptable.

Conclusion

Considering the example above, I feel like the best approach toward meeting the needs of the application is to utilize several dependency injections within the public constructor of the service class.

While it may not be common to see as many dependency injections as noted above, I feel like this is a realistic possibility. What I don't know is, what will be the impact if say one-hundred services or repositories were to be injected into a single service? Does the dependency injection start to fail at some point?

Certainly interested in feedback to this concept. Hopefully, I have established a scenario that provides an example where several injections are required to meet the needs of the application.

Have a really great day!

Further Reading

Spring Core: Dependency Injection

Spring DI Patterns: The Good, the Bad, and the Ugly

How Dependency Injection Works in Spring Java Application Development

Dependency injection Spring Framework application

Opinions expressed by DZone contributors are their own.

Related

  • Introduction to Apache Kafka With Spring
  • A Practical Guide to Creating a Spring Modulith Project
  • Spring Application Listeners
  • Creating Application using Spring Roo and Deploying on Google App Engine

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook