Dependency Injection

Dependency Injection

How does dependency injection work? Is it magic? Does it hurt? The first two questions might be reasonable, and the third one might be something I would ask. Either way, I’ll cover these issues and more.

Hopefully, you will agree that this is one of the easier design patterns to understand and implement. When I speak of design patterns, I’m not referring to the sewing patterns your mom used to make your clothes as a kid. These design patterns should help you overcome everyday programming tasks. They have been around for awhile and utilized by some brilliant programmers.

Why Use Dependency Injection

You may instantiate concrete classes inside of your other classes all loosey goosey like a wild developer. If you do, then I hope you keep reading, because I have some tips for you.

When you use concrete classes instead of interfaces, you are only making your life harder. Or you’re making someone else’s life harder, either way, stop it. If your code looks like the example below, then you know who you are.


<?php
class Notification {
	// . . .
	public function send($message) {
		$emailer = new ThirdPartyEmailer;
		$emailer->sendMessage('[email protected]', $message);
	}
	// . . .
}

As you can see from the example above, you lock yourself into using that one class. Doing this will prevent the ease of future growth of the application.

How To Use Dependency Injection

While it may be too late for some of you or some of your applications, it isn’t too late to learn a better way to do things. If you code your classes to an interface, you are already on the right track, and I applaud you. If you aren’t sure about interfaces, then I suggest you read my post about Interfaces in PHP.

Instead of instantiating a new concrete class in your method, have that methods class construct accept a parameter type of the interface your concrete class implements. Since that is a mouthful and sounds confusing, I think if you look at the example below, you’ll see what I mean.


<?php
interface EmailerContract {
	public function sendMessage($toEmail, $message);
}
class ThirdPartyEmailer implements EmailerContract {
	// . . .
	public function sendMessage($toEmail, $message) {
		// send email code
	}
	// . . .
}
class NewEmailer implements EmailerContract {
	// . . .
	public function sendMessage($toEmail, $message) {
		// send email code
	}
	// . . .
}
class Notification {
	private $emailer;
	public function __construct(EmailerContract $emailer) {
		$this->emailer = $emailer;	
	}
	// . . .
	public function send($message) {
		$this->emailer->sendMessage('[email protected]', $message);
	}
	// . . .
}
$notifcation = new Notification(new ThirdPartyEmailer);
$notifcation->send('Welcome!');
// if we switched third party emailers down the road, we can easily switch it out
$notification = new Notification(new NewEmailer);
$notifcation->send('Welcome! We switched mailers.');

Since your concrete class implements that interface, it is a valid argument for that construct, and you can use it. And since it does implement that interface, you know what methods will be available.

Conclusion

You may already be using this design pattern, and you didn’t even know it. If you aren’t using it, I encourage you to do so, it isn’t a huge change, and I hope the concept is one you can grasp. Of course, if you don’t understand, send me an email, and I’ll be happy to help.