Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which dependencies should I inject?

When using dependency injection which dependencies do you inject?

I have previously injected all dependencies but have found when doing TDD there are typically two types of dependency:

  • Those which are genuine external dependencies which may change e.g. ProductRepository
  • Those which exist purely for testability e.g. Part of the behaviour of the class that has been extracted and injected just for testability

One approach is to inject ALL dependencies like this

public ClassWithExternalDependency(IExternalDependency external,
    IExtractedForTestabilityDependency internal)
{
    // assign dependencies ...
}

but I've found this can cause dependency bloat in the DI registry.

Another approach is to hide the "testability dependency" like this

public ClassWithExternalDependency(IExternalDependency external)
    : this (external, new ConcreteClassOfInternalDependency())
{}

internal ClassWithExternalDependency(IExternalDependency external,
    IExtractedForTestabilityDependency internal)
{
    // assign dependencies ...
}

This is more effort but seems to make a lot more sense. The downside being not all objects are configured in the DI framework, thereby breaking a "best practice" that I've heard.

Which approach would you advocate and why?

like image 791
Alex Avatar asked Nov 09 '10 18:11

Alex


People also ask

Is it good to use dependency injection?

Dependency injection helps to develop testable code, allowing developers to write unit tests easily. You can use mock databases with dependency injection, and test your application without affecting the actual database.

When should I use dependency injection?

More specifically, dependency injection is effective in these situations: You need to inject configuration data into one or more components. You need to inject the same dependency into multiple components. You need to inject different implementations of the same dependency.

What is the most common type of dependency injection?

The most common way is using constructor injection, which requires that all software dependencies be provided when an object is first created. However, constructor injection makes the assumption that the entire system is using the pattern, which means the entire system must be refactored at the same time.


1 Answers

I believe you're better off injecting all of your dependencies. If it starts to get a little unwieldy, that's probably an indication that you need to simplify things a bit or move the dependencies into another object. Feeling the "pain" of your design as you go can be really enlightening.

As for dependency bloat in the registry, you might consider using some sort of conventional binding technique, rather than registering each dependency by hand. Some IoC containers have convention-based type-scanning bindings built into them. For example, here's part of a module I use in a Caliburn WPF application that uses Ninject:

public class AppModule : NinjectModule
{
    public override void Load()
    {
        Bind<IShellPresenter>().To<ShellPresenter>().InSingletonScope();

        BindAllResults();
        BindAllPresenters();
    }

    /// <summary>
    /// Automatically bind all presenters that haven't already been manually bound
    /// </summary>
    public void BindAllPresenters()
    {
        Type[] types = Assembly.GetExecutingAssembly().GetTypes();

        IEnumerable<Type> presenterImplementors =
            from t in types
            where !t.IsInterface
            && t.Name.EndsWith("Presenter")
            select t;

            presenterImplementors.Run(
                implementationType =>
                    {
                        if (!Kernel.GetBindings(implementationType).Any())
                            Bind(implementationType).ToSelf();
                    });
    }

Even though I have dozens of results and presenters running around, I don't have to register them explicitly.

like image 170
Andy S Avatar answered Oct 19 '22 02:10

Andy S