Dependency Injection – Method call

Hi there,

this is the second part of the article about (Dependency Injection – Field vs Constructor vs Method).

In the comments I was hinted that I forgot to mention the 5th way of dependency injection, the injection of behavior when a method is called and I was asked if I can give some example when which kind of injection, besides field injection, is feasible.

Then let’s introduce first the

Method call injection

This kind of injection takes advantage of parameters that can passed to a method call.
When applying this variant of dependency injection you pass the behavior you want to be used in the method as a parameter when you call it.

It is very handy when you

  • can’t determine the needed behavior upfront or
  • the behavior that should be used depends on information that is not and should not be available in the called method

Where to locate these variant on the scale of visible vs invisible and mandatory vs optional?
Let’s have a look

Visible vs invisible

Besides the method contract that requires the behavior to be injected on call, there is also the option to have a “smart/clever” default behavior, eg. a no-op implementation, that will be used by a simplified parameter list.  But the point goes straight forward to visible, because the caller of the method has to fulfill the contract specified when he uses the richer method.

Mandatory vs optional

We can follow here the same reasoning as before, but this answer depends heavily if you have a default method implementation which must not have the injected behavior. So for this section, the method call injection can be both.

Drawbacks

As the most things in the world, this sort of dependency injection is a two sided medal.
The drawbacks when applying it, are that you must check if the behavioral parameter is set or not. In Java for example a not null check or the @NotNull annotation can be instrumented for that. Additionally you must define what should happen in this case, should be an error thrown? Or should the method fallback to a default implementation?

This question can only be answered by your requirements.

 

Now that we have introduced this variant of dependency injection let’s answer the questions raised by Pictor in the comments.

When to apply method call injection?

As described in the above section, this variant comes usually in place when it is impossible or expensive to determine what should be injected when the injection happen. Or it is, as said impossible withing the context of the method with the information available to choose from multiple options the right one.

An example could be the derived from an article I wrote some time ago about dynamic dependency injection in Java EE. The interesting part is the class TaxCalculator.java. As an alternative to the model name, the caller could have used the factory directly and passed it to the mentioned class (even if this would end up with removing this class and using the class returned by the factory directly in this example 😉 ).

When it is a good approach to have optional dependencies?

This is a very good question, because I use these style rarely. The situations where I’m tend to use it, is when I write (internal) libraries or gradle plugins.

I would say one indicator for optional dependencies is, when you apply a kind of conventions over configurations.

For example at tyntec we calculate for each message we take care of a message id for tracking reasons. Besides a default format, we have some cases where we apply a different one. The different format can be specified by an optional dependency.

Or a sort of retry scheme calculation could be implement in this way.

More details in depth for the mixed approach

Let’s see if I can be more precise / detailed on this.

As said in the previous article this approach combines both the constructor and method / setter injection.

I would like to give you an example that will clarify this a little bit more

As you can see the blender specifies in it’s contract that it requires strictly Blades to function properly, but because this is a cool blender you can apply extra blades which chop the content an extra round.

So for this approach 4 things needs to be done

  1. Define what are your mandatory and what are your optional dependencies.
  2. Decide for the optional dependencies if you can have meaningful defaults or must check if the dependencies are unset in your code
  3. Put the mandatory , and only the mandatory, dependencies to the constructor
  4. Define setter methods for the optional dependencies

Have a nice weekend

Peter

 
3 Kudos
Don't
move!

Leave a Reply

Your email address will not be published. Required fields are marked *