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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Introduction to Apache Kafka With Spring
  • Dependency Injection in Spring
  • A Practical Guide to Creating a Spring Modulith Project
  • Spring Application Listeners

Trending

  • AI Agents: A New Era for Integration Professionals
  • The Evolution of Scalable and Resilient Container Infrastructure
  • Infrastructure as Code (IaC) Beyond the Basics
  • Prioritizing Cloud Security Risks: A Developer's Guide to Tackling Security Debt
  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.4K 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
  • Dependency Injection in Spring
  • A Practical Guide to Creating a Spring Modulith Project
  • Spring Application Listeners

Partner Resources

×

Comments
Oops! Something Went Wrong

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

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

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 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!