David Hoffman
David Hoffman

Reputation: 157

MVC DI/IoC too many dependencies?

Given this example of an MVC controller; psuedo code...

PostController
{
    private IGetPost _getPost;
    private ICreatePost _createPost;
    private IDeletePost _deletePost;
    private IUpdatePost _updatePost;

    public ActionResult Get()
    {
        return _getPost();
    }

    public ActionResult Create(post)
    {
        return _createPost(post);
    }

    public ActionResult Update(posts)
    {
        return _updatePost(post);
    }

    public ActionResult Delete(post)
    {
        return  _deletePost(post);
    }
}

The question I have is that if any one of the actions on the controller is called, all the dependencies of the controller have instances created for them, which seems like a performance buzzkill. Is there a better way to do this? The only thought I had was to create 4 different controllers each with only a single action, but that seems like overkill. I also thought of calling the DependencyResolver directly in each action, but I am unsure of what the implications for unit testability will be if I do that.

Upvotes: 3

Views: 369

Answers (2)

casperOne
casperOne

Reputation: 74530

Why is it a performance buzzkill? Have you measured this to be the case? While there's overhead in determining what implementations map to what interfaces, most dependency injection (DI) containers worth their salt will do this mapping once (and usually create compiled code on the fly so that the lookup is as quick as possible) to create the mappings.

It's then just a matter of creating the objects, which would be no different than if you were to use the new keyword.

For general cases, this isn't going to be a performance hit. Considering this is a web application, if you were getting Stack Overflow levels of traffic, then it very well could be an impediment to scaling; each of these operations is cheap, but when multiplied by a factor of millions, in aggregate, it's very expensive, and usually, these are the types of things that could lead to resource contentions, etc.

Assuming that this isn't the case (Stack Overflow levels of traffic), where you very well could be facing a performance issue is in the implementations of the constructors.

If the implementation of those four interfaces (or any number of them) is costly, that's not a function of DI, it's a function of your code and that's something you will get more benefit from optimizing.

The only place where tweaking the dependency injection might be beneficial would be if the construction one or more of those implementations had high overheads, and you had your DI container create one instance for all interface implementations instead of one instance per interface implementation. However, you should only look into lifetime management through the DI layer when you've determined that option is available to you (meaning, having one instance of that class to service all requests is viable; is it thread-safe? Does it hold onto any resources for a very long time? etc.)

If you're truly concerned about this and the above doesn't apply or isn't an option, then yes, you could create a number of smaller controllers, and that might make sense for other reasons; if the actions you are performing are not logically related to each other, they probably should be in separate controllers.

However, looking at the actions you have, it would seem that the logical divide you have is correct.

Long story short, don't try to optimize for performance in places you haven't measured it to be a factor.

That said, whatever you do, do not resolve dependencies inside of your class. If you do, you lose all the benefits of DI, and are tightly binding your class to a DI container (and possibly killing testability while at it).

Upvotes: 1

Alexander R
Alexander R

Reputation: 2476

I'm not sure the performance will really be a problem unless you have a really ridiculous number of dependencies. Either way, it's a good exercise to look at your architecture.

The way we do this is to abstract service level calls out to an external class, called a handler. This is from inspiration from Project Silk. This way, not only are you slimming down your controllers and making them much more manageable, but it avoids this kind of dependency build up.

In this case, you'd have the one controller which, for each action, simply resolves a handler and its dependencies, and executes it. Handlers are defined as small classes with very few (one is common) methods.

class MyController : BaseController
{
    public ActionResult Get(int id)
    {
        return Using<GetItemHandler>().Execute(id);
    }
}

class GetItemHandler
{
    private IDependency _myDep;

    public GetItemHandler(IDependency dep)
    {
        _myDep = dep;
    }

    public Execute(int id)
    {
        return _myDep.Get(id);
    }
}

Note that the way this works is that the Using<T>() method (defined in the BaseController) uses the IoC container to resolve the handler, thus grabbing all it's dependencies. Then we can just use it as normal. I think this pattern really helps to separate out responsibilities and keep your classes and controllers nice and lean.

Upvotes: 0

Related Questions