What are the benefits of using Dependency Injection and IoC Containers?

What are the benefits of using Dependency Injection and IoC Containers?

Most important, for me, is making it easy to follow the Single Responsibility Principle.

DI/IoC makes it simple for me to manage dependencies between objects. In turn, that makes it easier for me to break coherent functionality off into it's own contract (interface). As a result, my code has been far more modularized since I learned of DI/IoC.

Another result of this is that I can much more easily see my way through to a design that supports the Open-Closed Principle. This is one of the most confidence inspiring techniques (second only to automated testing). I doubt I could espouse the virtues of Open-Closed Principle enough.

DI/IoC is one of the few things in my programming career that has been a "game changer." There is a huge gap in quality between code I wrote before & after learning DI/IoC. Let me emphasize that some more. HUGE improvement in code quality.

 

 

Why should I use dependency injection?

回答1

The advantage is that without dependency injection, your Profile class

  • needs to know how to create a Settings object (violates Single Responsibility Principle)
  • Always creates its Settings object the same way (creates a tight coupling between the two)

But with dependency injection

  • The logic for creating Settings objects is somewhere else
  • It's easy to use different kinds of Settings objects

This may seem (or even be) irrelevant in this particular case, but imagine if we're not talking about a Settings object, but a DataStore object, which might have different implementations, one that stores data in files and another that stores it in a database. And for automated tests you want a mock implementation as well. Now you really don't want the Profile class to hardcode which one it uses - and even more importantly, you really, really don't want the Profile class to know about filesystem paths, DB connections and passwords, so the creation of DataStore objects has to happen somewhere else.

 

回答2

Why (what's even the issue)?

Why should I use dependency injection?

The best mnemonic I found for this is "new is glue": Every time you use new in your code, that code is tied down to that specific implementation. If you repeatedly use new in constructors, you will create a chain of specific implementations. And because you can't "have" an instance of a class without constructing it, you can't separate that chain.

As an example, imagine you're writing a race car video game. You started with a class Game, which creates a RaceTrack, which creates 8 Cars, which each create a Motor. Now if you want 4 additional Cars with a different acceleration, you will have to change every class mentioned, except maybe Game.

Cleaner code

Is this just for cleaner architecture/code

Yes.

However, it might very well seem less clear in this situation, because it's more an example of how to do it. The actual advantage only shows when several classes are involved and is more difficult to demonstrate, but imagine you would have used DI in the previous example. The code creating all those things might look something like this:

List<Car> cars = new List<Car>();
for(int i=0; i<8; i++){
    float acceleration = 0.3f;
    float maxSpeed = 200.0f;
    Motor motor = new Motor(acceleration, maxSpeed);
    Car car = new Car(motor);
    cars.Add(car);
}
RaceTrack raceTrack = new RaceTrack(cars);
Game game = new Game(raceTrack);

Adding those 4 different cars can now be done by adding these lines:

for(int i=0; i<4; i++){
    float acceleration = 0.5f;
    float maxSpeed = 100.0f;
    Motor motor = new Motor(acceleration, maxSpeed);
    Car car = new Car(motor);
    cars.Add(car);
}
  • No changes in RaceTrack, Game, Car, or Motor were necessary - which means we can be 100% sure that we did not introduce any new bugs there!
  • Instead of having to jump between several files, you will be able to see the complete change on your screen at the same time. This is a result of seeing creation/setup/configuration as an own responsibility - it's not the job of a car to build a motor.

Performance considerations

or does this affect performance as a whole?

No. But to be completely honest with you, it might.

However, even in that case, it's such a ridiculously small amount that you don't need to care. If at some point in the future, you have to write code for a tamagotchi with the equivalent of 5Mhz CPU and 2MB RAM, then maybe you might have to care about this.

In 99.999%* of cases it will have a better performance, because you spent less time fixing bugs and more time improving your resource-heavy algorithms.

*completely made up number

Added info: "hard-coded"

Make no mistake, this is still very much "hard-coded" - the numbers are written directly in the code. Not hard-coded would mean something like storing those values in a text file - e.g. in JSON format - and then reading them from that file.

In order to do that, you have to add code for reading a file and then parsing JSON. If you consider the example again; in the non-DI version, a Car or a Motor now has to read a file. That doesn't sound like it makes too much sense.

In the DI version, you would add it to the code setting up the game.

 

 

 

上一篇:解决”Error resolving template \"/XXX\", template might not exist or might not be accessibl


下一篇:英语,语法.情态动词