dependencies shackles

Inject interfaces instead of creating objects

Creating dependent objects inside a class is not a good idea anymore. Why? There’s no better way to explain it, as by example. Let’s consider class Controller.

class Controller
{
	private $model;
}

class Model
{
	public function setConfig()
	{
		echo 'config';
	}
}

$controller = new Controller();

The natural way of creating the model for out controller is to create it in constructor

class Controller
{
	private $model;

	public function __construct()
	{
		$this->model = new Model();
		$this->model->setConfig();
	}
}

$controller = new Controller();

But what to do if we need to override the Model with MyModel?

class MyModel extends Model
{
	public function setConfig()
	{
		echo 'my config';
	}
}

Of course we also have to override the Controller class.

class Controller
{
	private $model;

	public function __construct()
	{
		$this->model = new MyModel();
		$this->model->setConfig();
	}
}

$controller = new Controller();

As you expect it’s not the best solution because we had to override two classes. To solve this, we could rebuild the Controller class to be independent of the model class. We do this by injecting the $model object instead of creating it inside the constructor.

class Controller
{
	private $model;

	public function __construct(Model $model)
	{
		$this->model = $model;
		$this->model->setConfig();
	}
}

$model = new Model();
$controller = new Controller($model);

$myModel = new MyModel();
$controller2 = new Controller($myModel);

Ok, we have our injection done! But what if we want to use our Controller class in other project with completely different model class, say NewModel. In our previous case we would be forced to get the Controller class together with the Model class, and our NewModel class has to extend the Model class. To avoid it and free our Controller class, let’s use interface.

interface ModelInterface
{
	public function setConfig();
}

class Controller
{
	private $model;

	public function __construct(ModelInterface $model)
	{
		$this->model = $model;
		$this->model->setConfig();
	}
}

class NewModel implements ModelInterface
{
	public function setConfig()
	{
		echo 'new config';
	}
}

There’s only one change in our Controller class. A type of $model object in constructor. As a result we get a ready to use Controller class in many projects. The interface doesn’t enforce us to use the Model class, but only tell us about some required features. Of course we have to get ModelInterface interface with our Controller class, but it’s a small price for getting rid of the bound to one Model class.

Conclusion

Whenever creating a new class, create it as independent of other elements, as possible, but not too much. If your class needs dependencies, inject them. Those required ones inject into the constructor, like in example above and those optional inject by setter methods like the $session object for instance.

class Controller
{
	/**
	*
	* @var ModelInterface
	*/
	private $model;

	/**
	*
	* @var SessionInterface
	*/
	private $session;

	public function __construct(ModelInterface $model)
	{
		$this->model = $model;
		$this->model->setConfig();
	}

	public function setSession(SessionInterface $session)
	{
		$this->session = $session;
	}
}

0 thoughts on “Inject interfaces instead of creating objects

  • hi, i’m new to oop. i like your article but how do i get the SessionInterface? did you forget about it?

    • Hi patric. I didn’t forget. It’s just irrelevant to this example. The SessionInterface depends of the features you need from the Session class in your Controller.

Comments are closed.