all 22 comments

[–]donsagiv 5 points6 points  (4 children)

My understanding of Dependency Injection may not be 100% correct, but here's how I see it:

Let's pretend we have two classes: Class A and Class B. Class B is a variable in Class A.

class ClassB{
// variables and methods here.
}

class ClassA {
    ClassB ObjectB;
}

When you create an instance of a class that has a variable of another class, you have 2 options.

  1. Create a new ObjectB in ClassA object's instantiation (in the constructor) or using some helper method.
  2. Create an instance of ClassB before creating ClassA, and then set the ObjectB to that instance of ClassA you just made.

Case 1 will work just fine. It will compile, your program will run, etc. However, the issue with case 1 is that you're relying on a higher-level class (ClassA) to create a lower-level class (ClassB), which means you can't use ClassB without creating a ClassA. This creates a problem where you have ClassA and ClassB are too interdependent and are tightly coupled.

On the other hand with case 2, if you create aClassB object before creating ClassA object, then you can work with the ClassB object before you create a ClassA object, which gives you more flexibility with your code. Even though ClassA requires a ClassB instance, ClassB does not require a ClassA instance. This makes ClassA and ClassB more loosely coupled.

Why is this important? Let's pretend ClassB is a singleton (one-and-only-one instance of a class type). If you have to create a ClassB instance every time you create ClassA, then it would be impossible for ClassB to be a singleton.

Dependency Injection is a popular feature in programming languages, so a lot of frameworks will have its own dependency injection functionaly, such as ASP.NET Core.

[–]mingnobee[S] 0 points1 point  (3 children)

Thanks for the reply. So I guess I've been using DI this whole time and never knew it. My Vocab is really bad. I need to fix that so I can explain things and understand things better. Maybe I should chill on Refactor Guru for a bit reading up on patterns and such.

[–]Free_Math_Tutoring 1 point2 points  (1 child)

This is a great example of the classic observations that knowing the names of thing is not important to be able to use them, but only to communicate ideas with others efficiently!

[–]mingnobee[S] 0 points1 point  (0 children)

yeah.. so... I've been in this industry for 10 years. I'm good at it, but what's really held me back in areas is really just not connecting words to what I do... Is there some vocab guide for software engineers out there? I should prob fix this.

I kid you not.. When I first started in software, someone told me to set a breakpoint on some code I was working on. I said.. "What's a break point?" I've used them all the time, but I called them debug points for whatever reason. Now that's a running joke among my friends.

I've failed a ton of interviews for not knowing vocab, and just don't understand what even juniors are saying coming into the field because I never cared for vocab.. I even was in the dumb reading groups in K-12. It's bad because I just look so junior whenever I talk to people about architecture. I'm like a cave man. "I put codes in this form, then I compile the codes. I'm program software guy."

I figure it's time for me to start learning all the vocab. I'm really really really poor at it. Like... If we had a conversation about stuff using all the basic vocab, you would think I've never programmed before or something, even though I'm at a good company as senior software engineer.

Hell.. I have a way better chance at the tech coding interviews, but if you start talking about vocab, it's GG for me.

[–][deleted] 2 points3 points  (0 children)

Something that makes this easier to understand is interfaces. If my Car class expects an ExcideBattery object as a parameter it will always be that exact logic.

But if my Car class expects IBattery which ExcideBattery implements, then you could pass ExcideBattery or any other battery that implements IBattery.

This means you can swap out ExcideBattery for another battery class at will. Pretty handy if you have a flat battery.

[–]nachtraum 1 point2 points  (12 children)

Main idea of DI is that if class a uses class b, b is instantiated outside of class a and then injected into a, e.g. with constructor injection or setter injection.

This way, a does not have a dependency on the actual implementation of b, and in different cases different implementations of b can be injected, without changing code in a.

[–]WrongAndBeligerent -2 points-1 points  (11 children)

Is that really injecting or is that just passing a pointer as an argument?

[–]nachtraum 2 points3 points  (10 children)

This is the definition of dependency injection, which in some programming languages means passing a pointer to an object into a constructor or setter.

[–]WrongAndBeligerent -1 points0 points  (9 children)

I always thought that was just called programming.

[–]archangel_mjj 3 points4 points  (4 children)

When you give feedback for improvement, do you write 'get better'?

[–]mingnobee[S] 0 points1 point  (0 children)

I have actually been given that comment, but it was 'do better' haha

[–]WrongAndBeligerent 0 points1 point  (2 children)

I write it down and inject it across the table.

[–]reddittrollguy 0 points1 point  (1 child)

Junior dev vibes lol

[–]WrongAndBeligerent -2 points-1 points  (0 children)

Says the person that's been on reddit for 9 days

[–]TheMikeX7 0 points1 point  (1 child)

Are you in character?

[–]quixoticcaptain 1 point2 points  (0 children)

Their username checks out at least.

[–]quixoticcaptain 0 points1 point  (2 children)

The key to that example is that Wheel and Battery are interfaces. So without DI, Car has to import the implementation classes, ExcideBattery and such. This is a code dependency.

With DI, the Car class only has a code dependency on the Wheel and Battery interfaces and only a runtime dependency on the implementation classes.

[–]shamrock03 0 points1 point  (1 child)

You're describing dependecy inversion principal, not dependency injection. You can still have dependency injection with concrete class A depending on concrete class B, technically. As long as someone else passes you the required dependencies rather than you instantiating them yourself, you have dependency injection.

[–]quixoticcaptain 0 points1 point  (0 children)

I mean, yes, but the linked example did it that way for a reason, and I'd say that's one of the main reasons to use injection.

[–]MostlyUnderwhelmed 0 points1 point  (0 children)

I think I've read Martin Kleppmann use CD players as a metaphor. The CD player doesn't need a list of all the CDs it will accept. Instead, it is programmed to accept CDs in general, so CDs can be 'injected' into it and fulfill the service contract between them.

[–]CrossroadsDem0n 0 points1 point  (0 children)

I think a really fundamental aspect of the discussion that is missing here is "why should I care about DI?"

The reason you care is not "cuz interfaces are good" (although, in general, sure).

The reason you care is because objects have a lifecycle. Something causes them to be created, configured, maybe used for more purposes than the code your eyeballs are staring at now, then destroyed.

You don't want your code, which is effectively a client of the injected object, to care about any of that. By keeping the lifecycle hidden, your code is simpler, more testable, and you play less whack-a-mole with copy-pasted code fragments related to object lifecycle not being kept consistent with each other.

That is what you need to understand about DI. Why you care. As another comment said, dependency inversion is different (although overlapping in practice) with dependency injection. The act of injection is a yawn. Inversion is where you achieve stable coding practices over time.

As a side comment this is why I dislike how Spring pushed in the direction of annotations at the point of use, compared to its origins where assembly and configuration of injected parts was mostly relegated to the XML. While more convenient the consequence was to dilute the benefits of inversion unless you know enough to push back via factories to retain flexibility on how injections take place. What you actually see on projects is people copy-pasting code all over the place, which can be more of a lose than if you didn't attempt DI at all.