Dependency Injection, Services and Containers (DIC) – part 2

 More & more problems

In the previous part we’ve found a solution for one of the problems, and that is the removing of the dependencies and code it with an interface. By itself, this is a good milestone but we’ve never managed the object creation. The complexity of creating the dependencies through the other objects – so in order to instantiate Payment we need to create every class that must be injected and implement the PaymentProcessor, the Invoice and DB.

Dependency Injection Series

At a glance it looks easy as pie. Everything looks strict and clear. But the reality is different. Let us consider the following scenario. Throughout the application we’ll need a connection to the database, and if we thought about it we should have use an interface so we could pass the DB instance and we should give it to various objects that needs it. Example:

interface iDB
{
    public function select();
    public function insert();
}

class MySQLDB implements iDB
{}

class PostgresqlDB implements iDB
{}

class User
{
    public function __construct(iDB $db)
    {}
}

class Account
{
    public function __construct(iDB $db)
    {}
}

$db      = new MySQLDB();
$user    = new User($db);
$account = new Account($db);

This example here is not a part of a real life working program. I just try to express the idea of that implementation.

We create an instance of a given class and we pass that instance to all of the objects, the idea behind it is like what I’ve pointed out in the previous post: “If we decide to change the database driver like PostgresSQL we’ll just need to change the instance. But the practice shows that things are not that simple. We have many objects that has their own dependencies, and if we change the implementation here, we have to manually change it in other places. I guess you figured it out already, we have to use something like a Registry or create a global variable, which will hold the DB instance. In short, we create new iDB only once and every class that depends on it use that “variable”. The theory is logical, but the practice shows something else.

Using global variables or Registry raises another problems, but if you choose this approach what will happen if different classes need a different instance of that database object? And with global we hold only one instance of that DB every object that uses this implementation will have that same instance, and that is often undesirable.

And, this occurs often, we create an instance of a class and we force the dependencies, and then the forced dependencies has their own dependencies, and so on …

We are clearly in a situation where it’s so hard to create a new instance of a desired object. Not because it’s unclear, on the contrary, it’s complicated, and managing this many instances can be a IF/ELSE series with comments like:

While writing this code only me and god knew hot it works. Now only god knows

DI in action

So in general like a definition of DI:

DI is a mechanism which in its true state uses interfaces to reduce complexity with creating new instances and the whole injection process

Every OOP language uses DI and a form of a DI Container, that has numerous amount of libraries, but all of them are reduced to these simple means:

  • use interfaces when you create abstractions and write your code;
  • declare the dependency of the object with typecasting it via the 3 ways with DI usually with the class’ constructor.
  • define which particular implementation must be used at the given time (via a conf file) and decide its behaviour. Singleton, factory or a new instance.

Downsides of the DI

Of course every design pattern, or technique has its downsides, but in general the disadvantages of the DI technique are the lesser evil, and some of them can be removed with using another pattern, or a best practice.

First of the disadvantages is that we use the same DI library, and usually the DI library comes with its own DI Container (more on that subject just continue reading), and a change of the DI container is not an easy task. Ironically the DI pattern which main goal is to handle the dependencies creates dependencies on its own. And in general this is not something bad, if your framework uses the DI as a natural technique (structural). If we need to change the framework, so we have bigger issues than the DI container.

The other downside is that we cannot cope with that ton of interfaces that are needed for a bigger application. And that is where a Software architecture comes to explain and help.

Common criticism is that DI hides that complexity and creates a new layer between the parts of the application, so what? It’s better to have a place where you can control these dependencies than let them fly around.

So the one of the main downsides is that a DI and a DI Container wants a devotion into knowledge to know the bread and butter, but if you tend to use a DI and a DI Container for website with 5 pages + user login system, reconsider using something else …

In PHP 7.0 one of the benefits is the using and performance of the Reflection library – so I hope that PHP 7.2 will be even better and faster. The trend with DI was bad for PHP pre 7.0 versions, because tests show the performance is slow. So at this state of the PHP language and the test that we’ve made, the Reflection library is little slow. More on the library here. And based on the given version of your application your implementation with the DI Library can be a lot serious. And you must know that the larger the application, the larger the resources it needs to hold the load and performance.

But not to criticize me check this comparison that SitePoint offer you about the DI Containers and libraries.

Next post

Advertisements

2 thoughts on “Dependency Injection, Services and Containers (DIC) – part 2

Give your opinion

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s