When using dependency injection, where do all new operators go?

I read about dependency injection, and I understand the basic concept that a method should get what it needs from its caller, and not create such elements themselves. As a result, new operators can be completely excluded from the method (some basic objects would be excluded, of course, I found one example of this for things like StringBuilder that seem crazy to them, go).

My question sounds deceptively simple, but I suspect that the answer is actually quite complicated: where do all the new operators go?

The answer at first seems simple: the new operator just gets into a method that calls a method that needs this object. The problem with this, however, is that the calling method is probably also under testing, and so new gets the calling method from the calling method until you get to the root method (which at the moment seems crazy unchecked) , which creates an obscene amount of objects to use at different points in the call stack. The situation becomes even more complicated when you consider that this root method is the root of a large number of other methods, so for every opportunity you need to create objects. This also poses a performance problem, as you quickly end up with a large number of objects that are never used, but which should be created anyway "just in case".

It’s quite obvious to me that I missed some important knowledge that is so obvious to other developers that no one thinks to describe on the blog. However, I obviously don’t know what I don’t know, so I humbly ask that I be secret: where do all the new operators go?

I should mention that I am developing PHP, so every request starts from the same point, and it looks like this "root" method in index.php should cover everything the application can do to ensure it provides an object for everything. what will he do in the current request. Again, a fundamental misunderstanding arises here, and I really really want to fix it.

+6
source share
4 answers

You did it right: they all fall into your root composition . See this interview with Mark Siman , closer to the bottom, for an explanation of why this is good practice and important.

Also note: dependency injection is for services, not objects or value objects. So, for example, an injection of IUserRepository makes sense, but IUser not so much - and, of course, not StringBuilder s. This can help clarify the situation, in the light of your bracket in relation to more primitive types: separation is actually not so primitive, but what their role is in the system.

+5
source

This is quite obvious - the new operator went to the DI container when all instances occur.

There should also be no performance issues, because services are created on demand - when you request them for the first time.

For PHP development, I suggest you study the Symfony Framework , which implements DI very well and is an example of a flawless and clean architecture.

+3
source

Dependency injection is commonly used in MVC applications. In this case, " new ", as you call it, is usually included in the Controler layer.

When the model is called, the controlling dependent dependent elements pass them to the model and then call the business methods exposed by the model.

But don’t think that DI is “removing new s”. It's about the denouement. The fewer classes that other classes manage (and therefore “know”), the less damage can be caused by a change in these other classes.

Another goal is to facilitate testing. If you have a method that should compose and send mail, it is difficult to verify that the mail is spelled correctly. However, if you remove the dependency on the actual sending of mail from this class to another class and provide only an object that can send mail to this method when you write your test, instead of giving this method to an object that can actually send mail, you will give this method is an object that is only fake sending mail . Do you see the point?

+1
source

DI is often used in tandem with IOC containers (when the scale of the application exceeds a certain threshold). The containers are configured so that they can serve requests for a specific type / interface and return fully constructed objects (with the necessary dependencies).

So instead of executing new ConcreteType() you are requesting a container container.Get<Interface/Type>() .

However, since I read the comments indicating that you are just getting started, I would recommend not to shift your own DI Framework (this is a regular temporary shell). Use and learn code for existing functional DI libraries, such as MEF / Unity / any other.

-2
source

Source: https://habr.com/ru/post/890772/


All Articles