Explain Dependency Injection (DI) like I am five.

tam360 profile image Mirza ・1 min read

I have watched some videos about it but they weren't really helpful in explaining the underline workings and philosophy. All I know is that some frameworks like .NET Core and Spring use it extensively.


markdown guide

Dependency injection is used to allow your application to share instances of specific classes instead of you having to instantiate and initialize them many times around your application.

How this happens will vary with each framework, but the goal is to relegate the management of your classes (typically things like service classes) to the framework instead of your application.

The framework will instantiate the class in question at runtime, and then your code will ask for it using an identifier somewhere instead of creating a new one. This way, everywhere in your code is always using the same instance of the class.

Tl;dr: dependency injection makes the framework instantiate classes for your application and shares them with other parts of your code instead of you needing to call new Foo() yourself. It helps reduce memory usage.


Are there any drawbacks of challenges associated with DI?


Depending on your school of thought, some people may not find the way you interact with your classes to be terribly intuitive, as you need to have a good understanding of the underlying management.

Also, depending on which framework you're using, it may be easier or more difficult to handle how the framework manages constructor arguments for the classes you need.

On the bright side though it makes unit tests simpler because it's very easy to stib/mock your services since you're never interacting with them directly.

I guess the main challenge of using DI is having a solid knowledge of interface/class's internal workings. Since DI does all the things behind the curtain, it becomes annoying when one starts using them without understanding. This I think is true in the case of debugging.

For sure.

I personally think the pros outweigh the cons, but to each their own.


A simple concrete example (using a vaguely Java/C# pseudocode): You want to save some data to a database. You can do something like this:

public class PetManager {
  public PetManager() {
    _dbConnection = new FancyDbConnection("some_connection_string");
  savePet(pet) {

Your PetManager class is responsible for creating and configuring the database, then uses that connection to save a pet record. With dependency injection, the key idea is that the dependency, which is the database connection in this case, can be passed in to the PetManager class from outside (usually as an interface). So it would look like this:

public class PetManager {
  public PetManager(DbConnection dbConnection) {
    _dbConnection = dbConnection;
  savePet(pet) {

This makes it easier to unit test your PetManager class, since you can pass a test-only version of DbConnection. Also, if your application is running in a container of some kind, you can configure the database connection properties in the container, and then let the container wire up the database connection for you at run time. This gives you additional flexibility for setting up these kinds of external dependencies, which can also help with scalability and performance.


Say you’re hungry. With dependency injection, you can just tell mom you’re hungry and she’ll feed you something that matches the food interface.

Without DI, you decide and gather the bread, ketchup, mustard and a hotdog put it all in a bin and bring it to mom and she makes you a hot dog.


So it's kind of like high level abstraction which hides all the complexities and give you what you really need. Interesting.


I think DI uses the idea of IoC behind the scenes


Hey Mirza, literally have been in the same boat as you
Hope this helps!

In a nutshell, what it means is that any given piece of code you write should be provided everything it needs to do its job, instead of creating things for itself. So say I'm writing a forum, and I'm specifically writing the code that adds a new user record to the database and sends them an email to confirm their registration. If I used dependency injection, that piece of code would be given a data model/database connection to work with (instead of creating a new instance of one) and a external class with a pre-defined interface to send email instead of creating an SMTP client object. The reason you do this is it makes the code much easier to test in isolation. So I can replace the class instance for sending emails with one that just checks one is sent to a know address to help with unit tests. It also means that components are easier to replace later on because you can just swap out what objects you give it with objects of a different class with a matching interface.

Let me know if you need any more help :)


I find code examples best for illustrating, so I'll share an example and try to explain. This is valid Ruby code, but will hopefully read more like pseudo code.

Without dependency injection:

class Teacher
  def grade(title, content)
    Paper.new(title, content).grade
  • Anytime you want to grade a new type of paper, you need to update Teacher.
  • If the arguments of Paper change, you need to update Teacher.
  • Basically, the Teacher class has many reasons to change.

With dependency injection:

class Teacher
  def grade(paper)

teacher.grade(Paper.new(title, content))
teacher.grade(BookReport.new(book, title, content))
  • By default, you can grade many types of papers. As long as any new Paper has a grade method, the Teacher can handle it.
  • The Teacher class has fewer reasons to change now.

I realize this isn't a simple explanation yet, so I'll try to simplify. Dependency injection gives you a Teacher that knows how to grade any paper you assigned to students in the past and any paper you might assign in the future. Without it, the Teacher needs to go back to school whenever a new paper is assigned.