6

I'm learning TDD. I know about dependency injection whereby you place the class's dependencies in the constructor's parameters and have them passed in, passing in default implementations from the default constructor eg;

public AccountController() : this( RepositoryFactory.Users())
{
}

public AccountController( IUserRepository oUserRepository)
{
 m_oUserRepository = oUserRepository;
}

RepositoryFactory is a simple static class that returns the chosen implementations for the current build

But the default ASP.NET MVC web app project doesn't do this, instead the DI takes the form of public properties that are assigned in the object initializer in the test class eg; from AccountController.cs :

protected override void Initialize(RequestContext requestContext)
{
 if (FormsService == null)
  { FormsService = new FormsAuthenticationService(); }
 if (MembershipService == null)
  { MembershipService = new AccountMembershipService(); }

 base.Initialize(requestContext);
}

And in the test class AccountControllerTest.cs :

private static AccountController GetAccountController()
{
 AccountController controller = new AccountController()
 {
  FormsService = new MockFormsAuthenticationService(),
  MembershipService = new MockMembershipService(),
  Url = new UrlHelper(requestContext),
 };
 //snip
}

So now my AccountController class has two approaches to dependency injection. Which one should I use? Constructor injection or public properties?

Am thinking constructor injection...

Is the ASP.NET MVC use of public properties like that because you need to provide a specific way of injecting into the constructor, and the basic "create new" web app needs to be generic as a starting point?

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
Typo Johnson
  • 5,974
  • 6
  • 29
  • 40

2 Answers2

11

The examples in the ASP.NET MVC are excellent demonstrations of how not to use DI.

First of all, using a default constructor as well as an overloaded constructor introduces ambiguity: does the class control its own dependencies, or does it get them from the outside? Apparently, it can't really decide.

Secondly, having a default implementation introduces tight coupling because you can't create a new instance of the default implementation without having a reference to it. However, the whole point of DI is to enable loose coupling.

Unfortunately we see this idiom a lot. In my book I call it the Bastard Injection anti-pattern; I lifted the name from one of Oren Eini/Ayende Rahien's many opinionated blog posts where he walks through a very similar example.

As a general advice I recommend using Constructor Injection in the vast majority of cases. It's easy to implement and has very strong semantics: it forces the consumer to supply an instance of the dependency, effectively stating that the dependency is mandatory.

Property Injection, on the other hand, implies that the dependency is optional, because the compiler doesn't force you to assign a value. In most cases, dependencies are not really optional, so use of this pattern should be rare.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • Thanks Mark, makes sense now. Is it ambiguity or convenient? For controllers I only see two uses (in my ignorance probably); the compiled app and the test project. The compiled app just uses the default implementations from the default constructor. That'll be faster than using an IOC container won't it? – Typo Johnson Jan 23 '11 at 10:22
  • Ah ok I think I get it. I'm reading about nested IOC where a dependency has dependencies. With IOC this is resolved with a single line like IoC.Resolve(); – Typo Johnson Jan 23 '11 at 10:29
  • Mark, can you help me understand better why not to use "Bastard Injection"? As I see it, the class still allows loose-coupling in that you don't have to use the default constrcutor. Admittedly, the code has a static dependency on RepositoryFactory, but you don't have to use it. Also, the "ambiguity" is a feature: Use the default dependencies or inject your own. What's wrong with that? – Patrick Szalapski May 09 '11 at 15:18
  • 1
    The problem with Bastard Injection is that it creates a tight coupling to the default dependency. It also allows callers to compose the object graph too early if they invoke the default constructor. It's explained in more details in chapter 5 of my book: http://affiliate.manning.com/idevaffiliate.php?id=1150_236 – Mark Seemann May 09 '11 at 16:16
  • Hmm, those seem to be rather minor concerns. I will read about this further. – Patrick Szalapski May 09 '11 at 16:36
  • After further consideration, I still don't see the big benefit to avoiding bastard constructors. Would love to hear more. See: http://stackoverflow.com/questions/6733667/is-there-an-alternative-to-bastard-injection – Patrick Szalapski Jul 18 '11 at 13:31
1

Take a look at structuremap. You are correct...constructor injection is the preferred method of DI/IoC. Check out this article by Martin Fowler. Hope this helps you.

jsteve81
  • 735
  • 2
  • 6
  • 16