How to avoid injecting dependencies into an object so that it can pass them on?

I am interested in applying dependency injection to my current project, which makes use of the MVC pattern.

My controllers will call the models and therefore will need to inject the dependencies into the models. To do this, the controller must have the dependencies (such as a database object) in the first place. The controller doesn't need to make use of some of these dependencies (such as the database object), so I feel that it shouldn't be given this dependency. However, it has to have these dependencies if it is to inject them into the model objects.

How can I avoid having dependencies injected into an object just so that it can pass them on? Doing so feels wrong and can result in many dependencies being injected into an object.

Edit: I am using PHP.

Answers


I agree with your concerns. It's a code smell to take dependencies for the sole purpose of passing them on to other dependencies.

Depending on the exact interaction between those dependencies, you have a couple of options:

If only one instance of the dependency is needed

If your Controller only needs a single instance of a dependency, then just take a dependency on that instead.

(apologies for the c# code)

Don't do this:

public class MyController
{
    public MyController(IDb db)
    {
        var dep = new MyDependency(db);
        // Use dep or save it for later
    }
}

Instead, you can do this:

public class MyController
{
    public MyController(MyDependency dep)
    {
        // Use dep or save it for later
    }
}

You may want to consider MyDependency behind an interface itself. See also Refactoring to Aggregate Services.

If you need to create multiple instances during the Controller's lifetime

Sometimes, however, you need to create multiple instances dynamically. This is often the case when you need a value that's only available at run-time before you can fully populate a dependency.

In this case, an Abstract Factory is an excellent and universal solution.


I'm not speaking from PHP experience but you should look into Inversion of Control (IOC) Containers.

This question on StackOverflow talks about IOC Containers for PHP. For a quick overview of some of the other benefits of IOC Containers you should check this question, probably one of my favourite on the site. Check the last answer ;)

How can I avoid having dependencies injected into an object just so that it can pass them on? Doing so feels wrong and can result in many dependencies being injected into an object.

Most people don't realise that an IOC container makes the need to store temporary dependencies void. This in turn makes your code cleaner and easier to follow. Each class (or module) of your code simply asks for what it needs. IOC Containers can manage object life time, so even if two classes ask for the same dependency independently, they can receive the same instance, which is pretty neat.


Need Your Help

awesome_nested_set How to not select a parent?

ruby-on-rails ruby ruby-on-rails-plugins

I just got awesome_nested_set put in place and all is working well. I converted over from acts_as_tree using Category.rebuild! listed on the github link.