Why should I use dependency injection?











up vote
61
down vote

favorite
19












I am having a hard time looking for resources on why should I use Dependency Injection. Most of the resources that I see explains that it just passes an instance of an object to another instance of an object but why? Is this just for cleaner architecture/code or does this affect performance as a whole?



Why should I do this:



class Profile {
public function deactivateProfile(Setting $setting)
{
$setting->isActive = false;
}
}


instead of this:



class Profile {
public function deactivateProfile()
{
$setting = new Setting();
$setting->isActive = false;
}
}








share


















  • 7




    You are introducing a hard-coded dependency to deactivateProfile() (which is bad). You have more decoupled code in the first one, which makes it easier to change and to test.
    – Aulis Ronkainen
    2 days ago








  • 3




    Why would you do the first one? You're passing in a Setting and then ignoring its value.
    – Phil N DeBlanc
    2 days ago






  • 1




    @PhilNDeBlanc it did not came from me. It came from here: medium.com/tech-tajawal/…
    – Daniel
    2 days ago






  • 29




    I don't agree with the downvotes. While the subject matter may be considered trivial to experts, the question has merit: if dependency inversion should be used, then there should be a justification for using it.
    – Flater
    yesterday








  • 9




    @PhilNDeBlanc: This code is clearly oversimplified and not really indicative of real world logic. However, deactivateProfile suggests to me that setting the isActive to false without caring about its previous state is the correct approach here. Calling the method inherently means that you mean to set it as inactive, not get its current (in)active status.
    – Flater
    yesterday















up vote
61
down vote

favorite
19












I am having a hard time looking for resources on why should I use Dependency Injection. Most of the resources that I see explains that it just passes an instance of an object to another instance of an object but why? Is this just for cleaner architecture/code or does this affect performance as a whole?



Why should I do this:



class Profile {
public function deactivateProfile(Setting $setting)
{
$setting->isActive = false;
}
}


instead of this:



class Profile {
public function deactivateProfile()
{
$setting = new Setting();
$setting->isActive = false;
}
}








share


















  • 7




    You are introducing a hard-coded dependency to deactivateProfile() (which is bad). You have more decoupled code in the first one, which makes it easier to change and to test.
    – Aulis Ronkainen
    2 days ago








  • 3




    Why would you do the first one? You're passing in a Setting and then ignoring its value.
    – Phil N DeBlanc
    2 days ago






  • 1




    @PhilNDeBlanc it did not came from me. It came from here: medium.com/tech-tajawal/…
    – Daniel
    2 days ago






  • 29




    I don't agree with the downvotes. While the subject matter may be considered trivial to experts, the question has merit: if dependency inversion should be used, then there should be a justification for using it.
    – Flater
    yesterday








  • 9




    @PhilNDeBlanc: This code is clearly oversimplified and not really indicative of real world logic. However, deactivateProfile suggests to me that setting the isActive to false without caring about its previous state is the correct approach here. Calling the method inherently means that you mean to set it as inactive, not get its current (in)active status.
    – Flater
    yesterday













up vote
61
down vote

favorite
19









up vote
61
down vote

favorite
19






19





I am having a hard time looking for resources on why should I use Dependency Injection. Most of the resources that I see explains that it just passes an instance of an object to another instance of an object but why? Is this just for cleaner architecture/code or does this affect performance as a whole?



Why should I do this:



class Profile {
public function deactivateProfile(Setting $setting)
{
$setting->isActive = false;
}
}


instead of this:



class Profile {
public function deactivateProfile()
{
$setting = new Setting();
$setting->isActive = false;
}
}








share













I am having a hard time looking for resources on why should I use Dependency Injection. Most of the resources that I see explains that it just passes an instance of an object to another instance of an object but why? Is this just for cleaner architecture/code or does this affect performance as a whole?



Why should I do this:



class Profile {
public function deactivateProfile(Setting $setting)
{
$setting->isActive = false;
}
}


instead of this:



class Profile {
public function deactivateProfile()
{
$setting = new Setting();
$setting->isActive = false;
}
}






architecture object-oriented-design clean-code





share












share










share



share










asked 2 days ago









Daniel

44524




44524








  • 7




    You are introducing a hard-coded dependency to deactivateProfile() (which is bad). You have more decoupled code in the first one, which makes it easier to change and to test.
    – Aulis Ronkainen
    2 days ago








  • 3




    Why would you do the first one? You're passing in a Setting and then ignoring its value.
    – Phil N DeBlanc
    2 days ago






  • 1




    @PhilNDeBlanc it did not came from me. It came from here: medium.com/tech-tajawal/…
    – Daniel
    2 days ago






  • 29




    I don't agree with the downvotes. While the subject matter may be considered trivial to experts, the question has merit: if dependency inversion should be used, then there should be a justification for using it.
    – Flater
    yesterday








  • 9




    @PhilNDeBlanc: This code is clearly oversimplified and not really indicative of real world logic. However, deactivateProfile suggests to me that setting the isActive to false without caring about its previous state is the correct approach here. Calling the method inherently means that you mean to set it as inactive, not get its current (in)active status.
    – Flater
    yesterday














  • 7




    You are introducing a hard-coded dependency to deactivateProfile() (which is bad). You have more decoupled code in the first one, which makes it easier to change and to test.
    – Aulis Ronkainen
    2 days ago








  • 3




    Why would you do the first one? You're passing in a Setting and then ignoring its value.
    – Phil N DeBlanc
    2 days ago






  • 1




    @PhilNDeBlanc it did not came from me. It came from here: medium.com/tech-tajawal/…
    – Daniel
    2 days ago






  • 29




    I don't agree with the downvotes. While the subject matter may be considered trivial to experts, the question has merit: if dependency inversion should be used, then there should be a justification for using it.
    – Flater
    yesterday








  • 9




    @PhilNDeBlanc: This code is clearly oversimplified and not really indicative of real world logic. However, deactivateProfile suggests to me that setting the isActive to false without caring about its previous state is the correct approach here. Calling the method inherently means that you mean to set it as inactive, not get its current (in)active status.
    – Flater
    yesterday








7




7




You are introducing a hard-coded dependency to deactivateProfile() (which is bad). You have more decoupled code in the first one, which makes it easier to change and to test.
– Aulis Ronkainen
2 days ago






You are introducing a hard-coded dependency to deactivateProfile() (which is bad). You have more decoupled code in the first one, which makes it easier to change and to test.
– Aulis Ronkainen
2 days ago






3




3




Why would you do the first one? You're passing in a Setting and then ignoring its value.
– Phil N DeBlanc
2 days ago




Why would you do the first one? You're passing in a Setting and then ignoring its value.
– Phil N DeBlanc
2 days ago




1




1




@PhilNDeBlanc it did not came from me. It came from here: medium.com/tech-tajawal/…
– Daniel
2 days ago




@PhilNDeBlanc it did not came from me. It came from here: medium.com/tech-tajawal/…
– Daniel
2 days ago




29




29




I don't agree with the downvotes. While the subject matter may be considered trivial to experts, the question has merit: if dependency inversion should be used, then there should be a justification for using it.
– Flater
yesterday






I don't agree with the downvotes. While the subject matter may be considered trivial to experts, the question has merit: if dependency inversion should be used, then there should be a justification for using it.
– Flater
yesterday






9




9




@PhilNDeBlanc: This code is clearly oversimplified and not really indicative of real world logic. However, deactivateProfile suggests to me that setting the isActive to false without caring about its previous state is the correct approach here. Calling the method inherently means that you mean to set it as inactive, not get its current (in)active status.
– Flater
yesterday




@PhilNDeBlanc: This code is clearly oversimplified and not really indicative of real world logic. However, deactivateProfile suggests to me that setting the isActive to false without caring about its previous state is the correct approach here. Calling the method inherently means that you mean to set it as inactive, not get its current (in)active status.
– Flater
yesterday










9 Answers
9






active

oldest

votes

















up vote
77
down vote













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.






share|improve this answer

















  • 14




    This may seem (or even be) irrelevant in this particular case I think it is very much relevant, in fact. How would you get the settings? A lot of systems I've seen will have a hard-coded default set of settings and a public facing configuration, so you'd need to load both and overwrite some values with the public settings. You may even need multiple sources of defaults. Perhaps you might even be getting some from disk, others from DB. So, the entire logic for even getting settings can, and often is, non-trivial - definitely not something consuming code should or would care about.
    – vlaz
    yesterday










  • We could also mention that object initialisation for a non-trivial component, such as a web service, would make $setting = new Setting(); horrendously inefficient. Injection and object instantiation happens once.
    – vikingsteve
    yesterday










  • @vikingsteve That's not important - you'd solve that problem more easily by using e.g. a singleton. And indeed, dependency injection doesn't mean you don't create the object multiple times. It just means that your class doesn't have control over the lifetime of its dependencies - you delegate it to something in your chain of callers.
    – Luaan
    17 hours ago






  • 5




    I think using mocks for testing should have more emphasis. Chances are if you look just at the code, it's always going to be a Settings object and will never change, so passing it in seems like a wasted effort. However, the very first time you try to test a Profile object by itself without also needing a Settings object (using a mock object instead as a solution) the need is very apparent.
    – JPhi1618
    16 hours ago






  • 1




    @JPhi1618 I think the problem with emphasising "DI is for Unit Testing" is that it just leads to the question "why do I need Unit Tests". The answer may seem obvious to you, and the benefits are definitely there, but to someone just starting out, saying "you need to do this complicated-sounding thing in order to do this other complicated-sounding thing" tends to be a bit of a turn-off. So it's good to mention different advantages which might be more applicable to what they're doing right now.
    – IMSoP
    14 hours ago




















up vote
42
down vote













Dependency Injection makes your code easier to test.



I learned this first-hand when I was tasked with fixing a hard-to-catch bug in Magento's PayPal integration.



An issue would arise when PayPal was telling Magento about a failed payment: Magento wouldn't register the failure properly.



Testing a potential fix "manually" would be very tedious: you'd need to somehow trigger a "Failed" PayPal notification. You'd have to submit an e-check, cancel it, and wait for it to error out. That means 3+ days to test a one-character code change!



Luckily, it appears that the Magento core devs who developed this function had testing in mind, and used a dependency injection pattern to make it trivial. This allows us to verify our work with a simple test case like this one:



<?php
// This is the dependency we will inject to facilitate our testing
class MockHttpClient extends Varien_Http_Adapter_Curl {
function read() {
// Make Magento think that PayPal said "VERIFIED", no matter what they actually said...
return "HTTP/1.1 200 OKnnVERIFIED";
}
}

// Here, we trick Magento into thinking PayPal actually sent something back.
// Magento will try to verify it against PayPal's API though, and since it's fake data, it'll always fail.
$ipnPayload = array (
'invoice' => '100058137', // Order ID to test against
'txn_id' => '04S87540L2309371A', // Test PayPal transaction ID
'payment_status' => 'Failed' // New payment status that Magento should ingest
);

// This is what Magento's controller calls during a normal IPN request.
// Instead of letting Magento talk to PayPal, we "inject" our fake HTTP client, which always returns VERIFIED.
Mage::getModel('paypal/ipn')->processIpnRequest($ipnPayload, new MockHttpClient());


I'm sure the DI pattern has plenty of other advantages, but increased testability is the single biggest benefit in my mind.



If you're curious about the solution to this problem, check out the GitHub repo here: https://github.com/bubbleupdev/BUCorefix_Paypalstatus






share|improve this answer

















  • 2




    Dependency injection makes code easier to test than code with hardcoded dependencies. Eliminating dependencies from business logic altogether is even better.
    – Ant P
    yesterday






  • 1




    And one major way to do what @AntP suggests is via parameterization. The logic to transform results coming back from the database into the object used to fill out a page template (commonly known as a "model") shouldn't even know a fetch is happening; it just needs to get those objects as input.
    – jpmc26
    yesterday








  • 3




    @jpmc26 indeed - I tend to harp on about functional core, imperative shell, which is really just a fancy name for passing data into your domain instead of injecting dependencies into it. The domain is pure, can be unit tested with no mocks and then is just wrapped in a shell that adapts things like persistence, messaging etc.
    – Ant P
    yesterday












  • I think the sole focus on testability is harmful to the adoption of DI. It makes it unappealing to people who feel like they either don't need much testing, or think they already have testing under control. I would argue it is virtually impossible to write clean, reusable code without DI. Testing is very far down on the list of benefits and it's disappointing to see this answer ranked 1st or 2nd in every question on DI's benefits.
    – Carl Leth
    1 hour ago


















up vote
15
down vote













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 a second type of Car 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);


Now you don't have to make any changes in RaceTrack, Game, Car, or Motor. That means two things:




  • the change is easier, because it's all in one place.

  • there's no way to introduce new bugs in classes you don't change!


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.






share|improve this answer



















  • 2




    Ad hard-coded, there is not really that much difference between code and config file. A file bundled with the application is a source even if you read dynamically. Pulling values from code to data files in json or whatever ‘config’ format helps nothing unless the values should be overridden by the user or depend on the environment.
    – Jan Hudec
    yesterday








  • 1




    I actually made a Tamagotchi once on an Arduino (16MHz, 2KB)
    – Jungkook
    23 hours ago










  • @JanHudec True. I actually had a longer explanation there, but decided to remove it to keep it shorter and focus on how it relates to DI. There's more stuff which isn't 100% correct; overall the answer is more optimized to push "the point" of DI without it getting too long. Or put differently, this is what I would have wanted to hear when I started out with DI.
    – R. Schmitz
    20 hours ago


















up vote
6
down vote













The example you give is not dependency injection in the classical sense. Dependency injection usually refers to passing objects in a constructor or by using "setter injection" just after the object is created, in order to set a value on a field in a newly created object.



Your example passes an object as an argument to an instance method. This instance method then modifies a field on that object. Dependency injection? No. Breaking encapsulation and data hiding? Absolutely!



Now, if the code was like this:



class Profile {
private $settings;

public function __construct(Settings $settings) {
$this->settings = $settings;
}

public function deactive() {
$this->settings->isActive = false;
}
}


Then I would say you are using dependency injection. The notable difference is a Settings object being passed in to the constructor or a Profile object.



This is useful if the Settings object is expensive or complex to construct, or Settings is an interface or abstract class where multiple concrete implementations exist in order to change run time behavior.



Since you are directly accessing a field on the Settings object rather than calling a method, you can't take advantage of Polymorphism, which is one of the benefits of dependency injection.



It looks like the Settings for a Profile are specific to that profile. In this case I would do one of the following:




  1. Instantiate the Settings object inside the Profile constructor


  2. Pass the Settings object in the constructor and copy over individual fields that apply to the Profile



Honestly, by passing the Settings object in to deactivateProfile and then modifying an internal field of the Settings object is a code smell. The Settings object should be the only one modifying its internal fields.






share|improve this answer

















  • 5




    The example you give is not dependency injection in the classical sense. -- It doesn't matter. OO people have objects on the brain, but you're still handing a dependency to something.
    – Robert Harvey
    yesterday










  • When you talk about “in the classical sense”, you are, as @RobertHarvey says, speaking purely in OO terms. In functional programming for example, injecting one function into another (higher order functions) is that paradigm’s classical example of dependency injection.
    – David Arno
    yesterday






  • 3




    @RobertHarvey: I guess I was taking too many liberties with "dependency injection." The place people most often think of the term and use the term is in reference to fields on an object being "injected" at the time of object construction, or immediately after in the case of setter injection.
    – Greg Burghardt
    yesterday










  • @DavidArno: Yes, you are correct. The OP seems to have an object oriented PHP code snippet in the question, so I was answering in that regard only, and not addressing functional programming --- all though with PHP you could ask the same question from the standpoint of functional programming.
    – Greg Burghardt
    yesterday


















up vote
3
down vote













I know I'm coming late to this party but I feel an important point is being missed.




Why should I do this:




class Profile {
public function deactivateProfile(Setting $setting)
{
$setting->isActive = false;
}
}


You shouldn't. But not because Dependency Injection is a bad idea. It's because this is doing it wrong.



Lets look at this things using code. We're going to do this:



$profile = new Profile();
$profile->deactivateProfile($setting);


when we get about the same thing out of this:



$setting->isActive = false; // Deactivate profile


So of course it seems like a waste of time. It is when you do it this way. This is not the best use of Dependency Injection. It's not even the best use of a class.



Now what if instead we had this:



$profile = new Profile($setting);

$application = new Application($profile);

$application.start();


And now the application is free to activate and deactivate the profile without having to know anything in particular about the setting that it's actually changing. Why is that good? In case you need to change setting. The application is walled off from those changes so you're free to go nuts in a safe contained space without having to watch everything break as soon as you touch something.



This follows the separate construction from behavior principle. The DI pattern here is a simple one. Build everything you need at as low a level as you can, wire them together, then start all the behavior ticking with one call.



The result is you have a separate place to decide what connects to what and a different place to manage what says what to whatever.



Try that on something you have to maintain over time and see if it doesn't help.






share|improve this answer























  • I was ready to upvote this until I got to the last three paragraphs, which come across as a bit patronising, or maybe just pessimistic. It's like you're assuming that the reader will ignore everything you've just said, and defensively responding to comments that haven't been made yet.
    – IMSoP
    15 hours ago










  • @IMSoP Better now?
    – candied_orange
    11 hours ago


















up vote
1
down vote













As a customer, when you hire a mechanic to do something to your car, do you expect that mechanic to build a car from scratch only to then work with it? No, you give the mechanic the car you want them to work on.



As the garage owner, when you instruct a mechanic to do something to a car, do you expect the mechanic to create his own screwdriver/wrench/car parts? No, you provide the mechanic with the parts/tools he needs to use



Why do we do this? Well, think about it. You're a garage owner who wants to hire someone to become your mechanic. You will teach them to be a mechanic (= you will write the code).



What's going to be easier:




  • Teach a mechanic how to attach a spoiler to a car using a screwdriver.

  • Teach a mechanic to create a car, create a spoiler, created a screwdriver
    and then attach the newly created spoiler to the newly created car with the newly created screwdriver.


There are massive benefits to not having your mechanic create everything from scratch:




  • Obviously, training (= development) is dramatically shortened if you just supply your mechanic with existing tools and parts.

  • If the same mechanic has to perform the same job multiple times, you can make sure he reuses the screwdriver instead of always throwing the old one out and creating a new one.

  • Additionally, a mechanic who has learned to create everything will need to be much more of an expert, and thus will expect a higher wage. The coding analogy here is that a class with many responsibilities is much harder to maintain than a class with a single strictly defined responsibility.

  • Additionally, when new inventions hit the market and spoilers are now being made from carbon instead of plastic; you will have to retrain (= redevelop) your expert mechanic. But your "simple" mechanic won't have to be retrained as long as the spoiler can still be attached in the same way.

  • Having a mechanic who doesn't rely on a car that they've built themselves means that you have a mechanic who is able to handle any car they may receive. Including cars that didn't even exist yet at the time of training the mechanic. However, your expert mechanic will not be able to build newer cars that have been created after their training.


If you hire and train the expert mechanic, you're going to end up with an employee who costs more, takes more time to perform what ought to be a simple job, and will perpetually need to be retrained whenever one of their many responsibilities need to be updated.



The development analogy is that if you use classes with hardcoded dependencies, then you're going to end up with hard to maintain classes which will need continual redevelopment/changes whenever a new version of the object (Settings in your case) is created, and you'll have to develop internal logic for the class to have the ability to create different types of Settings objects.



Furthermore, whoever consumes your class is now also going to have to ask the class to create the correct Settings object, as opposed to simply being able to pass the class any Settings object it wishes to pass. This means additional development for the consumer to figure out how to ask the class to create the right tool.





Yes, dependency inversion takes a bit more effort to write instead of hardcoding the dependency. Yes, it's annoying to have to type more.



But that is the same argument as choosing to hardcode literal values because "declaring variables takes more effort". Technically correct, but the pro's outweigh the cons by several orders of magnitude.



The benefit of dependency inversion is not experienced when you create the first version of the application. The benefit of dependency inversion is experienced when you need to change or extend that initial version. And don't trick yourself into thinking that you will get it right the first time and won't need to extend/change the code. You will have to change things.






does this affect performance as a whole?




This does not affect runtime performance of the application. But it massively impacts the development time (and therefore performance) of the developer.






share|improve this answer



















  • 2




    If you removed your comment, "As a minor comment, your question focuses on dependency inversion, not dependency injection. Injection is one way to do inversion, but it's not the only way.", this would be an excellent answer. Dependency inversion can be achieved via either injection or locator/globals. The question's examples relate to injection. So the question is about dependency injection (as well as dependency inversion).
    – David Arno
    yesterday






  • 11




    I think the whole car thing is a bit belaboured and confusing
    – Ewan
    yesterday






  • 3




    @Flater, part of the problem is no one really seems to agree on what the difference between dependency injection, dependency inversion and inversion of control are. One thing is for certain though, a "container" most certainly isn't needed to inject a dependency into a method or constructor. Pure (or poor man's) DI specifically describes manual dependency injection. It's the only dependency injection I personally use as I dislike the "magic" associated with containers.
    – David Arno
    yesterday






  • 1




    Your mechanic analogy is poor even as an analogy. If I have a mechanic trained how to fix cars, he can fix most varieties but if I come to him with a EV instead, he's likely to have no clue what to do with it. DI does not fix the polymorphic problem, all it does is help with coupling - ie how to get the car and mechanic together. A better analogy is a mechanic working for a dealer who only fixed 1 brand of car going independent and fixing other brands of car.
    – gbjbaanb
    17 hours ago






  • 1




    @gbjbaanb I think the analogy can be extended naturally to the EV example: the mechanic specifies constraints on the cars he accepts; in an OO language, that would be represented as the interface the dependency must implement. In the simple example, the constraint is "any car", but in reality it would be "any car with an internal combustion engine", or some more specific description; an EV car wouldn't meet that constraint, so wouldn't be accepted. In OO terms, NissanLeaf would be a new class that implemented an EVCar interface, but didn't implement the InternalCombustionCar interface.
    – IMSoP
    15 hours ago




















up vote
0
down vote













You should use techniques to solve the problems they're good at solving when you have those problems. Dependency inversion and injection are no different.



Dependency inversion or injection is a technique that allows your code to decide on what implementation of a method gets called at run time. This maximizes the benefits of late binding. The technique is necessary when the language does not support run time replacement of non-instance functions. For example, Java lacks a mechanism to replace calls to a static method with calls to a different implementation; contrast with Python, where all that's necessary to replace the function call is to bind the name to a different function (reassign the variable holding the function).



Why would we want to vary the implementation of the function? There's a two main reasons:




  • We want to use fakes for testing purposes. This allows us to test a class that depends on a database fetch without actually connecting to the database.

  • We need to support multiple implementations. For example, we might need to set up a system that supports both MySQL and PostgreSQL databases.


You may also want to take note of inversion of control containers. This is a technique that is intended to help you avoid huge, tangled construction trees that look like this pseudocode:



thing5 =  new MyThing5();
thing3 = new MyThing3(thing5, new MyThing10());

myApp = new MyApp(
new MyAppDependency1(thing5, thing3),
new MyAppDependency2(
new Thing1(),
new Thing2(new Thing3(thing5, new Thing4(thing5)))
),
...
new MyAppDependency15(thing5)
);


It lets you register your classes and then does the construction for you:



injector.register(Thing1); // Yes, you'd need some kind of actual class reference.
injector.register(Thing2);
...
injector.register(MyAppDepdency15);
injector.register(MyApp);

myApp = injector.create(MyApp); // The injector fills in all the construction parameters.


Note that it's simplest if the classes registered can be stateless singletons.



Word of caution



Note that dependency inversion should not be your go-to answer for decoupling logic. Look for opportunities to use parameterization instead. Consider this pseudocode method for example:



myAverageAboveMin()
{
dbConn = new DbConnection("my connection string");
dbQuery = dbConn.makeQuery();
dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
dbQuery.setParam("min", 5);
dbQuery.Execute();
myData = dbQuery.getAll();
count = 0;
total = 0;
foreach (row in myData)
{
count++;
total += row.x;
}

return total / count;
}


We could use dependency inversion for some parts of this method:



class MyQuerier
{
private _dbConn;

MyQueries(dbConn) { this._dbConn = dbConn; }

fetchAboveMin(min)
{
dbQuery = this._dbConn.makeQuery();
dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
dbQuery.setParam("min", min);
dbQuery.Execute();
return dbQuery.getAll();
}
}


class Averager
{
private _querier;

Averager(querier) { this._querier = querier; }

myAverageAboveMin(min)
{
myData = this._querier.fetchAboveMin(min);
count = 0;
total = 0;
foreach (row in myData)
{
count++;
total += row.x;
}

return total / count;
}


But we shouldn't, at least not completely. Notice that we've created a stateful class with Querier. It now holds a reference to some essentially global connection object. This creates problems such as difficulty in understanding the overall state of the program and how different classes coordinate with each other. Notice also that we're forced to fake out the querier or the connection if we want to test the averaging logic. Further A better approach would be to increase parameterization:



class MyQuerier
{
fetchAboveMin(dbConn, min)
{
dbQuery = dbConn.makeQuery();
dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
dbQuery.setParam("min", min);
dbQuery.Execute();
return dbQuery.getAll();
}
}


class Averager
{
averageData(myData)
{
count = 0;
total = 0;
foreach (row in myData)
{
count++;
total += row.x;
}

return total / count;
}

class StuffDoer
{
private _querier;
private _averager;

StuffDoer(querier, averager)
{
this._querier = querier;
this._averager = averager;
}

myAverageAboveMin(dbConn, min)
{
myData = this._querier.fetchAboveMin(dbConn, min);
return this._averager.averageData(myData);
}
}


And the connection would be managed at some even higher level that's responsible for the operation as a whole and knows what to do with this output.



Now we can test the averaging logic completely independently of the querying, and what's more we can use it in a wider variety of situations. We might question whether we even need the MyQuerier and Averager objects, and maybe the answer is that we don't if we don't intend to unit test StuffDoer, and not unit testing StuffDoer would be perfectly reasonable since it's so tightly coupled to the database. It might make more sense to just let integration tests cover it. In that case, we might be fine making fetchAboveMin and averageData into static methods.






share|improve this answer



















  • 1




    "Dependency injection is a technique that is intended to help you avoid huge, tangled construction trees...". Your first example after this claim is an example of pure, or poor man's, dependency injection. The second is an example of using an IoC container to "automate" the injection of those dependencies. Both are examples of dependency injection in action.
    – David Arno
    yesterday










  • @DavidArno Yeah, you're right. I've adjusted the terminology.
    – jpmc26
    yesterday










  • There's a third main reason to vary the implementation, or at least design the code assuming that the implementation can vary: it incentivizes developer to have loose coupling and avoid writing code that will be hard to change should a new implementation be implemented at some time in the future. And while that may not be a priority in some projects (e.g. knowing that the application will never be revisited after its initial release), it will be in others (e.g. where the company business model specifically tries to offer extended support/extension of their applications).
    – Flater
    2 hours ago


















up vote
0
down vote













I was always baffled by dependency injection. It seemed to only exist within Java spheres, but those spheres spoke of it with great reverence. It was one of the great Patterns, you see, which are said to bring order to chaos. But the examples were always convoluted and artificial, establishing a non-problem and then setting out to solve it by making the code more complicated.



It made more sense when a fellow Python dev imparted to me this wisdom: it's just passing arguments to functions. It's barely a pattern at all; more like a reminder that you can ask for something as an argument, even if you could have conceivably provided a reasonable value yourself.



So your question is roughly equivalent to "why should my function take arguments?" and has many of the same answers, namely: to let the caller make decisions.



This comes with a cost, of course, because now you're forcing the caller to make some decision (unless you make the argument optional), and the interface is somewhat more complex. In exchange, you gain flexibility.



So: Is there a good reason you specifically need to use this particular Setting type/value? Is there a good reason calling code might want a different Setting type/value? (Remember, tests are code!)






share|improve this answer








New contributor




Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • Yep. IoC finally clicked to me when I realised that it's simply about "letting the caller make decisions". That IoC means the control of the component is shifted from the component's author to the component's user. And since at that point I've already had enough gripes with software that thought itself smarter than me, I was instantly sold on the DI approach.
    – Joker_vD
    10 hours ago


















up vote
0
down vote













Like all patterns, it is very valid to ask "why" to avoid bloated designs.



For dependency injection, this is easily seen by thinking of the two, arguably, most important facets of OOP design...



Low coupling



Coupling in computer programming:




In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules.




You want to achieve low coupling. Two things being strongly coupled means that if you change the one, you very likely have to change the other. Bugs or restrictions in the one likely will induce bugs/restrictions in the other; and so on.



One class instantiating objects of the others is a very strong coupling, because the one needs to know about the existence of the other; it needs to know how to instantiate it (which arguments the constructor needs), and those arguments need to be available when calling the constructor. Also, depending on whether the language needs explicit deconstruction (C++), this will introduce further complications. If you introduce new classes (i.e., a NextSettings or whatever), you have to go back to the original class and add more calls to their constructors.



High cohesion



Cohesion:




In computer programming, cohesion refers to the degree to which the elements inside a module belong together.




This is the other side of the coin. If you look at one unit of code (one method, one class, one package etc.), you want to have all code inside that unit to have as few responsibilities as possible.



A basic example for this would be the MVC pattern: you clearly separate the domain model from the view (GUI) and a control layer that glues those together.



This avoids code bloat where you get large chunks that do lots of different things; if you wish to change some part of it, you have to keep track of all the other features as well, trying to avoid bugs, etc.; and you quickly program yourself into a hole where it's very hard to get out.



With dependency injection, you delegate the creation or keeping track of, well, dependencies to whatever classes (or configuration files) which implement your DI. Other classes will not care much about what exactly is going on - they will be working with some generic interfaces, and have no idea what the actual implementation is, which means they are not responsible for the other stuff.






share|improve this answer




















    protected by gnat 12 hours ago



    Thank you for your interest in this question.
    Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



    Would you like to answer one of these unanswered questions instead?














    9 Answers
    9






    active

    oldest

    votes








    9 Answers
    9






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    77
    down vote













    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.






    share|improve this answer

















    • 14




      This may seem (or even be) irrelevant in this particular case I think it is very much relevant, in fact. How would you get the settings? A lot of systems I've seen will have a hard-coded default set of settings and a public facing configuration, so you'd need to load both and overwrite some values with the public settings. You may even need multiple sources of defaults. Perhaps you might even be getting some from disk, others from DB. So, the entire logic for even getting settings can, and often is, non-trivial - definitely not something consuming code should or would care about.
      – vlaz
      yesterday










    • We could also mention that object initialisation for a non-trivial component, such as a web service, would make $setting = new Setting(); horrendously inefficient. Injection and object instantiation happens once.
      – vikingsteve
      yesterday










    • @vikingsteve That's not important - you'd solve that problem more easily by using e.g. a singleton. And indeed, dependency injection doesn't mean you don't create the object multiple times. It just means that your class doesn't have control over the lifetime of its dependencies - you delegate it to something in your chain of callers.
      – Luaan
      17 hours ago






    • 5




      I think using mocks for testing should have more emphasis. Chances are if you look just at the code, it's always going to be a Settings object and will never change, so passing it in seems like a wasted effort. However, the very first time you try to test a Profile object by itself without also needing a Settings object (using a mock object instead as a solution) the need is very apparent.
      – JPhi1618
      16 hours ago






    • 1




      @JPhi1618 I think the problem with emphasising "DI is for Unit Testing" is that it just leads to the question "why do I need Unit Tests". The answer may seem obvious to you, and the benefits are definitely there, but to someone just starting out, saying "you need to do this complicated-sounding thing in order to do this other complicated-sounding thing" tends to be a bit of a turn-off. So it's good to mention different advantages which might be more applicable to what they're doing right now.
      – IMSoP
      14 hours ago

















    up vote
    77
    down vote













    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.






    share|improve this answer

















    • 14




      This may seem (or even be) irrelevant in this particular case I think it is very much relevant, in fact. How would you get the settings? A lot of systems I've seen will have a hard-coded default set of settings and a public facing configuration, so you'd need to load both and overwrite some values with the public settings. You may even need multiple sources of defaults. Perhaps you might even be getting some from disk, others from DB. So, the entire logic for even getting settings can, and often is, non-trivial - definitely not something consuming code should or would care about.
      – vlaz
      yesterday










    • We could also mention that object initialisation for a non-trivial component, such as a web service, would make $setting = new Setting(); horrendously inefficient. Injection and object instantiation happens once.
      – vikingsteve
      yesterday










    • @vikingsteve That's not important - you'd solve that problem more easily by using e.g. a singleton. And indeed, dependency injection doesn't mean you don't create the object multiple times. It just means that your class doesn't have control over the lifetime of its dependencies - you delegate it to something in your chain of callers.
      – Luaan
      17 hours ago






    • 5




      I think using mocks for testing should have more emphasis. Chances are if you look just at the code, it's always going to be a Settings object and will never change, so passing it in seems like a wasted effort. However, the very first time you try to test a Profile object by itself without also needing a Settings object (using a mock object instead as a solution) the need is very apparent.
      – JPhi1618
      16 hours ago






    • 1




      @JPhi1618 I think the problem with emphasising "DI is for Unit Testing" is that it just leads to the question "why do I need Unit Tests". The answer may seem obvious to you, and the benefits are definitely there, but to someone just starting out, saying "you need to do this complicated-sounding thing in order to do this other complicated-sounding thing" tends to be a bit of a turn-off. So it's good to mention different advantages which might be more applicable to what they're doing right now.
      – IMSoP
      14 hours ago















    up vote
    77
    down vote










    up vote
    77
    down vote









    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.






    share|improve this answer












    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.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    Michael Borgwardt

    42.7k1097156




    42.7k1097156








    • 14




      This may seem (or even be) irrelevant in this particular case I think it is very much relevant, in fact. How would you get the settings? A lot of systems I've seen will have a hard-coded default set of settings and a public facing configuration, so you'd need to load both and overwrite some values with the public settings. You may even need multiple sources of defaults. Perhaps you might even be getting some from disk, others from DB. So, the entire logic for even getting settings can, and often is, non-trivial - definitely not something consuming code should or would care about.
      – vlaz
      yesterday










    • We could also mention that object initialisation for a non-trivial component, such as a web service, would make $setting = new Setting(); horrendously inefficient. Injection and object instantiation happens once.
      – vikingsteve
      yesterday










    • @vikingsteve That's not important - you'd solve that problem more easily by using e.g. a singleton. And indeed, dependency injection doesn't mean you don't create the object multiple times. It just means that your class doesn't have control over the lifetime of its dependencies - you delegate it to something in your chain of callers.
      – Luaan
      17 hours ago






    • 5




      I think using mocks for testing should have more emphasis. Chances are if you look just at the code, it's always going to be a Settings object and will never change, so passing it in seems like a wasted effort. However, the very first time you try to test a Profile object by itself without also needing a Settings object (using a mock object instead as a solution) the need is very apparent.
      – JPhi1618
      16 hours ago






    • 1




      @JPhi1618 I think the problem with emphasising "DI is for Unit Testing" is that it just leads to the question "why do I need Unit Tests". The answer may seem obvious to you, and the benefits are definitely there, but to someone just starting out, saying "you need to do this complicated-sounding thing in order to do this other complicated-sounding thing" tends to be a bit of a turn-off. So it's good to mention different advantages which might be more applicable to what they're doing right now.
      – IMSoP
      14 hours ago
















    • 14




      This may seem (or even be) irrelevant in this particular case I think it is very much relevant, in fact. How would you get the settings? A lot of systems I've seen will have a hard-coded default set of settings and a public facing configuration, so you'd need to load both and overwrite some values with the public settings. You may even need multiple sources of defaults. Perhaps you might even be getting some from disk, others from DB. So, the entire logic for even getting settings can, and often is, non-trivial - definitely not something consuming code should or would care about.
      – vlaz
      yesterday










    • We could also mention that object initialisation for a non-trivial component, such as a web service, would make $setting = new Setting(); horrendously inefficient. Injection and object instantiation happens once.
      – vikingsteve
      yesterday










    • @vikingsteve That's not important - you'd solve that problem more easily by using e.g. a singleton. And indeed, dependency injection doesn't mean you don't create the object multiple times. It just means that your class doesn't have control over the lifetime of its dependencies - you delegate it to something in your chain of callers.
      – Luaan
      17 hours ago






    • 5




      I think using mocks for testing should have more emphasis. Chances are if you look just at the code, it's always going to be a Settings object and will never change, so passing it in seems like a wasted effort. However, the very first time you try to test a Profile object by itself without also needing a Settings object (using a mock object instead as a solution) the need is very apparent.
      – JPhi1618
      16 hours ago






    • 1




      @JPhi1618 I think the problem with emphasising "DI is for Unit Testing" is that it just leads to the question "why do I need Unit Tests". The answer may seem obvious to you, and the benefits are definitely there, but to someone just starting out, saying "you need to do this complicated-sounding thing in order to do this other complicated-sounding thing" tends to be a bit of a turn-off. So it's good to mention different advantages which might be more applicable to what they're doing right now.
      – IMSoP
      14 hours ago










    14




    14




    This may seem (or even be) irrelevant in this particular case I think it is very much relevant, in fact. How would you get the settings? A lot of systems I've seen will have a hard-coded default set of settings and a public facing configuration, so you'd need to load both and overwrite some values with the public settings. You may even need multiple sources of defaults. Perhaps you might even be getting some from disk, others from DB. So, the entire logic for even getting settings can, and often is, non-trivial - definitely not something consuming code should or would care about.
    – vlaz
    yesterday




    This may seem (or even be) irrelevant in this particular case I think it is very much relevant, in fact. How would you get the settings? A lot of systems I've seen will have a hard-coded default set of settings and a public facing configuration, so you'd need to load both and overwrite some values with the public settings. You may even need multiple sources of defaults. Perhaps you might even be getting some from disk, others from DB. So, the entire logic for even getting settings can, and often is, non-trivial - definitely not something consuming code should or would care about.
    – vlaz
    yesterday












    We could also mention that object initialisation for a non-trivial component, such as a web service, would make $setting = new Setting(); horrendously inefficient. Injection and object instantiation happens once.
    – vikingsteve
    yesterday




    We could also mention that object initialisation for a non-trivial component, such as a web service, would make $setting = new Setting(); horrendously inefficient. Injection and object instantiation happens once.
    – vikingsteve
    yesterday












    @vikingsteve That's not important - you'd solve that problem more easily by using e.g. a singleton. And indeed, dependency injection doesn't mean you don't create the object multiple times. It just means that your class doesn't have control over the lifetime of its dependencies - you delegate it to something in your chain of callers.
    – Luaan
    17 hours ago




    @vikingsteve That's not important - you'd solve that problem more easily by using e.g. a singleton. And indeed, dependency injection doesn't mean you don't create the object multiple times. It just means that your class doesn't have control over the lifetime of its dependencies - you delegate it to something in your chain of callers.
    – Luaan
    17 hours ago




    5




    5




    I think using mocks for testing should have more emphasis. Chances are if you look just at the code, it's always going to be a Settings object and will never change, so passing it in seems like a wasted effort. However, the very first time you try to test a Profile object by itself without also needing a Settings object (using a mock object instead as a solution) the need is very apparent.
    – JPhi1618
    16 hours ago




    I think using mocks for testing should have more emphasis. Chances are if you look just at the code, it's always going to be a Settings object and will never change, so passing it in seems like a wasted effort. However, the very first time you try to test a Profile object by itself without also needing a Settings object (using a mock object instead as a solution) the need is very apparent.
    – JPhi1618
    16 hours ago




    1




    1




    @JPhi1618 I think the problem with emphasising "DI is for Unit Testing" is that it just leads to the question "why do I need Unit Tests". The answer may seem obvious to you, and the benefits are definitely there, but to someone just starting out, saying "you need to do this complicated-sounding thing in order to do this other complicated-sounding thing" tends to be a bit of a turn-off. So it's good to mention different advantages which might be more applicable to what they're doing right now.
    – IMSoP
    14 hours ago






    @JPhi1618 I think the problem with emphasising "DI is for Unit Testing" is that it just leads to the question "why do I need Unit Tests". The answer may seem obvious to you, and the benefits are definitely there, but to someone just starting out, saying "you need to do this complicated-sounding thing in order to do this other complicated-sounding thing" tends to be a bit of a turn-off. So it's good to mention different advantages which might be more applicable to what they're doing right now.
    – IMSoP
    14 hours ago














    up vote
    42
    down vote













    Dependency Injection makes your code easier to test.



    I learned this first-hand when I was tasked with fixing a hard-to-catch bug in Magento's PayPal integration.



    An issue would arise when PayPal was telling Magento about a failed payment: Magento wouldn't register the failure properly.



    Testing a potential fix "manually" would be very tedious: you'd need to somehow trigger a "Failed" PayPal notification. You'd have to submit an e-check, cancel it, and wait for it to error out. That means 3+ days to test a one-character code change!



    Luckily, it appears that the Magento core devs who developed this function had testing in mind, and used a dependency injection pattern to make it trivial. This allows us to verify our work with a simple test case like this one:



    <?php
    // This is the dependency we will inject to facilitate our testing
    class MockHttpClient extends Varien_Http_Adapter_Curl {
    function read() {
    // Make Magento think that PayPal said "VERIFIED", no matter what they actually said...
    return "HTTP/1.1 200 OKnnVERIFIED";
    }
    }

    // Here, we trick Magento into thinking PayPal actually sent something back.
    // Magento will try to verify it against PayPal's API though, and since it's fake data, it'll always fail.
    $ipnPayload = array (
    'invoice' => '100058137', // Order ID to test against
    'txn_id' => '04S87540L2309371A', // Test PayPal transaction ID
    'payment_status' => 'Failed' // New payment status that Magento should ingest
    );

    // This is what Magento's controller calls during a normal IPN request.
    // Instead of letting Magento talk to PayPal, we "inject" our fake HTTP client, which always returns VERIFIED.
    Mage::getModel('paypal/ipn')->processIpnRequest($ipnPayload, new MockHttpClient());


    I'm sure the DI pattern has plenty of other advantages, but increased testability is the single biggest benefit in my mind.



    If you're curious about the solution to this problem, check out the GitHub repo here: https://github.com/bubbleupdev/BUCorefix_Paypalstatus






    share|improve this answer

















    • 2




      Dependency injection makes code easier to test than code with hardcoded dependencies. Eliminating dependencies from business logic altogether is even better.
      – Ant P
      yesterday






    • 1




      And one major way to do what @AntP suggests is via parameterization. The logic to transform results coming back from the database into the object used to fill out a page template (commonly known as a "model") shouldn't even know a fetch is happening; it just needs to get those objects as input.
      – jpmc26
      yesterday








    • 3




      @jpmc26 indeed - I tend to harp on about functional core, imperative shell, which is really just a fancy name for passing data into your domain instead of injecting dependencies into it. The domain is pure, can be unit tested with no mocks and then is just wrapped in a shell that adapts things like persistence, messaging etc.
      – Ant P
      yesterday












    • I think the sole focus on testability is harmful to the adoption of DI. It makes it unappealing to people who feel like they either don't need much testing, or think they already have testing under control. I would argue it is virtually impossible to write clean, reusable code without DI. Testing is very far down on the list of benefits and it's disappointing to see this answer ranked 1st or 2nd in every question on DI's benefits.
      – Carl Leth
      1 hour ago















    up vote
    42
    down vote













    Dependency Injection makes your code easier to test.



    I learned this first-hand when I was tasked with fixing a hard-to-catch bug in Magento's PayPal integration.



    An issue would arise when PayPal was telling Magento about a failed payment: Magento wouldn't register the failure properly.



    Testing a potential fix "manually" would be very tedious: you'd need to somehow trigger a "Failed" PayPal notification. You'd have to submit an e-check, cancel it, and wait for it to error out. That means 3+ days to test a one-character code change!



    Luckily, it appears that the Magento core devs who developed this function had testing in mind, and used a dependency injection pattern to make it trivial. This allows us to verify our work with a simple test case like this one:



    <?php
    // This is the dependency we will inject to facilitate our testing
    class MockHttpClient extends Varien_Http_Adapter_Curl {
    function read() {
    // Make Magento think that PayPal said "VERIFIED", no matter what they actually said...
    return "HTTP/1.1 200 OKnnVERIFIED";
    }
    }

    // Here, we trick Magento into thinking PayPal actually sent something back.
    // Magento will try to verify it against PayPal's API though, and since it's fake data, it'll always fail.
    $ipnPayload = array (
    'invoice' => '100058137', // Order ID to test against
    'txn_id' => '04S87540L2309371A', // Test PayPal transaction ID
    'payment_status' => 'Failed' // New payment status that Magento should ingest
    );

    // This is what Magento's controller calls during a normal IPN request.
    // Instead of letting Magento talk to PayPal, we "inject" our fake HTTP client, which always returns VERIFIED.
    Mage::getModel('paypal/ipn')->processIpnRequest($ipnPayload, new MockHttpClient());


    I'm sure the DI pattern has plenty of other advantages, but increased testability is the single biggest benefit in my mind.



    If you're curious about the solution to this problem, check out the GitHub repo here: https://github.com/bubbleupdev/BUCorefix_Paypalstatus






    share|improve this answer

















    • 2




      Dependency injection makes code easier to test than code with hardcoded dependencies. Eliminating dependencies from business logic altogether is even better.
      – Ant P
      yesterday






    • 1




      And one major way to do what @AntP suggests is via parameterization. The logic to transform results coming back from the database into the object used to fill out a page template (commonly known as a "model") shouldn't even know a fetch is happening; it just needs to get those objects as input.
      – jpmc26
      yesterday








    • 3




      @jpmc26 indeed - I tend to harp on about functional core, imperative shell, which is really just a fancy name for passing data into your domain instead of injecting dependencies into it. The domain is pure, can be unit tested with no mocks and then is just wrapped in a shell that adapts things like persistence, messaging etc.
      – Ant P
      yesterday












    • I think the sole focus on testability is harmful to the adoption of DI. It makes it unappealing to people who feel like they either don't need much testing, or think they already have testing under control. I would argue it is virtually impossible to write clean, reusable code without DI. Testing is very far down on the list of benefits and it's disappointing to see this answer ranked 1st or 2nd in every question on DI's benefits.
      – Carl Leth
      1 hour ago













    up vote
    42
    down vote










    up vote
    42
    down vote









    Dependency Injection makes your code easier to test.



    I learned this first-hand when I was tasked with fixing a hard-to-catch bug in Magento's PayPal integration.



    An issue would arise when PayPal was telling Magento about a failed payment: Magento wouldn't register the failure properly.



    Testing a potential fix "manually" would be very tedious: you'd need to somehow trigger a "Failed" PayPal notification. You'd have to submit an e-check, cancel it, and wait for it to error out. That means 3+ days to test a one-character code change!



    Luckily, it appears that the Magento core devs who developed this function had testing in mind, and used a dependency injection pattern to make it trivial. This allows us to verify our work with a simple test case like this one:



    <?php
    // This is the dependency we will inject to facilitate our testing
    class MockHttpClient extends Varien_Http_Adapter_Curl {
    function read() {
    // Make Magento think that PayPal said "VERIFIED", no matter what they actually said...
    return "HTTP/1.1 200 OKnnVERIFIED";
    }
    }

    // Here, we trick Magento into thinking PayPal actually sent something back.
    // Magento will try to verify it against PayPal's API though, and since it's fake data, it'll always fail.
    $ipnPayload = array (
    'invoice' => '100058137', // Order ID to test against
    'txn_id' => '04S87540L2309371A', // Test PayPal transaction ID
    'payment_status' => 'Failed' // New payment status that Magento should ingest
    );

    // This is what Magento's controller calls during a normal IPN request.
    // Instead of letting Magento talk to PayPal, we "inject" our fake HTTP client, which always returns VERIFIED.
    Mage::getModel('paypal/ipn')->processIpnRequest($ipnPayload, new MockHttpClient());


    I'm sure the DI pattern has plenty of other advantages, but increased testability is the single biggest benefit in my mind.



    If you're curious about the solution to this problem, check out the GitHub repo here: https://github.com/bubbleupdev/BUCorefix_Paypalstatus






    share|improve this answer












    Dependency Injection makes your code easier to test.



    I learned this first-hand when I was tasked with fixing a hard-to-catch bug in Magento's PayPal integration.



    An issue would arise when PayPal was telling Magento about a failed payment: Magento wouldn't register the failure properly.



    Testing a potential fix "manually" would be very tedious: you'd need to somehow trigger a "Failed" PayPal notification. You'd have to submit an e-check, cancel it, and wait for it to error out. That means 3+ days to test a one-character code change!



    Luckily, it appears that the Magento core devs who developed this function had testing in mind, and used a dependency injection pattern to make it trivial. This allows us to verify our work with a simple test case like this one:



    <?php
    // This is the dependency we will inject to facilitate our testing
    class MockHttpClient extends Varien_Http_Adapter_Curl {
    function read() {
    // Make Magento think that PayPal said "VERIFIED", no matter what they actually said...
    return "HTTP/1.1 200 OKnnVERIFIED";
    }
    }

    // Here, we trick Magento into thinking PayPal actually sent something back.
    // Magento will try to verify it against PayPal's API though, and since it's fake data, it'll always fail.
    $ipnPayload = array (
    'invoice' => '100058137', // Order ID to test against
    'txn_id' => '04S87540L2309371A', // Test PayPal transaction ID
    'payment_status' => 'Failed' // New payment status that Magento should ingest
    );

    // This is what Magento's controller calls during a normal IPN request.
    // Instead of letting Magento talk to PayPal, we "inject" our fake HTTP client, which always returns VERIFIED.
    Mage::getModel('paypal/ipn')->processIpnRequest($ipnPayload, new MockHttpClient());


    I'm sure the DI pattern has plenty of other advantages, but increased testability is the single biggest benefit in my mind.



    If you're curious about the solution to this problem, check out the GitHub repo here: https://github.com/bubbleupdev/BUCorefix_Paypalstatus







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    Eric Seastrand

    49038




    49038








    • 2




      Dependency injection makes code easier to test than code with hardcoded dependencies. Eliminating dependencies from business logic altogether is even better.
      – Ant P
      yesterday






    • 1




      And one major way to do what @AntP suggests is via parameterization. The logic to transform results coming back from the database into the object used to fill out a page template (commonly known as a "model") shouldn't even know a fetch is happening; it just needs to get those objects as input.
      – jpmc26
      yesterday








    • 3




      @jpmc26 indeed - I tend to harp on about functional core, imperative shell, which is really just a fancy name for passing data into your domain instead of injecting dependencies into it. The domain is pure, can be unit tested with no mocks and then is just wrapped in a shell that adapts things like persistence, messaging etc.
      – Ant P
      yesterday












    • I think the sole focus on testability is harmful to the adoption of DI. It makes it unappealing to people who feel like they either don't need much testing, or think they already have testing under control. I would argue it is virtually impossible to write clean, reusable code without DI. Testing is very far down on the list of benefits and it's disappointing to see this answer ranked 1st or 2nd in every question on DI's benefits.
      – Carl Leth
      1 hour ago














    • 2




      Dependency injection makes code easier to test than code with hardcoded dependencies. Eliminating dependencies from business logic altogether is even better.
      – Ant P
      yesterday






    • 1




      And one major way to do what @AntP suggests is via parameterization. The logic to transform results coming back from the database into the object used to fill out a page template (commonly known as a "model") shouldn't even know a fetch is happening; it just needs to get those objects as input.
      – jpmc26
      yesterday








    • 3




      @jpmc26 indeed - I tend to harp on about functional core, imperative shell, which is really just a fancy name for passing data into your domain instead of injecting dependencies into it. The domain is pure, can be unit tested with no mocks and then is just wrapped in a shell that adapts things like persistence, messaging etc.
      – Ant P
      yesterday












    • I think the sole focus on testability is harmful to the adoption of DI. It makes it unappealing to people who feel like they either don't need much testing, or think they already have testing under control. I would argue it is virtually impossible to write clean, reusable code without DI. Testing is very far down on the list of benefits and it's disappointing to see this answer ranked 1st or 2nd in every question on DI's benefits.
      – Carl Leth
      1 hour ago








    2




    2




    Dependency injection makes code easier to test than code with hardcoded dependencies. Eliminating dependencies from business logic altogether is even better.
    – Ant P
    yesterday




    Dependency injection makes code easier to test than code with hardcoded dependencies. Eliminating dependencies from business logic altogether is even better.
    – Ant P
    yesterday




    1




    1




    And one major way to do what @AntP suggests is via parameterization. The logic to transform results coming back from the database into the object used to fill out a page template (commonly known as a "model") shouldn't even know a fetch is happening; it just needs to get those objects as input.
    – jpmc26
    yesterday






    And one major way to do what @AntP suggests is via parameterization. The logic to transform results coming back from the database into the object used to fill out a page template (commonly known as a "model") shouldn't even know a fetch is happening; it just needs to get those objects as input.
    – jpmc26
    yesterday






    3




    3




    @jpmc26 indeed - I tend to harp on about functional core, imperative shell, which is really just a fancy name for passing data into your domain instead of injecting dependencies into it. The domain is pure, can be unit tested with no mocks and then is just wrapped in a shell that adapts things like persistence, messaging etc.
    – Ant P
    yesterday






    @jpmc26 indeed - I tend to harp on about functional core, imperative shell, which is really just a fancy name for passing data into your domain instead of injecting dependencies into it. The domain is pure, can be unit tested with no mocks and then is just wrapped in a shell that adapts things like persistence, messaging etc.
    – Ant P
    yesterday














    I think the sole focus on testability is harmful to the adoption of DI. It makes it unappealing to people who feel like they either don't need much testing, or think they already have testing under control. I would argue it is virtually impossible to write clean, reusable code without DI. Testing is very far down on the list of benefits and it's disappointing to see this answer ranked 1st or 2nd in every question on DI's benefits.
    – Carl Leth
    1 hour ago




    I think the sole focus on testability is harmful to the adoption of DI. It makes it unappealing to people who feel like they either don't need much testing, or think they already have testing under control. I would argue it is virtually impossible to write clean, reusable code without DI. Testing is very far down on the list of benefits and it's disappointing to see this answer ranked 1st or 2nd in every question on DI's benefits.
    – Carl Leth
    1 hour ago










    up vote
    15
    down vote













    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 a second type of Car 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);


    Now you don't have to make any changes in RaceTrack, Game, Car, or Motor. That means two things:




    • the change is easier, because it's all in one place.

    • there's no way to introduce new bugs in classes you don't change!


    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.






    share|improve this answer



















    • 2




      Ad hard-coded, there is not really that much difference between code and config file. A file bundled with the application is a source even if you read dynamically. Pulling values from code to data files in json or whatever ‘config’ format helps nothing unless the values should be overridden by the user or depend on the environment.
      – Jan Hudec
      yesterday








    • 1




      I actually made a Tamagotchi once on an Arduino (16MHz, 2KB)
      – Jungkook
      23 hours ago










    • @JanHudec True. I actually had a longer explanation there, but decided to remove it to keep it shorter and focus on how it relates to DI. There's more stuff which isn't 100% correct; overall the answer is more optimized to push "the point" of DI without it getting too long. Or put differently, this is what I would have wanted to hear when I started out with DI.
      – R. Schmitz
      20 hours ago















    up vote
    15
    down vote













    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 a second type of Car 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);


    Now you don't have to make any changes in RaceTrack, Game, Car, or Motor. That means two things:




    • the change is easier, because it's all in one place.

    • there's no way to introduce new bugs in classes you don't change!


    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.






    share|improve this answer



















    • 2




      Ad hard-coded, there is not really that much difference between code and config file. A file bundled with the application is a source even if you read dynamically. Pulling values from code to data files in json or whatever ‘config’ format helps nothing unless the values should be overridden by the user or depend on the environment.
      – Jan Hudec
      yesterday








    • 1




      I actually made a Tamagotchi once on an Arduino (16MHz, 2KB)
      – Jungkook
      23 hours ago










    • @JanHudec True. I actually had a longer explanation there, but decided to remove it to keep it shorter and focus on how it relates to DI. There's more stuff which isn't 100% correct; overall the answer is more optimized to push "the point" of DI without it getting too long. Or put differently, this is what I would have wanted to hear when I started out with DI.
      – R. Schmitz
      20 hours ago













    up vote
    15
    down vote










    up vote
    15
    down vote









    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 a second type of Car 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);


    Now you don't have to make any changes in RaceTrack, Game, Car, or Motor. That means two things:




    • the change is easier, because it's all in one place.

    • there's no way to introduce new bugs in classes you don't change!


    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.






    share|improve this answer














    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 a second type of Car 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);


    Now you don't have to make any changes in RaceTrack, Game, Car, or Motor. That means two things:




    • the change is easier, because it's all in one place.

    • there's no way to introduce new bugs in classes you don't change!


    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited yesterday

























    answered yesterday









    R. Schmitz

    972621




    972621








    • 2




      Ad hard-coded, there is not really that much difference between code and config file. A file bundled with the application is a source even if you read dynamically. Pulling values from code to data files in json or whatever ‘config’ format helps nothing unless the values should be overridden by the user or depend on the environment.
      – Jan Hudec
      yesterday








    • 1




      I actually made a Tamagotchi once on an Arduino (16MHz, 2KB)
      – Jungkook
      23 hours ago










    • @JanHudec True. I actually had a longer explanation there, but decided to remove it to keep it shorter and focus on how it relates to DI. There's more stuff which isn't 100% correct; overall the answer is more optimized to push "the point" of DI without it getting too long. Or put differently, this is what I would have wanted to hear when I started out with DI.
      – R. Schmitz
      20 hours ago














    • 2




      Ad hard-coded, there is not really that much difference between code and config file. A file bundled with the application is a source even if you read dynamically. Pulling values from code to data files in json or whatever ‘config’ format helps nothing unless the values should be overridden by the user or depend on the environment.
      – Jan Hudec
      yesterday








    • 1




      I actually made a Tamagotchi once on an Arduino (16MHz, 2KB)
      – Jungkook
      23 hours ago










    • @JanHudec True. I actually had a longer explanation there, but decided to remove it to keep it shorter and focus on how it relates to DI. There's more stuff which isn't 100% correct; overall the answer is more optimized to push "the point" of DI without it getting too long. Or put differently, this is what I would have wanted to hear when I started out with DI.
      – R. Schmitz
      20 hours ago








    2




    2




    Ad hard-coded, there is not really that much difference between code and config file. A file bundled with the application is a source even if you read dynamically. Pulling values from code to data files in json or whatever ‘config’ format helps nothing unless the values should be overridden by the user or depend on the environment.
    – Jan Hudec
    yesterday






    Ad hard-coded, there is not really that much difference between code and config file. A file bundled with the application is a source even if you read dynamically. Pulling values from code to data files in json or whatever ‘config’ format helps nothing unless the values should be overridden by the user or depend on the environment.
    – Jan Hudec
    yesterday






    1




    1




    I actually made a Tamagotchi once on an Arduino (16MHz, 2KB)
    – Jungkook
    23 hours ago




    I actually made a Tamagotchi once on an Arduino (16MHz, 2KB)
    – Jungkook
    23 hours ago












    @JanHudec True. I actually had a longer explanation there, but decided to remove it to keep it shorter and focus on how it relates to DI. There's more stuff which isn't 100% correct; overall the answer is more optimized to push "the point" of DI without it getting too long. Or put differently, this is what I would have wanted to hear when I started out with DI.
    – R. Schmitz
    20 hours ago




    @JanHudec True. I actually had a longer explanation there, but decided to remove it to keep it shorter and focus on how it relates to DI. There's more stuff which isn't 100% correct; overall the answer is more optimized to push "the point" of DI without it getting too long. Or put differently, this is what I would have wanted to hear when I started out with DI.
    – R. Schmitz
    20 hours ago










    up vote
    6
    down vote













    The example you give is not dependency injection in the classical sense. Dependency injection usually refers to passing objects in a constructor or by using "setter injection" just after the object is created, in order to set a value on a field in a newly created object.



    Your example passes an object as an argument to an instance method. This instance method then modifies a field on that object. Dependency injection? No. Breaking encapsulation and data hiding? Absolutely!



    Now, if the code was like this:



    class Profile {
    private $settings;

    public function __construct(Settings $settings) {
    $this->settings = $settings;
    }

    public function deactive() {
    $this->settings->isActive = false;
    }
    }


    Then I would say you are using dependency injection. The notable difference is a Settings object being passed in to the constructor or a Profile object.



    This is useful if the Settings object is expensive or complex to construct, or Settings is an interface or abstract class where multiple concrete implementations exist in order to change run time behavior.



    Since you are directly accessing a field on the Settings object rather than calling a method, you can't take advantage of Polymorphism, which is one of the benefits of dependency injection.



    It looks like the Settings for a Profile are specific to that profile. In this case I would do one of the following:




    1. Instantiate the Settings object inside the Profile constructor


    2. Pass the Settings object in the constructor and copy over individual fields that apply to the Profile



    Honestly, by passing the Settings object in to deactivateProfile and then modifying an internal field of the Settings object is a code smell. The Settings object should be the only one modifying its internal fields.






    share|improve this answer

















    • 5




      The example you give is not dependency injection in the classical sense. -- It doesn't matter. OO people have objects on the brain, but you're still handing a dependency to something.
      – Robert Harvey
      yesterday










    • When you talk about “in the classical sense”, you are, as @RobertHarvey says, speaking purely in OO terms. In functional programming for example, injecting one function into another (higher order functions) is that paradigm’s classical example of dependency injection.
      – David Arno
      yesterday






    • 3




      @RobertHarvey: I guess I was taking too many liberties with "dependency injection." The place people most often think of the term and use the term is in reference to fields on an object being "injected" at the time of object construction, or immediately after in the case of setter injection.
      – Greg Burghardt
      yesterday










    • @DavidArno: Yes, you are correct. The OP seems to have an object oriented PHP code snippet in the question, so I was answering in that regard only, and not addressing functional programming --- all though with PHP you could ask the same question from the standpoint of functional programming.
      – Greg Burghardt
      yesterday















    up vote
    6
    down vote













    The example you give is not dependency injection in the classical sense. Dependency injection usually refers to passing objects in a constructor or by using "setter injection" just after the object is created, in order to set a value on a field in a newly created object.



    Your example passes an object as an argument to an instance method. This instance method then modifies a field on that object. Dependency injection? No. Breaking encapsulation and data hiding? Absolutely!



    Now, if the code was like this:



    class Profile {
    private $settings;

    public function __construct(Settings $settings) {
    $this->settings = $settings;
    }

    public function deactive() {
    $this->settings->isActive = false;
    }
    }


    Then I would say you are using dependency injection. The notable difference is a Settings object being passed in to the constructor or a Profile object.



    This is useful if the Settings object is expensive or complex to construct, or Settings is an interface or abstract class where multiple concrete implementations exist in order to change run time behavior.



    Since you are directly accessing a field on the Settings object rather than calling a method, you can't take advantage of Polymorphism, which is one of the benefits of dependency injection.



    It looks like the Settings for a Profile are specific to that profile. In this case I would do one of the following:




    1. Instantiate the Settings object inside the Profile constructor


    2. Pass the Settings object in the constructor and copy over individual fields that apply to the Profile



    Honestly, by passing the Settings object in to deactivateProfile and then modifying an internal field of the Settings object is a code smell. The Settings object should be the only one modifying its internal fields.






    share|improve this answer

















    • 5




      The example you give is not dependency injection in the classical sense. -- It doesn't matter. OO people have objects on the brain, but you're still handing a dependency to something.
      – Robert Harvey
      yesterday










    • When you talk about “in the classical sense”, you are, as @RobertHarvey says, speaking purely in OO terms. In functional programming for example, injecting one function into another (higher order functions) is that paradigm’s classical example of dependency injection.
      – David Arno
      yesterday






    • 3




      @RobertHarvey: I guess I was taking too many liberties with "dependency injection." The place people most often think of the term and use the term is in reference to fields on an object being "injected" at the time of object construction, or immediately after in the case of setter injection.
      – Greg Burghardt
      yesterday










    • @DavidArno: Yes, you are correct. The OP seems to have an object oriented PHP code snippet in the question, so I was answering in that regard only, and not addressing functional programming --- all though with PHP you could ask the same question from the standpoint of functional programming.
      – Greg Burghardt
      yesterday













    up vote
    6
    down vote










    up vote
    6
    down vote









    The example you give is not dependency injection in the classical sense. Dependency injection usually refers to passing objects in a constructor or by using "setter injection" just after the object is created, in order to set a value on a field in a newly created object.



    Your example passes an object as an argument to an instance method. This instance method then modifies a field on that object. Dependency injection? No. Breaking encapsulation and data hiding? Absolutely!



    Now, if the code was like this:



    class Profile {
    private $settings;

    public function __construct(Settings $settings) {
    $this->settings = $settings;
    }

    public function deactive() {
    $this->settings->isActive = false;
    }
    }


    Then I would say you are using dependency injection. The notable difference is a Settings object being passed in to the constructor or a Profile object.



    This is useful if the Settings object is expensive or complex to construct, or Settings is an interface or abstract class where multiple concrete implementations exist in order to change run time behavior.



    Since you are directly accessing a field on the Settings object rather than calling a method, you can't take advantage of Polymorphism, which is one of the benefits of dependency injection.



    It looks like the Settings for a Profile are specific to that profile. In this case I would do one of the following:




    1. Instantiate the Settings object inside the Profile constructor


    2. Pass the Settings object in the constructor and copy over individual fields that apply to the Profile



    Honestly, by passing the Settings object in to deactivateProfile and then modifying an internal field of the Settings object is a code smell. The Settings object should be the only one modifying its internal fields.






    share|improve this answer












    The example you give is not dependency injection in the classical sense. Dependency injection usually refers to passing objects in a constructor or by using "setter injection" just after the object is created, in order to set a value on a field in a newly created object.



    Your example passes an object as an argument to an instance method. This instance method then modifies a field on that object. Dependency injection? No. Breaking encapsulation and data hiding? Absolutely!



    Now, if the code was like this:



    class Profile {
    private $settings;

    public function __construct(Settings $settings) {
    $this->settings = $settings;
    }

    public function deactive() {
    $this->settings->isActive = false;
    }
    }


    Then I would say you are using dependency injection. The notable difference is a Settings object being passed in to the constructor or a Profile object.



    This is useful if the Settings object is expensive or complex to construct, or Settings is an interface or abstract class where multiple concrete implementations exist in order to change run time behavior.



    Since you are directly accessing a field on the Settings object rather than calling a method, you can't take advantage of Polymorphism, which is one of the benefits of dependency injection.



    It looks like the Settings for a Profile are specific to that profile. In this case I would do one of the following:




    1. Instantiate the Settings object inside the Profile constructor


    2. Pass the Settings object in the constructor and copy over individual fields that apply to the Profile



    Honestly, by passing the Settings object in to deactivateProfile and then modifying an internal field of the Settings object is a code smell. The Settings object should be the only one modifying its internal fields.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    Greg Burghardt

    11.2k42755




    11.2k42755








    • 5




      The example you give is not dependency injection in the classical sense. -- It doesn't matter. OO people have objects on the brain, but you're still handing a dependency to something.
      – Robert Harvey
      yesterday










    • When you talk about “in the classical sense”, you are, as @RobertHarvey says, speaking purely in OO terms. In functional programming for example, injecting one function into another (higher order functions) is that paradigm’s classical example of dependency injection.
      – David Arno
      yesterday






    • 3




      @RobertHarvey: I guess I was taking too many liberties with "dependency injection." The place people most often think of the term and use the term is in reference to fields on an object being "injected" at the time of object construction, or immediately after in the case of setter injection.
      – Greg Burghardt
      yesterday










    • @DavidArno: Yes, you are correct. The OP seems to have an object oriented PHP code snippet in the question, so I was answering in that regard only, and not addressing functional programming --- all though with PHP you could ask the same question from the standpoint of functional programming.
      – Greg Burghardt
      yesterday














    • 5




      The example you give is not dependency injection in the classical sense. -- It doesn't matter. OO people have objects on the brain, but you're still handing a dependency to something.
      – Robert Harvey
      yesterday










    • When you talk about “in the classical sense”, you are, as @RobertHarvey says, speaking purely in OO terms. In functional programming for example, injecting one function into another (higher order functions) is that paradigm’s classical example of dependency injection.
      – David Arno
      yesterday






    • 3




      @RobertHarvey: I guess I was taking too many liberties with "dependency injection." The place people most often think of the term and use the term is in reference to fields on an object being "injected" at the time of object construction, or immediately after in the case of setter injection.
      – Greg Burghardt
      yesterday










    • @DavidArno: Yes, you are correct. The OP seems to have an object oriented PHP code snippet in the question, so I was answering in that regard only, and not addressing functional programming --- all though with PHP you could ask the same question from the standpoint of functional programming.
      – Greg Burghardt
      yesterday








    5




    5




    The example you give is not dependency injection in the classical sense. -- It doesn't matter. OO people have objects on the brain, but you're still handing a dependency to something.
    – Robert Harvey
    yesterday




    The example you give is not dependency injection in the classical sense. -- It doesn't matter. OO people have objects on the brain, but you're still handing a dependency to something.
    – Robert Harvey
    yesterday












    When you talk about “in the classical sense”, you are, as @RobertHarvey says, speaking purely in OO terms. In functional programming for example, injecting one function into another (higher order functions) is that paradigm’s classical example of dependency injection.
    – David Arno
    yesterday




    When you talk about “in the classical sense”, you are, as @RobertHarvey says, speaking purely in OO terms. In functional programming for example, injecting one function into another (higher order functions) is that paradigm’s classical example of dependency injection.
    – David Arno
    yesterday




    3




    3




    @RobertHarvey: I guess I was taking too many liberties with "dependency injection." The place people most often think of the term and use the term is in reference to fields on an object being "injected" at the time of object construction, or immediately after in the case of setter injection.
    – Greg Burghardt
    yesterday




    @RobertHarvey: I guess I was taking too many liberties with "dependency injection." The place people most often think of the term and use the term is in reference to fields on an object being "injected" at the time of object construction, or immediately after in the case of setter injection.
    – Greg Burghardt
    yesterday












    @DavidArno: Yes, you are correct. The OP seems to have an object oriented PHP code snippet in the question, so I was answering in that regard only, and not addressing functional programming --- all though with PHP you could ask the same question from the standpoint of functional programming.
    – Greg Burghardt
    yesterday




    @DavidArno: Yes, you are correct. The OP seems to have an object oriented PHP code snippet in the question, so I was answering in that regard only, and not addressing functional programming --- all though with PHP you could ask the same question from the standpoint of functional programming.
    – Greg Burghardt
    yesterday










    up vote
    3
    down vote













    I know I'm coming late to this party but I feel an important point is being missed.




    Why should I do this:




    class Profile {
    public function deactivateProfile(Setting $setting)
    {
    $setting->isActive = false;
    }
    }


    You shouldn't. But not because Dependency Injection is a bad idea. It's because this is doing it wrong.



    Lets look at this things using code. We're going to do this:



    $profile = new Profile();
    $profile->deactivateProfile($setting);


    when we get about the same thing out of this:



    $setting->isActive = false; // Deactivate profile


    So of course it seems like a waste of time. It is when you do it this way. This is not the best use of Dependency Injection. It's not even the best use of a class.



    Now what if instead we had this:



    $profile = new Profile($setting);

    $application = new Application($profile);

    $application.start();


    And now the application is free to activate and deactivate the profile without having to know anything in particular about the setting that it's actually changing. Why is that good? In case you need to change setting. The application is walled off from those changes so you're free to go nuts in a safe contained space without having to watch everything break as soon as you touch something.



    This follows the separate construction from behavior principle. The DI pattern here is a simple one. Build everything you need at as low a level as you can, wire them together, then start all the behavior ticking with one call.



    The result is you have a separate place to decide what connects to what and a different place to manage what says what to whatever.



    Try that on something you have to maintain over time and see if it doesn't help.






    share|improve this answer























    • I was ready to upvote this until I got to the last three paragraphs, which come across as a bit patronising, or maybe just pessimistic. It's like you're assuming that the reader will ignore everything you've just said, and defensively responding to comments that haven't been made yet.
      – IMSoP
      15 hours ago










    • @IMSoP Better now?
      – candied_orange
      11 hours ago















    up vote
    3
    down vote













    I know I'm coming late to this party but I feel an important point is being missed.




    Why should I do this:




    class Profile {
    public function deactivateProfile(Setting $setting)
    {
    $setting->isActive = false;
    }
    }


    You shouldn't. But not because Dependency Injection is a bad idea. It's because this is doing it wrong.



    Lets look at this things using code. We're going to do this:



    $profile = new Profile();
    $profile->deactivateProfile($setting);


    when we get about the same thing out of this:



    $setting->isActive = false; // Deactivate profile


    So of course it seems like a waste of time. It is when you do it this way. This is not the best use of Dependency Injection. It's not even the best use of a class.



    Now what if instead we had this:



    $profile = new Profile($setting);

    $application = new Application($profile);

    $application.start();


    And now the application is free to activate and deactivate the profile without having to know anything in particular about the setting that it's actually changing. Why is that good? In case you need to change setting. The application is walled off from those changes so you're free to go nuts in a safe contained space without having to watch everything break as soon as you touch something.



    This follows the separate construction from behavior principle. The DI pattern here is a simple one. Build everything you need at as low a level as you can, wire them together, then start all the behavior ticking with one call.



    The result is you have a separate place to decide what connects to what and a different place to manage what says what to whatever.



    Try that on something you have to maintain over time and see if it doesn't help.






    share|improve this answer























    • I was ready to upvote this until I got to the last three paragraphs, which come across as a bit patronising, or maybe just pessimistic. It's like you're assuming that the reader will ignore everything you've just said, and defensively responding to comments that haven't been made yet.
      – IMSoP
      15 hours ago










    • @IMSoP Better now?
      – candied_orange
      11 hours ago













    up vote
    3
    down vote










    up vote
    3
    down vote









    I know I'm coming late to this party but I feel an important point is being missed.




    Why should I do this:




    class Profile {
    public function deactivateProfile(Setting $setting)
    {
    $setting->isActive = false;
    }
    }


    You shouldn't. But not because Dependency Injection is a bad idea. It's because this is doing it wrong.



    Lets look at this things using code. We're going to do this:



    $profile = new Profile();
    $profile->deactivateProfile($setting);


    when we get about the same thing out of this:



    $setting->isActive = false; // Deactivate profile


    So of course it seems like a waste of time. It is when you do it this way. This is not the best use of Dependency Injection. It's not even the best use of a class.



    Now what if instead we had this:



    $profile = new Profile($setting);

    $application = new Application($profile);

    $application.start();


    And now the application is free to activate and deactivate the profile without having to know anything in particular about the setting that it's actually changing. Why is that good? In case you need to change setting. The application is walled off from those changes so you're free to go nuts in a safe contained space without having to watch everything break as soon as you touch something.



    This follows the separate construction from behavior principle. The DI pattern here is a simple one. Build everything you need at as low a level as you can, wire them together, then start all the behavior ticking with one call.



    The result is you have a separate place to decide what connects to what and a different place to manage what says what to whatever.



    Try that on something you have to maintain over time and see if it doesn't help.






    share|improve this answer














    I know I'm coming late to this party but I feel an important point is being missed.




    Why should I do this:




    class Profile {
    public function deactivateProfile(Setting $setting)
    {
    $setting->isActive = false;
    }
    }


    You shouldn't. But not because Dependency Injection is a bad idea. It's because this is doing it wrong.



    Lets look at this things using code. We're going to do this:



    $profile = new Profile();
    $profile->deactivateProfile($setting);


    when we get about the same thing out of this:



    $setting->isActive = false; // Deactivate profile


    So of course it seems like a waste of time. It is when you do it this way. This is not the best use of Dependency Injection. It's not even the best use of a class.



    Now what if instead we had this:



    $profile = new Profile($setting);

    $application = new Application($profile);

    $application.start();


    And now the application is free to activate and deactivate the profile without having to know anything in particular about the setting that it's actually changing. Why is that good? In case you need to change setting. The application is walled off from those changes so you're free to go nuts in a safe contained space without having to watch everything break as soon as you touch something.



    This follows the separate construction from behavior principle. The DI pattern here is a simple one. Build everything you need at as low a level as you can, wire them together, then start all the behavior ticking with one call.



    The result is you have a separate place to decide what connects to what and a different place to manage what says what to whatever.



    Try that on something you have to maintain over time and see if it doesn't help.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 11 hours ago

























    answered yesterday









    candied_orange

    49.4k1686173




    49.4k1686173












    • I was ready to upvote this until I got to the last three paragraphs, which come across as a bit patronising, or maybe just pessimistic. It's like you're assuming that the reader will ignore everything you've just said, and defensively responding to comments that haven't been made yet.
      – IMSoP
      15 hours ago










    • @IMSoP Better now?
      – candied_orange
      11 hours ago


















    • I was ready to upvote this until I got to the last three paragraphs, which come across as a bit patronising, or maybe just pessimistic. It's like you're assuming that the reader will ignore everything you've just said, and defensively responding to comments that haven't been made yet.
      – IMSoP
      15 hours ago










    • @IMSoP Better now?
      – candied_orange
      11 hours ago
















    I was ready to upvote this until I got to the last three paragraphs, which come across as a bit patronising, or maybe just pessimistic. It's like you're assuming that the reader will ignore everything you've just said, and defensively responding to comments that haven't been made yet.
    – IMSoP
    15 hours ago




    I was ready to upvote this until I got to the last three paragraphs, which come across as a bit patronising, or maybe just pessimistic. It's like you're assuming that the reader will ignore everything you've just said, and defensively responding to comments that haven't been made yet.
    – IMSoP
    15 hours ago












    @IMSoP Better now?
    – candied_orange
    11 hours ago




    @IMSoP Better now?
    – candied_orange
    11 hours ago










    up vote
    1
    down vote













    As a customer, when you hire a mechanic to do something to your car, do you expect that mechanic to build a car from scratch only to then work with it? No, you give the mechanic the car you want them to work on.



    As the garage owner, when you instruct a mechanic to do something to a car, do you expect the mechanic to create his own screwdriver/wrench/car parts? No, you provide the mechanic with the parts/tools he needs to use



    Why do we do this? Well, think about it. You're a garage owner who wants to hire someone to become your mechanic. You will teach them to be a mechanic (= you will write the code).



    What's going to be easier:




    • Teach a mechanic how to attach a spoiler to a car using a screwdriver.

    • Teach a mechanic to create a car, create a spoiler, created a screwdriver
      and then attach the newly created spoiler to the newly created car with the newly created screwdriver.


    There are massive benefits to not having your mechanic create everything from scratch:




    • Obviously, training (= development) is dramatically shortened if you just supply your mechanic with existing tools and parts.

    • If the same mechanic has to perform the same job multiple times, you can make sure he reuses the screwdriver instead of always throwing the old one out and creating a new one.

    • Additionally, a mechanic who has learned to create everything will need to be much more of an expert, and thus will expect a higher wage. The coding analogy here is that a class with many responsibilities is much harder to maintain than a class with a single strictly defined responsibility.

    • Additionally, when new inventions hit the market and spoilers are now being made from carbon instead of plastic; you will have to retrain (= redevelop) your expert mechanic. But your "simple" mechanic won't have to be retrained as long as the spoiler can still be attached in the same way.

    • Having a mechanic who doesn't rely on a car that they've built themselves means that you have a mechanic who is able to handle any car they may receive. Including cars that didn't even exist yet at the time of training the mechanic. However, your expert mechanic will not be able to build newer cars that have been created after their training.


    If you hire and train the expert mechanic, you're going to end up with an employee who costs more, takes more time to perform what ought to be a simple job, and will perpetually need to be retrained whenever one of their many responsibilities need to be updated.



    The development analogy is that if you use classes with hardcoded dependencies, then you're going to end up with hard to maintain classes which will need continual redevelopment/changes whenever a new version of the object (Settings in your case) is created, and you'll have to develop internal logic for the class to have the ability to create different types of Settings objects.



    Furthermore, whoever consumes your class is now also going to have to ask the class to create the correct Settings object, as opposed to simply being able to pass the class any Settings object it wishes to pass. This means additional development for the consumer to figure out how to ask the class to create the right tool.





    Yes, dependency inversion takes a bit more effort to write instead of hardcoding the dependency. Yes, it's annoying to have to type more.



    But that is the same argument as choosing to hardcode literal values because "declaring variables takes more effort". Technically correct, but the pro's outweigh the cons by several orders of magnitude.



    The benefit of dependency inversion is not experienced when you create the first version of the application. The benefit of dependency inversion is experienced when you need to change or extend that initial version. And don't trick yourself into thinking that you will get it right the first time and won't need to extend/change the code. You will have to change things.






    does this affect performance as a whole?




    This does not affect runtime performance of the application. But it massively impacts the development time (and therefore performance) of the developer.






    share|improve this answer



















    • 2




      If you removed your comment, "As a minor comment, your question focuses on dependency inversion, not dependency injection. Injection is one way to do inversion, but it's not the only way.", this would be an excellent answer. Dependency inversion can be achieved via either injection or locator/globals. The question's examples relate to injection. So the question is about dependency injection (as well as dependency inversion).
      – David Arno
      yesterday






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      yesterday






    • 3




      @Flater, part of the problem is no one really seems to agree on what the difference between dependency injection, dependency inversion and inversion of control are. One thing is for certain though, a "container" most certainly isn't needed to inject a dependency into a method or constructor. Pure (or poor man's) DI specifically describes manual dependency injection. It's the only dependency injection I personally use as I dislike the "magic" associated with containers.
      – David Arno
      yesterday






    • 1




      Your mechanic analogy is poor even as an analogy. If I have a mechanic trained how to fix cars, he can fix most varieties but if I come to him with a EV instead, he's likely to have no clue what to do with it. DI does not fix the polymorphic problem, all it does is help with coupling - ie how to get the car and mechanic together. A better analogy is a mechanic working for a dealer who only fixed 1 brand of car going independent and fixing other brands of car.
      – gbjbaanb
      17 hours ago






    • 1




      @gbjbaanb I think the analogy can be extended naturally to the EV example: the mechanic specifies constraints on the cars he accepts; in an OO language, that would be represented as the interface the dependency must implement. In the simple example, the constraint is "any car", but in reality it would be "any car with an internal combustion engine", or some more specific description; an EV car wouldn't meet that constraint, so wouldn't be accepted. In OO terms, NissanLeaf would be a new class that implemented an EVCar interface, but didn't implement the InternalCombustionCar interface.
      – IMSoP
      15 hours ago

















    up vote
    1
    down vote













    As a customer, when you hire a mechanic to do something to your car, do you expect that mechanic to build a car from scratch only to then work with it? No, you give the mechanic the car you want them to work on.



    As the garage owner, when you instruct a mechanic to do something to a car, do you expect the mechanic to create his own screwdriver/wrench/car parts? No, you provide the mechanic with the parts/tools he needs to use



    Why do we do this? Well, think about it. You're a garage owner who wants to hire someone to become your mechanic. You will teach them to be a mechanic (= you will write the code).



    What's going to be easier:




    • Teach a mechanic how to attach a spoiler to a car using a screwdriver.

    • Teach a mechanic to create a car, create a spoiler, created a screwdriver
      and then attach the newly created spoiler to the newly created car with the newly created screwdriver.


    There are massive benefits to not having your mechanic create everything from scratch:




    • Obviously, training (= development) is dramatically shortened if you just supply your mechanic with existing tools and parts.

    • If the same mechanic has to perform the same job multiple times, you can make sure he reuses the screwdriver instead of always throwing the old one out and creating a new one.

    • Additionally, a mechanic who has learned to create everything will need to be much more of an expert, and thus will expect a higher wage. The coding analogy here is that a class with many responsibilities is much harder to maintain than a class with a single strictly defined responsibility.

    • Additionally, when new inventions hit the market and spoilers are now being made from carbon instead of plastic; you will have to retrain (= redevelop) your expert mechanic. But your "simple" mechanic won't have to be retrained as long as the spoiler can still be attached in the same way.

    • Having a mechanic who doesn't rely on a car that they've built themselves means that you have a mechanic who is able to handle any car they may receive. Including cars that didn't even exist yet at the time of training the mechanic. However, your expert mechanic will not be able to build newer cars that have been created after their training.


    If you hire and train the expert mechanic, you're going to end up with an employee who costs more, takes more time to perform what ought to be a simple job, and will perpetually need to be retrained whenever one of their many responsibilities need to be updated.



    The development analogy is that if you use classes with hardcoded dependencies, then you're going to end up with hard to maintain classes which will need continual redevelopment/changes whenever a new version of the object (Settings in your case) is created, and you'll have to develop internal logic for the class to have the ability to create different types of Settings objects.



    Furthermore, whoever consumes your class is now also going to have to ask the class to create the correct Settings object, as opposed to simply being able to pass the class any Settings object it wishes to pass. This means additional development for the consumer to figure out how to ask the class to create the right tool.





    Yes, dependency inversion takes a bit more effort to write instead of hardcoding the dependency. Yes, it's annoying to have to type more.



    But that is the same argument as choosing to hardcode literal values because "declaring variables takes more effort". Technically correct, but the pro's outweigh the cons by several orders of magnitude.



    The benefit of dependency inversion is not experienced when you create the first version of the application. The benefit of dependency inversion is experienced when you need to change or extend that initial version. And don't trick yourself into thinking that you will get it right the first time and won't need to extend/change the code. You will have to change things.






    does this affect performance as a whole?




    This does not affect runtime performance of the application. But it massively impacts the development time (and therefore performance) of the developer.






    share|improve this answer



















    • 2




      If you removed your comment, "As a minor comment, your question focuses on dependency inversion, not dependency injection. Injection is one way to do inversion, but it's not the only way.", this would be an excellent answer. Dependency inversion can be achieved via either injection or locator/globals. The question's examples relate to injection. So the question is about dependency injection (as well as dependency inversion).
      – David Arno
      yesterday






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      yesterday






    • 3




      @Flater, part of the problem is no one really seems to agree on what the difference between dependency injection, dependency inversion and inversion of control are. One thing is for certain though, a "container" most certainly isn't needed to inject a dependency into a method or constructor. Pure (or poor man's) DI specifically describes manual dependency injection. It's the only dependency injection I personally use as I dislike the "magic" associated with containers.
      – David Arno
      yesterday






    • 1




      Your mechanic analogy is poor even as an analogy. If I have a mechanic trained how to fix cars, he can fix most varieties but if I come to him with a EV instead, he's likely to have no clue what to do with it. DI does not fix the polymorphic problem, all it does is help with coupling - ie how to get the car and mechanic together. A better analogy is a mechanic working for a dealer who only fixed 1 brand of car going independent and fixing other brands of car.
      – gbjbaanb
      17 hours ago






    • 1




      @gbjbaanb I think the analogy can be extended naturally to the EV example: the mechanic specifies constraints on the cars he accepts; in an OO language, that would be represented as the interface the dependency must implement. In the simple example, the constraint is "any car", but in reality it would be "any car with an internal combustion engine", or some more specific description; an EV car wouldn't meet that constraint, so wouldn't be accepted. In OO terms, NissanLeaf would be a new class that implemented an EVCar interface, but didn't implement the InternalCombustionCar interface.
      – IMSoP
      15 hours ago















    up vote
    1
    down vote










    up vote
    1
    down vote









    As a customer, when you hire a mechanic to do something to your car, do you expect that mechanic to build a car from scratch only to then work with it? No, you give the mechanic the car you want them to work on.



    As the garage owner, when you instruct a mechanic to do something to a car, do you expect the mechanic to create his own screwdriver/wrench/car parts? No, you provide the mechanic with the parts/tools he needs to use



    Why do we do this? Well, think about it. You're a garage owner who wants to hire someone to become your mechanic. You will teach them to be a mechanic (= you will write the code).



    What's going to be easier:




    • Teach a mechanic how to attach a spoiler to a car using a screwdriver.

    • Teach a mechanic to create a car, create a spoiler, created a screwdriver
      and then attach the newly created spoiler to the newly created car with the newly created screwdriver.


    There are massive benefits to not having your mechanic create everything from scratch:




    • Obviously, training (= development) is dramatically shortened if you just supply your mechanic with existing tools and parts.

    • If the same mechanic has to perform the same job multiple times, you can make sure he reuses the screwdriver instead of always throwing the old one out and creating a new one.

    • Additionally, a mechanic who has learned to create everything will need to be much more of an expert, and thus will expect a higher wage. The coding analogy here is that a class with many responsibilities is much harder to maintain than a class with a single strictly defined responsibility.

    • Additionally, when new inventions hit the market and spoilers are now being made from carbon instead of plastic; you will have to retrain (= redevelop) your expert mechanic. But your "simple" mechanic won't have to be retrained as long as the spoiler can still be attached in the same way.

    • Having a mechanic who doesn't rely on a car that they've built themselves means that you have a mechanic who is able to handle any car they may receive. Including cars that didn't even exist yet at the time of training the mechanic. However, your expert mechanic will not be able to build newer cars that have been created after their training.


    If you hire and train the expert mechanic, you're going to end up with an employee who costs more, takes more time to perform what ought to be a simple job, and will perpetually need to be retrained whenever one of their many responsibilities need to be updated.



    The development analogy is that if you use classes with hardcoded dependencies, then you're going to end up with hard to maintain classes which will need continual redevelopment/changes whenever a new version of the object (Settings in your case) is created, and you'll have to develop internal logic for the class to have the ability to create different types of Settings objects.



    Furthermore, whoever consumes your class is now also going to have to ask the class to create the correct Settings object, as opposed to simply being able to pass the class any Settings object it wishes to pass. This means additional development for the consumer to figure out how to ask the class to create the right tool.





    Yes, dependency inversion takes a bit more effort to write instead of hardcoding the dependency. Yes, it's annoying to have to type more.



    But that is the same argument as choosing to hardcode literal values because "declaring variables takes more effort". Technically correct, but the pro's outweigh the cons by several orders of magnitude.



    The benefit of dependency inversion is not experienced when you create the first version of the application. The benefit of dependency inversion is experienced when you need to change or extend that initial version. And don't trick yourself into thinking that you will get it right the first time and won't need to extend/change the code. You will have to change things.






    does this affect performance as a whole?




    This does not affect runtime performance of the application. But it massively impacts the development time (and therefore performance) of the developer.






    share|improve this answer














    As a customer, when you hire a mechanic to do something to your car, do you expect that mechanic to build a car from scratch only to then work with it? No, you give the mechanic the car you want them to work on.



    As the garage owner, when you instruct a mechanic to do something to a car, do you expect the mechanic to create his own screwdriver/wrench/car parts? No, you provide the mechanic with the parts/tools he needs to use



    Why do we do this? Well, think about it. You're a garage owner who wants to hire someone to become your mechanic. You will teach them to be a mechanic (= you will write the code).



    What's going to be easier:




    • Teach a mechanic how to attach a spoiler to a car using a screwdriver.

    • Teach a mechanic to create a car, create a spoiler, created a screwdriver
      and then attach the newly created spoiler to the newly created car with the newly created screwdriver.


    There are massive benefits to not having your mechanic create everything from scratch:




    • Obviously, training (= development) is dramatically shortened if you just supply your mechanic with existing tools and parts.

    • If the same mechanic has to perform the same job multiple times, you can make sure he reuses the screwdriver instead of always throwing the old one out and creating a new one.

    • Additionally, a mechanic who has learned to create everything will need to be much more of an expert, and thus will expect a higher wage. The coding analogy here is that a class with many responsibilities is much harder to maintain than a class with a single strictly defined responsibility.

    • Additionally, when new inventions hit the market and spoilers are now being made from carbon instead of plastic; you will have to retrain (= redevelop) your expert mechanic. But your "simple" mechanic won't have to be retrained as long as the spoiler can still be attached in the same way.

    • Having a mechanic who doesn't rely on a car that they've built themselves means that you have a mechanic who is able to handle any car they may receive. Including cars that didn't even exist yet at the time of training the mechanic. However, your expert mechanic will not be able to build newer cars that have been created after their training.


    If you hire and train the expert mechanic, you're going to end up with an employee who costs more, takes more time to perform what ought to be a simple job, and will perpetually need to be retrained whenever one of their many responsibilities need to be updated.



    The development analogy is that if you use classes with hardcoded dependencies, then you're going to end up with hard to maintain classes which will need continual redevelopment/changes whenever a new version of the object (Settings in your case) is created, and you'll have to develop internal logic for the class to have the ability to create different types of Settings objects.



    Furthermore, whoever consumes your class is now also going to have to ask the class to create the correct Settings object, as opposed to simply being able to pass the class any Settings object it wishes to pass. This means additional development for the consumer to figure out how to ask the class to create the right tool.





    Yes, dependency inversion takes a bit more effort to write instead of hardcoding the dependency. Yes, it's annoying to have to type more.



    But that is the same argument as choosing to hardcode literal values because "declaring variables takes more effort". Technically correct, but the pro's outweigh the cons by several orders of magnitude.



    The benefit of dependency inversion is not experienced when you create the first version of the application. The benefit of dependency inversion is experienced when you need to change or extend that initial version. And don't trick yourself into thinking that you will get it right the first time and won't need to extend/change the code. You will have to change things.






    does this affect performance as a whole?




    This does not affect runtime performance of the application. But it massively impacts the development time (and therefore performance) of the developer.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited yesterday

























    answered yesterday









    Flater

    5,27511019




    5,27511019








    • 2




      If you removed your comment, "As a minor comment, your question focuses on dependency inversion, not dependency injection. Injection is one way to do inversion, but it's not the only way.", this would be an excellent answer. Dependency inversion can be achieved via either injection or locator/globals. The question's examples relate to injection. So the question is about dependency injection (as well as dependency inversion).
      – David Arno
      yesterday






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      yesterday






    • 3




      @Flater, part of the problem is no one really seems to agree on what the difference between dependency injection, dependency inversion and inversion of control are. One thing is for certain though, a "container" most certainly isn't needed to inject a dependency into a method or constructor. Pure (or poor man's) DI specifically describes manual dependency injection. It's the only dependency injection I personally use as I dislike the "magic" associated with containers.
      – David Arno
      yesterday






    • 1




      Your mechanic analogy is poor even as an analogy. If I have a mechanic trained how to fix cars, he can fix most varieties but if I come to him with a EV instead, he's likely to have no clue what to do with it. DI does not fix the polymorphic problem, all it does is help with coupling - ie how to get the car and mechanic together. A better analogy is a mechanic working for a dealer who only fixed 1 brand of car going independent and fixing other brands of car.
      – gbjbaanb
      17 hours ago






    • 1




      @gbjbaanb I think the analogy can be extended naturally to the EV example: the mechanic specifies constraints on the cars he accepts; in an OO language, that would be represented as the interface the dependency must implement. In the simple example, the constraint is "any car", but in reality it would be "any car with an internal combustion engine", or some more specific description; an EV car wouldn't meet that constraint, so wouldn't be accepted. In OO terms, NissanLeaf would be a new class that implemented an EVCar interface, but didn't implement the InternalCombustionCar interface.
      – IMSoP
      15 hours ago
















    • 2




      If you removed your comment, "As a minor comment, your question focuses on dependency inversion, not dependency injection. Injection is one way to do inversion, but it's not the only way.", this would be an excellent answer. Dependency inversion can be achieved via either injection or locator/globals. The question's examples relate to injection. So the question is about dependency injection (as well as dependency inversion).
      – David Arno
      yesterday






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      yesterday






    • 3




      @Flater, part of the problem is no one really seems to agree on what the difference between dependency injection, dependency inversion and inversion of control are. One thing is for certain though, a "container" most certainly isn't needed to inject a dependency into a method or constructor. Pure (or poor man's) DI specifically describes manual dependency injection. It's the only dependency injection I personally use as I dislike the "magic" associated with containers.
      – David Arno
      yesterday






    • 1




      Your mechanic analogy is poor even as an analogy. If I have a mechanic trained how to fix cars, he can fix most varieties but if I come to him with a EV instead, he's likely to have no clue what to do with it. DI does not fix the polymorphic problem, all it does is help with coupling - ie how to get the car and mechanic together. A better analogy is a mechanic working for a dealer who only fixed 1 brand of car going independent and fixing other brands of car.
      – gbjbaanb
      17 hours ago






    • 1




      @gbjbaanb I think the analogy can be extended naturally to the EV example: the mechanic specifies constraints on the cars he accepts; in an OO language, that would be represented as the interface the dependency must implement. In the simple example, the constraint is "any car", but in reality it would be "any car with an internal combustion engine", or some more specific description; an EV car wouldn't meet that constraint, so wouldn't be accepted. In OO terms, NissanLeaf would be a new class that implemented an EVCar interface, but didn't implement the InternalCombustionCar interface.
      – IMSoP
      15 hours ago










    2




    2




    If you removed your comment, "As a minor comment, your question focuses on dependency inversion, not dependency injection. Injection is one way to do inversion, but it's not the only way.", this would be an excellent answer. Dependency inversion can be achieved via either injection or locator/globals. The question's examples relate to injection. So the question is about dependency injection (as well as dependency inversion).
    – David Arno
    yesterday




    If you removed your comment, "As a minor comment, your question focuses on dependency inversion, not dependency injection. Injection is one way to do inversion, but it's not the only way.", this would be an excellent answer. Dependency inversion can be achieved via either injection or locator/globals. The question's examples relate to injection. So the question is about dependency injection (as well as dependency inversion).
    – David Arno
    yesterday




    11




    11




    I think the whole car thing is a bit belaboured and confusing
    – Ewan
    yesterday




    I think the whole car thing is a bit belaboured and confusing
    – Ewan
    yesterday




    3




    3




    @Flater, part of the problem is no one really seems to agree on what the difference between dependency injection, dependency inversion and inversion of control are. One thing is for certain though, a "container" most certainly isn't needed to inject a dependency into a method or constructor. Pure (or poor man's) DI specifically describes manual dependency injection. It's the only dependency injection I personally use as I dislike the "magic" associated with containers.
    – David Arno
    yesterday




    @Flater, part of the problem is no one really seems to agree on what the difference between dependency injection, dependency inversion and inversion of control are. One thing is for certain though, a "container" most certainly isn't needed to inject a dependency into a method or constructor. Pure (or poor man's) DI specifically describes manual dependency injection. It's the only dependency injection I personally use as I dislike the "magic" associated with containers.
    – David Arno
    yesterday




    1




    1




    Your mechanic analogy is poor even as an analogy. If I have a mechanic trained how to fix cars, he can fix most varieties but if I come to him with a EV instead, he's likely to have no clue what to do with it. DI does not fix the polymorphic problem, all it does is help with coupling - ie how to get the car and mechanic together. A better analogy is a mechanic working for a dealer who only fixed 1 brand of car going independent and fixing other brands of car.
    – gbjbaanb
    17 hours ago




    Your mechanic analogy is poor even as an analogy. If I have a mechanic trained how to fix cars, he can fix most varieties but if I come to him with a EV instead, he's likely to have no clue what to do with it. DI does not fix the polymorphic problem, all it does is help with coupling - ie how to get the car and mechanic together. A better analogy is a mechanic working for a dealer who only fixed 1 brand of car going independent and fixing other brands of car.
    – gbjbaanb
    17 hours ago




    1




    1




    @gbjbaanb I think the analogy can be extended naturally to the EV example: the mechanic specifies constraints on the cars he accepts; in an OO language, that would be represented as the interface the dependency must implement. In the simple example, the constraint is "any car", but in reality it would be "any car with an internal combustion engine", or some more specific description; an EV car wouldn't meet that constraint, so wouldn't be accepted. In OO terms, NissanLeaf would be a new class that implemented an EVCar interface, but didn't implement the InternalCombustionCar interface.
    – IMSoP
    15 hours ago






    @gbjbaanb I think the analogy can be extended naturally to the EV example: the mechanic specifies constraints on the cars he accepts; in an OO language, that would be represented as the interface the dependency must implement. In the simple example, the constraint is "any car", but in reality it would be "any car with an internal combustion engine", or some more specific description; an EV car wouldn't meet that constraint, so wouldn't be accepted. In OO terms, NissanLeaf would be a new class that implemented an EVCar interface, but didn't implement the InternalCombustionCar interface.
    – IMSoP
    15 hours ago












    up vote
    0
    down vote













    You should use techniques to solve the problems they're good at solving when you have those problems. Dependency inversion and injection are no different.



    Dependency inversion or injection is a technique that allows your code to decide on what implementation of a method gets called at run time. This maximizes the benefits of late binding. The technique is necessary when the language does not support run time replacement of non-instance functions. For example, Java lacks a mechanism to replace calls to a static method with calls to a different implementation; contrast with Python, where all that's necessary to replace the function call is to bind the name to a different function (reassign the variable holding the function).



    Why would we want to vary the implementation of the function? There's a two main reasons:




    • We want to use fakes for testing purposes. This allows us to test a class that depends on a database fetch without actually connecting to the database.

    • We need to support multiple implementations. For example, we might need to set up a system that supports both MySQL and PostgreSQL databases.


    You may also want to take note of inversion of control containers. This is a technique that is intended to help you avoid huge, tangled construction trees that look like this pseudocode:



    thing5 =  new MyThing5();
    thing3 = new MyThing3(thing5, new MyThing10());

    myApp = new MyApp(
    new MyAppDependency1(thing5, thing3),
    new MyAppDependency2(
    new Thing1(),
    new Thing2(new Thing3(thing5, new Thing4(thing5)))
    ),
    ...
    new MyAppDependency15(thing5)
    );


    It lets you register your classes and then does the construction for you:



    injector.register(Thing1); // Yes, you'd need some kind of actual class reference.
    injector.register(Thing2);
    ...
    injector.register(MyAppDepdency15);
    injector.register(MyApp);

    myApp = injector.create(MyApp); // The injector fills in all the construction parameters.


    Note that it's simplest if the classes registered can be stateless singletons.



    Word of caution



    Note that dependency inversion should not be your go-to answer for decoupling logic. Look for opportunities to use parameterization instead. Consider this pseudocode method for example:



    myAverageAboveMin()
    {
    dbConn = new DbConnection("my connection string");
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", 5);
    dbQuery.Execute();
    myData = dbQuery.getAll();
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    We could use dependency inversion for some parts of this method:



    class MyQuerier
    {
    private _dbConn;

    MyQueries(dbConn) { this._dbConn = dbConn; }

    fetchAboveMin(min)
    {
    dbQuery = this._dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    private _querier;

    Averager(querier) { this._querier = querier; }

    myAverageAboveMin(min)
    {
    myData = this._querier.fetchAboveMin(min);
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    But we shouldn't, at least not completely. Notice that we've created a stateful class with Querier. It now holds a reference to some essentially global connection object. This creates problems such as difficulty in understanding the overall state of the program and how different classes coordinate with each other. Notice also that we're forced to fake out the querier or the connection if we want to test the averaging logic. Further A better approach would be to increase parameterization:



    class MyQuerier
    {
    fetchAboveMin(dbConn, min)
    {
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    averageData(myData)
    {
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }

    class StuffDoer
    {
    private _querier;
    private _averager;

    StuffDoer(querier, averager)
    {
    this._querier = querier;
    this._averager = averager;
    }

    myAverageAboveMin(dbConn, min)
    {
    myData = this._querier.fetchAboveMin(dbConn, min);
    return this._averager.averageData(myData);
    }
    }


    And the connection would be managed at some even higher level that's responsible for the operation as a whole and knows what to do with this output.



    Now we can test the averaging logic completely independently of the querying, and what's more we can use it in a wider variety of situations. We might question whether we even need the MyQuerier and Averager objects, and maybe the answer is that we don't if we don't intend to unit test StuffDoer, and not unit testing StuffDoer would be perfectly reasonable since it's so tightly coupled to the database. It might make more sense to just let integration tests cover it. In that case, we might be fine making fetchAboveMin and averageData into static methods.






    share|improve this answer



















    • 1




      "Dependency injection is a technique that is intended to help you avoid huge, tangled construction trees...". Your first example after this claim is an example of pure, or poor man's, dependency injection. The second is an example of using an IoC container to "automate" the injection of those dependencies. Both are examples of dependency injection in action.
      – David Arno
      yesterday










    • @DavidArno Yeah, you're right. I've adjusted the terminology.
      – jpmc26
      yesterday










    • There's a third main reason to vary the implementation, or at least design the code assuming that the implementation can vary: it incentivizes developer to have loose coupling and avoid writing code that will be hard to change should a new implementation be implemented at some time in the future. And while that may not be a priority in some projects (e.g. knowing that the application will never be revisited after its initial release), it will be in others (e.g. where the company business model specifically tries to offer extended support/extension of their applications).
      – Flater
      2 hours ago















    up vote
    0
    down vote













    You should use techniques to solve the problems they're good at solving when you have those problems. Dependency inversion and injection are no different.



    Dependency inversion or injection is a technique that allows your code to decide on what implementation of a method gets called at run time. This maximizes the benefits of late binding. The technique is necessary when the language does not support run time replacement of non-instance functions. For example, Java lacks a mechanism to replace calls to a static method with calls to a different implementation; contrast with Python, where all that's necessary to replace the function call is to bind the name to a different function (reassign the variable holding the function).



    Why would we want to vary the implementation of the function? There's a two main reasons:




    • We want to use fakes for testing purposes. This allows us to test a class that depends on a database fetch without actually connecting to the database.

    • We need to support multiple implementations. For example, we might need to set up a system that supports both MySQL and PostgreSQL databases.


    You may also want to take note of inversion of control containers. This is a technique that is intended to help you avoid huge, tangled construction trees that look like this pseudocode:



    thing5 =  new MyThing5();
    thing3 = new MyThing3(thing5, new MyThing10());

    myApp = new MyApp(
    new MyAppDependency1(thing5, thing3),
    new MyAppDependency2(
    new Thing1(),
    new Thing2(new Thing3(thing5, new Thing4(thing5)))
    ),
    ...
    new MyAppDependency15(thing5)
    );


    It lets you register your classes and then does the construction for you:



    injector.register(Thing1); // Yes, you'd need some kind of actual class reference.
    injector.register(Thing2);
    ...
    injector.register(MyAppDepdency15);
    injector.register(MyApp);

    myApp = injector.create(MyApp); // The injector fills in all the construction parameters.


    Note that it's simplest if the classes registered can be stateless singletons.



    Word of caution



    Note that dependency inversion should not be your go-to answer for decoupling logic. Look for opportunities to use parameterization instead. Consider this pseudocode method for example:



    myAverageAboveMin()
    {
    dbConn = new DbConnection("my connection string");
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", 5);
    dbQuery.Execute();
    myData = dbQuery.getAll();
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    We could use dependency inversion for some parts of this method:



    class MyQuerier
    {
    private _dbConn;

    MyQueries(dbConn) { this._dbConn = dbConn; }

    fetchAboveMin(min)
    {
    dbQuery = this._dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    private _querier;

    Averager(querier) { this._querier = querier; }

    myAverageAboveMin(min)
    {
    myData = this._querier.fetchAboveMin(min);
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    But we shouldn't, at least not completely. Notice that we've created a stateful class with Querier. It now holds a reference to some essentially global connection object. This creates problems such as difficulty in understanding the overall state of the program and how different classes coordinate with each other. Notice also that we're forced to fake out the querier or the connection if we want to test the averaging logic. Further A better approach would be to increase parameterization:



    class MyQuerier
    {
    fetchAboveMin(dbConn, min)
    {
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    averageData(myData)
    {
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }

    class StuffDoer
    {
    private _querier;
    private _averager;

    StuffDoer(querier, averager)
    {
    this._querier = querier;
    this._averager = averager;
    }

    myAverageAboveMin(dbConn, min)
    {
    myData = this._querier.fetchAboveMin(dbConn, min);
    return this._averager.averageData(myData);
    }
    }


    And the connection would be managed at some even higher level that's responsible for the operation as a whole and knows what to do with this output.



    Now we can test the averaging logic completely independently of the querying, and what's more we can use it in a wider variety of situations. We might question whether we even need the MyQuerier and Averager objects, and maybe the answer is that we don't if we don't intend to unit test StuffDoer, and not unit testing StuffDoer would be perfectly reasonable since it's so tightly coupled to the database. It might make more sense to just let integration tests cover it. In that case, we might be fine making fetchAboveMin and averageData into static methods.






    share|improve this answer



















    • 1




      "Dependency injection is a technique that is intended to help you avoid huge, tangled construction trees...". Your first example after this claim is an example of pure, or poor man's, dependency injection. The second is an example of using an IoC container to "automate" the injection of those dependencies. Both are examples of dependency injection in action.
      – David Arno
      yesterday










    • @DavidArno Yeah, you're right. I've adjusted the terminology.
      – jpmc26
      yesterday










    • There's a third main reason to vary the implementation, or at least design the code assuming that the implementation can vary: it incentivizes developer to have loose coupling and avoid writing code that will be hard to change should a new implementation be implemented at some time in the future. And while that may not be a priority in some projects (e.g. knowing that the application will never be revisited after its initial release), it will be in others (e.g. where the company business model specifically tries to offer extended support/extension of their applications).
      – Flater
      2 hours ago













    up vote
    0
    down vote










    up vote
    0
    down vote









    You should use techniques to solve the problems they're good at solving when you have those problems. Dependency inversion and injection are no different.



    Dependency inversion or injection is a technique that allows your code to decide on what implementation of a method gets called at run time. This maximizes the benefits of late binding. The technique is necessary when the language does not support run time replacement of non-instance functions. For example, Java lacks a mechanism to replace calls to a static method with calls to a different implementation; contrast with Python, where all that's necessary to replace the function call is to bind the name to a different function (reassign the variable holding the function).



    Why would we want to vary the implementation of the function? There's a two main reasons:




    • We want to use fakes for testing purposes. This allows us to test a class that depends on a database fetch without actually connecting to the database.

    • We need to support multiple implementations. For example, we might need to set up a system that supports both MySQL and PostgreSQL databases.


    You may also want to take note of inversion of control containers. This is a technique that is intended to help you avoid huge, tangled construction trees that look like this pseudocode:



    thing5 =  new MyThing5();
    thing3 = new MyThing3(thing5, new MyThing10());

    myApp = new MyApp(
    new MyAppDependency1(thing5, thing3),
    new MyAppDependency2(
    new Thing1(),
    new Thing2(new Thing3(thing5, new Thing4(thing5)))
    ),
    ...
    new MyAppDependency15(thing5)
    );


    It lets you register your classes and then does the construction for you:



    injector.register(Thing1); // Yes, you'd need some kind of actual class reference.
    injector.register(Thing2);
    ...
    injector.register(MyAppDepdency15);
    injector.register(MyApp);

    myApp = injector.create(MyApp); // The injector fills in all the construction parameters.


    Note that it's simplest if the classes registered can be stateless singletons.



    Word of caution



    Note that dependency inversion should not be your go-to answer for decoupling logic. Look for opportunities to use parameterization instead. Consider this pseudocode method for example:



    myAverageAboveMin()
    {
    dbConn = new DbConnection("my connection string");
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", 5);
    dbQuery.Execute();
    myData = dbQuery.getAll();
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    We could use dependency inversion for some parts of this method:



    class MyQuerier
    {
    private _dbConn;

    MyQueries(dbConn) { this._dbConn = dbConn; }

    fetchAboveMin(min)
    {
    dbQuery = this._dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    private _querier;

    Averager(querier) { this._querier = querier; }

    myAverageAboveMin(min)
    {
    myData = this._querier.fetchAboveMin(min);
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    But we shouldn't, at least not completely. Notice that we've created a stateful class with Querier. It now holds a reference to some essentially global connection object. This creates problems such as difficulty in understanding the overall state of the program and how different classes coordinate with each other. Notice also that we're forced to fake out the querier or the connection if we want to test the averaging logic. Further A better approach would be to increase parameterization:



    class MyQuerier
    {
    fetchAboveMin(dbConn, min)
    {
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    averageData(myData)
    {
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }

    class StuffDoer
    {
    private _querier;
    private _averager;

    StuffDoer(querier, averager)
    {
    this._querier = querier;
    this._averager = averager;
    }

    myAverageAboveMin(dbConn, min)
    {
    myData = this._querier.fetchAboveMin(dbConn, min);
    return this._averager.averageData(myData);
    }
    }


    And the connection would be managed at some even higher level that's responsible for the operation as a whole and knows what to do with this output.



    Now we can test the averaging logic completely independently of the querying, and what's more we can use it in a wider variety of situations. We might question whether we even need the MyQuerier and Averager objects, and maybe the answer is that we don't if we don't intend to unit test StuffDoer, and not unit testing StuffDoer would be perfectly reasonable since it's so tightly coupled to the database. It might make more sense to just let integration tests cover it. In that case, we might be fine making fetchAboveMin and averageData into static methods.






    share|improve this answer














    You should use techniques to solve the problems they're good at solving when you have those problems. Dependency inversion and injection are no different.



    Dependency inversion or injection is a technique that allows your code to decide on what implementation of a method gets called at run time. This maximizes the benefits of late binding. The technique is necessary when the language does not support run time replacement of non-instance functions. For example, Java lacks a mechanism to replace calls to a static method with calls to a different implementation; contrast with Python, where all that's necessary to replace the function call is to bind the name to a different function (reassign the variable holding the function).



    Why would we want to vary the implementation of the function? There's a two main reasons:




    • We want to use fakes for testing purposes. This allows us to test a class that depends on a database fetch without actually connecting to the database.

    • We need to support multiple implementations. For example, we might need to set up a system that supports both MySQL and PostgreSQL databases.


    You may also want to take note of inversion of control containers. This is a technique that is intended to help you avoid huge, tangled construction trees that look like this pseudocode:



    thing5 =  new MyThing5();
    thing3 = new MyThing3(thing5, new MyThing10());

    myApp = new MyApp(
    new MyAppDependency1(thing5, thing3),
    new MyAppDependency2(
    new Thing1(),
    new Thing2(new Thing3(thing5, new Thing4(thing5)))
    ),
    ...
    new MyAppDependency15(thing5)
    );


    It lets you register your classes and then does the construction for you:



    injector.register(Thing1); // Yes, you'd need some kind of actual class reference.
    injector.register(Thing2);
    ...
    injector.register(MyAppDepdency15);
    injector.register(MyApp);

    myApp = injector.create(MyApp); // The injector fills in all the construction parameters.


    Note that it's simplest if the classes registered can be stateless singletons.



    Word of caution



    Note that dependency inversion should not be your go-to answer for decoupling logic. Look for opportunities to use parameterization instead. Consider this pseudocode method for example:



    myAverageAboveMin()
    {
    dbConn = new DbConnection("my connection string");
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", 5);
    dbQuery.Execute();
    myData = dbQuery.getAll();
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    We could use dependency inversion for some parts of this method:



    class MyQuerier
    {
    private _dbConn;

    MyQueries(dbConn) { this._dbConn = dbConn; }

    fetchAboveMin(min)
    {
    dbQuery = this._dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    private _querier;

    Averager(querier) { this._querier = querier; }

    myAverageAboveMin(min)
    {
    myData = this._querier.fetchAboveMin(min);
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }


    But we shouldn't, at least not completely. Notice that we've created a stateful class with Querier. It now holds a reference to some essentially global connection object. This creates problems such as difficulty in understanding the overall state of the program and how different classes coordinate with each other. Notice also that we're forced to fake out the querier or the connection if we want to test the averaging logic. Further A better approach would be to increase parameterization:



    class MyQuerier
    {
    fetchAboveMin(dbConn, min)
    {
    dbQuery = dbConn.makeQuery();
    dbQuery.Command = "SELECT * FROM MY_DATA WHERE x > :min";
    dbQuery.setParam("min", min);
    dbQuery.Execute();
    return dbQuery.getAll();
    }
    }


    class Averager
    {
    averageData(myData)
    {
    count = 0;
    total = 0;
    foreach (row in myData)
    {
    count++;
    total += row.x;
    }

    return total / count;
    }

    class StuffDoer
    {
    private _querier;
    private _averager;

    StuffDoer(querier, averager)
    {
    this._querier = querier;
    this._averager = averager;
    }

    myAverageAboveMin(dbConn, min)
    {
    myData = this._querier.fetchAboveMin(dbConn, min);
    return this._averager.averageData(myData);
    }
    }


    And the connection would be managed at some even higher level that's responsible for the operation as a whole and knows what to do with this output.



    Now we can test the averaging logic completely independently of the querying, and what's more we can use it in a wider variety of situations. We might question whether we even need the MyQuerier and Averager objects, and maybe the answer is that we don't if we don't intend to unit test StuffDoer, and not unit testing StuffDoer would be perfectly reasonable since it's so tightly coupled to the database. It might make more sense to just let integration tests cover it. In that case, we might be fine making fetchAboveMin and averageData into static methods.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited yesterday

























    answered yesterday









    jpmc26

    3,82111735




    3,82111735








    • 1




      "Dependency injection is a technique that is intended to help you avoid huge, tangled construction trees...". Your first example after this claim is an example of pure, or poor man's, dependency injection. The second is an example of using an IoC container to "automate" the injection of those dependencies. Both are examples of dependency injection in action.
      – David Arno
      yesterday










    • @DavidArno Yeah, you're right. I've adjusted the terminology.
      – jpmc26
      yesterday










    • There's a third main reason to vary the implementation, or at least design the code assuming that the implementation can vary: it incentivizes developer to have loose coupling and avoid writing code that will be hard to change should a new implementation be implemented at some time in the future. And while that may not be a priority in some projects (e.g. knowing that the application will never be revisited after its initial release), it will be in others (e.g. where the company business model specifically tries to offer extended support/extension of their applications).
      – Flater
      2 hours ago














    • 1




      "Dependency injection is a technique that is intended to help you avoid huge, tangled construction trees...". Your first example after this claim is an example of pure, or poor man's, dependency injection. The second is an example of using an IoC container to "automate" the injection of those dependencies. Both are examples of dependency injection in action.
      – David Arno
      yesterday










    • @DavidArno Yeah, you're right. I've adjusted the terminology.
      – jpmc26
      yesterday










    • There's a third main reason to vary the implementation, or at least design the code assuming that the implementation can vary: it incentivizes developer to have loose coupling and avoid writing code that will be hard to change should a new implementation be implemented at some time in the future. And while that may not be a priority in some projects (e.g. knowing that the application will never be revisited after its initial release), it will be in others (e.g. where the company business model specifically tries to offer extended support/extension of their applications).
      – Flater
      2 hours ago








    1




    1




    "Dependency injection is a technique that is intended to help you avoid huge, tangled construction trees...". Your first example after this claim is an example of pure, or poor man's, dependency injection. The second is an example of using an IoC container to "automate" the injection of those dependencies. Both are examples of dependency injection in action.
    – David Arno
    yesterday




    "Dependency injection is a technique that is intended to help you avoid huge, tangled construction trees...". Your first example after this claim is an example of pure, or poor man's, dependency injection. The second is an example of using an IoC container to "automate" the injection of those dependencies. Both are examples of dependency injection in action.
    – David Arno
    yesterday












    @DavidArno Yeah, you're right. I've adjusted the terminology.
    – jpmc26
    yesterday




    @DavidArno Yeah, you're right. I've adjusted the terminology.
    – jpmc26
    yesterday












    There's a third main reason to vary the implementation, or at least design the code assuming that the implementation can vary: it incentivizes developer to have loose coupling and avoid writing code that will be hard to change should a new implementation be implemented at some time in the future. And while that may not be a priority in some projects (e.g. knowing that the application will never be revisited after its initial release), it will be in others (e.g. where the company business model specifically tries to offer extended support/extension of their applications).
    – Flater
    2 hours ago




    There's a third main reason to vary the implementation, or at least design the code assuming that the implementation can vary: it incentivizes developer to have loose coupling and avoid writing code that will be hard to change should a new implementation be implemented at some time in the future. And while that may not be a priority in some projects (e.g. knowing that the application will never be revisited after its initial release), it will be in others (e.g. where the company business model specifically tries to offer extended support/extension of their applications).
    – Flater
    2 hours ago










    up vote
    0
    down vote













    I was always baffled by dependency injection. It seemed to only exist within Java spheres, but those spheres spoke of it with great reverence. It was one of the great Patterns, you see, which are said to bring order to chaos. But the examples were always convoluted and artificial, establishing a non-problem and then setting out to solve it by making the code more complicated.



    It made more sense when a fellow Python dev imparted to me this wisdom: it's just passing arguments to functions. It's barely a pattern at all; more like a reminder that you can ask for something as an argument, even if you could have conceivably provided a reasonable value yourself.



    So your question is roughly equivalent to "why should my function take arguments?" and has many of the same answers, namely: to let the caller make decisions.



    This comes with a cost, of course, because now you're forcing the caller to make some decision (unless you make the argument optional), and the interface is somewhat more complex. In exchange, you gain flexibility.



    So: Is there a good reason you specifically need to use this particular Setting type/value? Is there a good reason calling code might want a different Setting type/value? (Remember, tests are code!)






    share|improve this answer








    New contributor




    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.


















    • Yep. IoC finally clicked to me when I realised that it's simply about "letting the caller make decisions". That IoC means the control of the component is shifted from the component's author to the component's user. And since at that point I've already had enough gripes with software that thought itself smarter than me, I was instantly sold on the DI approach.
      – Joker_vD
      10 hours ago















    up vote
    0
    down vote













    I was always baffled by dependency injection. It seemed to only exist within Java spheres, but those spheres spoke of it with great reverence. It was one of the great Patterns, you see, which are said to bring order to chaos. But the examples were always convoluted and artificial, establishing a non-problem and then setting out to solve it by making the code more complicated.



    It made more sense when a fellow Python dev imparted to me this wisdom: it's just passing arguments to functions. It's barely a pattern at all; more like a reminder that you can ask for something as an argument, even if you could have conceivably provided a reasonable value yourself.



    So your question is roughly equivalent to "why should my function take arguments?" and has many of the same answers, namely: to let the caller make decisions.



    This comes with a cost, of course, because now you're forcing the caller to make some decision (unless you make the argument optional), and the interface is somewhat more complex. In exchange, you gain flexibility.



    So: Is there a good reason you specifically need to use this particular Setting type/value? Is there a good reason calling code might want a different Setting type/value? (Remember, tests are code!)






    share|improve this answer








    New contributor




    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.


















    • Yep. IoC finally clicked to me when I realised that it's simply about "letting the caller make decisions". That IoC means the control of the component is shifted from the component's author to the component's user. And since at that point I've already had enough gripes with software that thought itself smarter than me, I was instantly sold on the DI approach.
      – Joker_vD
      10 hours ago













    up vote
    0
    down vote










    up vote
    0
    down vote









    I was always baffled by dependency injection. It seemed to only exist within Java spheres, but those spheres spoke of it with great reverence. It was one of the great Patterns, you see, which are said to bring order to chaos. But the examples were always convoluted and artificial, establishing a non-problem and then setting out to solve it by making the code more complicated.



    It made more sense when a fellow Python dev imparted to me this wisdom: it's just passing arguments to functions. It's barely a pattern at all; more like a reminder that you can ask for something as an argument, even if you could have conceivably provided a reasonable value yourself.



    So your question is roughly equivalent to "why should my function take arguments?" and has many of the same answers, namely: to let the caller make decisions.



    This comes with a cost, of course, because now you're forcing the caller to make some decision (unless you make the argument optional), and the interface is somewhat more complex. In exchange, you gain flexibility.



    So: Is there a good reason you specifically need to use this particular Setting type/value? Is there a good reason calling code might want a different Setting type/value? (Remember, tests are code!)






    share|improve this answer








    New contributor




    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    I was always baffled by dependency injection. It seemed to only exist within Java spheres, but those spheres spoke of it with great reverence. It was one of the great Patterns, you see, which are said to bring order to chaos. But the examples were always convoluted and artificial, establishing a non-problem and then setting out to solve it by making the code more complicated.



    It made more sense when a fellow Python dev imparted to me this wisdom: it's just passing arguments to functions. It's barely a pattern at all; more like a reminder that you can ask for something as an argument, even if you could have conceivably provided a reasonable value yourself.



    So your question is roughly equivalent to "why should my function take arguments?" and has many of the same answers, namely: to let the caller make decisions.



    This comes with a cost, of course, because now you're forcing the caller to make some decision (unless you make the argument optional), and the interface is somewhat more complex. In exchange, you gain flexibility.



    So: Is there a good reason you specifically need to use this particular Setting type/value? Is there a good reason calling code might want a different Setting type/value? (Remember, tests are code!)







    share|improve this answer








    New contributor




    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    share|improve this answer



    share|improve this answer






    New contributor




    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.









    answered 16 hours ago









    Eevee

    1097




    1097




    New contributor




    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





    New contributor





    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






    Eevee is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.












    • Yep. IoC finally clicked to me when I realised that it's simply about "letting the caller make decisions". That IoC means the control of the component is shifted from the component's author to the component's user. And since at that point I've already had enough gripes with software that thought itself smarter than me, I was instantly sold on the DI approach.
      – Joker_vD
      10 hours ago


















    • Yep. IoC finally clicked to me when I realised that it's simply about "letting the caller make decisions". That IoC means the control of the component is shifted from the component's author to the component's user. And since at that point I've already had enough gripes with software that thought itself smarter than me, I was instantly sold on the DI approach.
      – Joker_vD
      10 hours ago
















    Yep. IoC finally clicked to me when I realised that it's simply about "letting the caller make decisions". That IoC means the control of the component is shifted from the component's author to the component's user. And since at that point I've already had enough gripes with software that thought itself smarter than me, I was instantly sold on the DI approach.
    – Joker_vD
    10 hours ago




    Yep. IoC finally clicked to me when I realised that it's simply about "letting the caller make decisions". That IoC means the control of the component is shifted from the component's author to the component's user. And since at that point I've already had enough gripes with software that thought itself smarter than me, I was instantly sold on the DI approach.
    – Joker_vD
    10 hours ago










    up vote
    0
    down vote













    Like all patterns, it is very valid to ask "why" to avoid bloated designs.



    For dependency injection, this is easily seen by thinking of the two, arguably, most important facets of OOP design...



    Low coupling



    Coupling in computer programming:




    In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules.




    You want to achieve low coupling. Two things being strongly coupled means that if you change the one, you very likely have to change the other. Bugs or restrictions in the one likely will induce bugs/restrictions in the other; and so on.



    One class instantiating objects of the others is a very strong coupling, because the one needs to know about the existence of the other; it needs to know how to instantiate it (which arguments the constructor needs), and those arguments need to be available when calling the constructor. Also, depending on whether the language needs explicit deconstruction (C++), this will introduce further complications. If you introduce new classes (i.e., a NextSettings or whatever), you have to go back to the original class and add more calls to their constructors.



    High cohesion



    Cohesion:




    In computer programming, cohesion refers to the degree to which the elements inside a module belong together.




    This is the other side of the coin. If you look at one unit of code (one method, one class, one package etc.), you want to have all code inside that unit to have as few responsibilities as possible.



    A basic example for this would be the MVC pattern: you clearly separate the domain model from the view (GUI) and a control layer that glues those together.



    This avoids code bloat where you get large chunks that do lots of different things; if you wish to change some part of it, you have to keep track of all the other features as well, trying to avoid bugs, etc.; and you quickly program yourself into a hole where it's very hard to get out.



    With dependency injection, you delegate the creation or keeping track of, well, dependencies to whatever classes (or configuration files) which implement your DI. Other classes will not care much about what exactly is going on - they will be working with some generic interfaces, and have no idea what the actual implementation is, which means they are not responsible for the other stuff.






    share|improve this answer

























      up vote
      0
      down vote













      Like all patterns, it is very valid to ask "why" to avoid bloated designs.



      For dependency injection, this is easily seen by thinking of the two, arguably, most important facets of OOP design...



      Low coupling



      Coupling in computer programming:




      In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules.




      You want to achieve low coupling. Two things being strongly coupled means that if you change the one, you very likely have to change the other. Bugs or restrictions in the one likely will induce bugs/restrictions in the other; and so on.



      One class instantiating objects of the others is a very strong coupling, because the one needs to know about the existence of the other; it needs to know how to instantiate it (which arguments the constructor needs), and those arguments need to be available when calling the constructor. Also, depending on whether the language needs explicit deconstruction (C++), this will introduce further complications. If you introduce new classes (i.e., a NextSettings or whatever), you have to go back to the original class and add more calls to their constructors.



      High cohesion



      Cohesion:




      In computer programming, cohesion refers to the degree to which the elements inside a module belong together.




      This is the other side of the coin. If you look at one unit of code (one method, one class, one package etc.), you want to have all code inside that unit to have as few responsibilities as possible.



      A basic example for this would be the MVC pattern: you clearly separate the domain model from the view (GUI) and a control layer that glues those together.



      This avoids code bloat where you get large chunks that do lots of different things; if you wish to change some part of it, you have to keep track of all the other features as well, trying to avoid bugs, etc.; and you quickly program yourself into a hole where it's very hard to get out.



      With dependency injection, you delegate the creation or keeping track of, well, dependencies to whatever classes (or configuration files) which implement your DI. Other classes will not care much about what exactly is going on - they will be working with some generic interfaces, and have no idea what the actual implementation is, which means they are not responsible for the other stuff.






      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        Like all patterns, it is very valid to ask "why" to avoid bloated designs.



        For dependency injection, this is easily seen by thinking of the two, arguably, most important facets of OOP design...



        Low coupling



        Coupling in computer programming:




        In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules.




        You want to achieve low coupling. Two things being strongly coupled means that if you change the one, you very likely have to change the other. Bugs or restrictions in the one likely will induce bugs/restrictions in the other; and so on.



        One class instantiating objects of the others is a very strong coupling, because the one needs to know about the existence of the other; it needs to know how to instantiate it (which arguments the constructor needs), and those arguments need to be available when calling the constructor. Also, depending on whether the language needs explicit deconstruction (C++), this will introduce further complications. If you introduce new classes (i.e., a NextSettings or whatever), you have to go back to the original class and add more calls to their constructors.



        High cohesion



        Cohesion:




        In computer programming, cohesion refers to the degree to which the elements inside a module belong together.




        This is the other side of the coin. If you look at one unit of code (one method, one class, one package etc.), you want to have all code inside that unit to have as few responsibilities as possible.



        A basic example for this would be the MVC pattern: you clearly separate the domain model from the view (GUI) and a control layer that glues those together.



        This avoids code bloat where you get large chunks that do lots of different things; if you wish to change some part of it, you have to keep track of all the other features as well, trying to avoid bugs, etc.; and you quickly program yourself into a hole where it's very hard to get out.



        With dependency injection, you delegate the creation or keeping track of, well, dependencies to whatever classes (or configuration files) which implement your DI. Other classes will not care much about what exactly is going on - they will be working with some generic interfaces, and have no idea what the actual implementation is, which means they are not responsible for the other stuff.






        share|improve this answer












        Like all patterns, it is very valid to ask "why" to avoid bloated designs.



        For dependency injection, this is easily seen by thinking of the two, arguably, most important facets of OOP design...



        Low coupling



        Coupling in computer programming:




        In software engineering, coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules.




        You want to achieve low coupling. Two things being strongly coupled means that if you change the one, you very likely have to change the other. Bugs or restrictions in the one likely will induce bugs/restrictions in the other; and so on.



        One class instantiating objects of the others is a very strong coupling, because the one needs to know about the existence of the other; it needs to know how to instantiate it (which arguments the constructor needs), and those arguments need to be available when calling the constructor. Also, depending on whether the language needs explicit deconstruction (C++), this will introduce further complications. If you introduce new classes (i.e., a NextSettings or whatever), you have to go back to the original class and add more calls to their constructors.



        High cohesion



        Cohesion:




        In computer programming, cohesion refers to the degree to which the elements inside a module belong together.




        This is the other side of the coin. If you look at one unit of code (one method, one class, one package etc.), you want to have all code inside that unit to have as few responsibilities as possible.



        A basic example for this would be the MVC pattern: you clearly separate the domain model from the view (GUI) and a control layer that glues those together.



        This avoids code bloat where you get large chunks that do lots of different things; if you wish to change some part of it, you have to keep track of all the other features as well, trying to avoid bugs, etc.; and you quickly program yourself into a hole where it's very hard to get out.



        With dependency injection, you delegate the creation or keeping track of, well, dependencies to whatever classes (or configuration files) which implement your DI. Other classes will not care much about what exactly is going on - they will be working with some generic interfaces, and have no idea what the actual implementation is, which means they are not responsible for the other stuff.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 hours ago









        AnoE

        3,817716




        3,817716

















            protected by gnat 12 hours ago



            Thank you for your interest in this question.
            Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



            Would you like to answer one of these unanswered questions instead?



            Popular posts from this blog

            Morgemoulin

            Scott Moir

            Souastre