Why should I use dependency injection?











up vote
74
down vote

favorite
25












I am having a hard time looking for resources on why I should 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 the following?



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


Instead of the following?



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









share|improve this question




















  • 8




    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






  • 43




    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
    2 days ago








  • 11




    @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
    2 days ago






  • 2




    Your code is not an example of dependency injection or inversion. It's an example of parameterization (which is often much better than DI).
    – jpmc26
    2 days ago















up vote
74
down vote

favorite
25












I am having a hard time looking for resources on why I should 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 the following?



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


Instead of the following?



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









share|improve this question




















  • 8




    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






  • 43




    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
    2 days ago








  • 11




    @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
    2 days ago






  • 2




    Your code is not an example of dependency injection or inversion. It's an example of parameterization (which is often much better than DI).
    – jpmc26
    2 days ago













up vote
74
down vote

favorite
25









up vote
74
down vote

favorite
25






25





I am having a hard time looking for resources on why I should 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 the following?



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


Instead of the following?



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









share|improve this question















I am having a hard time looking for resources on why I should 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 the following?



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


Instead of the following?



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






architecture object-oriented-design clean-code






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 17 hours ago









Peter Mortensen

1,11621114




1,11621114










asked 2 days ago









Daniel

510134




510134








  • 8




    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






  • 43




    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
    2 days ago








  • 11




    @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
    2 days ago






  • 2




    Your code is not an example of dependency injection or inversion. It's an example of parameterization (which is often much better than DI).
    – jpmc26
    2 days ago














  • 8




    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






  • 43




    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
    2 days ago








  • 11




    @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
    2 days ago






  • 2




    Your code is not an example of dependency injection or inversion. It's an example of parameterization (which is often much better than DI).
    – jpmc26
    2 days ago








8




8




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




43




43




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
2 days ago






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
2 days ago






11




11




@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
2 days ago




@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
2 days ago




2




2




Your code is not an example of dependency injection or inversion. It's an example of parameterization (which is often much better than DI).
– jpmc26
2 days ago




Your code is not an example of dependency injection or inversion. It's an example of parameterization (which is often much better than DI).
– jpmc26
2 days ago










9 Answers
9






active

oldest

votes

















up vote
93
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

















  • 20




    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
    2 days ago










  • 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
    yesterday






  • 6




    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
    yesterday






  • 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
    yesterday




















up vote
53
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

















  • 3




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






  • 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
    2 days ago








  • 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








  • 1




    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
    21 hours ago


















up vote
21
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








  • 2




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










  • @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
    yesterday


















up vote
8
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.














  • 1




    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
    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
    2 days ago










  • 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
    2 days ago






  • 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
    2 days ago










  • @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
    2 days ago


















up vote
4
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
    2 days ago






  • 11




    I think the whole car thing is a bit belaboured and confusing
    – Ewan
    2 days ago






  • 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
    2 days ago






  • 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
    yesterday






  • 2




    @gbjbaanb: At no point does my answer even remotely delve into polymorphism. There is no inheritance, interface implementation, or anything resembling the up/downcasting of types. You are completely misreading the answer.
    – Flater
    16 hours ago




















up vote
4
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























  • @IMSoP Better now?
    – candied_orange
    yesterday










  • Yes, that's much more friendly :)
    – IMSoP
    19 hours ago




















up vote
1
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













    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
      2 days ago










    • @DavidArno Yeah, you're right. I've adjusted the terminology.
      – jpmc26
      2 days 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
      22 hours ago










    • @Flater Dependency injection still results in strong coupling. It ties the logic to a particular interface and requires the code in question to know about whatever that interface does. Consider code that transforms results fetched from a DB. If I use DI to separate them, then the code still needs to know that a DB fetch happens and invoke it. The better solution is if the transformation code doesn't even know a fetch is happening. The only way you can do that is if the results of the fetch are passed in by a caller, rather than injecting the fetcher.
      – jpmc26
      12 hours ago












    • @jpmc26 But in your (comment) example the database didn't even need to be a dependency to begin with. Of course avoiding dependencies is better for loose coupling, but DI focuses on implementing dependencies that are needed.
      – Flater
      12 hours ago












    protected by gnat yesterday



    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
    93
    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

















    • 20




      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
      2 days ago










    • 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
      yesterday






    • 6




      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
      yesterday






    • 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
      yesterday

















    up vote
    93
    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

















    • 20




      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
      2 days ago










    • 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
      yesterday






    • 6




      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
      yesterday






    • 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
      yesterday















    up vote
    93
    down vote










    up vote
    93
    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 2 days ago









    Michael Borgwardt

    42.9k1098156




    42.9k1098156








    • 20




      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
      2 days ago










    • 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
      yesterday






    • 6




      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
      yesterday






    • 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
      yesterday
















    • 20




      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
      2 days ago










    • 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
      yesterday






    • 6




      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
      yesterday






    • 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
      yesterday










    20




    20




    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
    2 days ago




    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
    2 days ago












    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
    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
    yesterday




    6




    6




    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
    yesterday




    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
    yesterday




    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
    yesterday






    @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
    yesterday














    up vote
    53
    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

















    • 3




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






    • 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
      2 days ago








    • 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








    • 1




      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
      21 hours ago















    up vote
    53
    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

















    • 3




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






    • 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
      2 days ago








    • 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








    • 1




      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
      21 hours ago













    up vote
    53
    down vote










    up vote
    53
    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












    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











    share


    share










    answered 2 days ago









    Eric Seastrand

    60039




    60039








    • 3




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






    • 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
      2 days ago








    • 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








    • 1




      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
      21 hours ago














    • 3




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






    • 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
      2 days ago








    • 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








    • 1




      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
      21 hours ago








    3




    3




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




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




    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
    2 days ago






    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
    2 days ago






    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






    1




    1




    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
    21 hours 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
    21 hours ago










    up vote
    21
    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








    • 2




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










    • @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
      yesterday















    up vote
    21
    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








    • 2




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










    • @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
      yesterday













    up vote
    21
    down vote










    up vote
    21
    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 2 days ago

























    answered 2 days ago









    R. Schmitz

    1,032621




    1,032621








    • 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








    • 2




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










    • @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
      yesterday














    • 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








    • 2




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










    • @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
      yesterday








    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






    2




    2




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




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












    @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
    yesterday




    @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
    yesterday










    up vote
    8
    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.














    • 1




      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
      yesterday















    up vote
    8
    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.














    • 1




      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
      yesterday













    up vote
    8
    down vote










    up vote
    8
    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 yesterday









    Eevee

    1897




    1897




    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.








    • 1




      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
      yesterday














    • 1




      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
      yesterday








    1




    1




    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
    yesterday




    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
    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
      2 days ago










    • 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
      2 days ago






    • 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
      2 days ago










    • @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
      2 days 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
      2 days ago










    • 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
      2 days ago






    • 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
      2 days ago










    • @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
      2 days ago













    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 2 days ago









    Greg Burghardt

    11.3k42755




    11.3k42755








    • 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
      2 days ago










    • 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
      2 days ago






    • 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
      2 days ago










    • @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
      2 days ago














    • 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
      2 days ago










    • 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
      2 days ago






    • 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
      2 days ago










    • @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
      2 days ago








    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
    2 days ago




    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
    2 days ago












    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
    2 days ago




    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
    2 days ago




    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
    2 days ago




    @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
    2 days ago












    @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
    2 days ago




    @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
    2 days ago










    up vote
    4
    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
      2 days ago






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      2 days ago






    • 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
      2 days ago






    • 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
      yesterday






    • 2




      @gbjbaanb: At no point does my answer even remotely delve into polymorphism. There is no inheritance, interface implementation, or anything resembling the up/downcasting of types. You are completely misreading the answer.
      – Flater
      16 hours ago

















    up vote
    4
    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
      2 days ago






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      2 days ago






    • 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
      2 days ago






    • 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
      yesterday






    • 2




      @gbjbaanb: At no point does my answer even remotely delve into polymorphism. There is no inheritance, interface implementation, or anything resembling the up/downcasting of types. You are completely misreading the answer.
      – Flater
      16 hours ago















    up vote
    4
    down vote










    up vote
    4
    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 2 days ago









    Flater

    5,30511019




    5,30511019








    • 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
      2 days ago






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      2 days ago






    • 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
      2 days ago






    • 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
      yesterday






    • 2




      @gbjbaanb: At no point does my answer even remotely delve into polymorphism. There is no inheritance, interface implementation, or anything resembling the up/downcasting of types. You are completely misreading the answer.
      – Flater
      16 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
      2 days ago






    • 11




      I think the whole car thing is a bit belaboured and confusing
      – Ewan
      2 days ago






    • 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
      2 days ago






    • 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
      yesterday






    • 2




      @gbjbaanb: At no point does my answer even remotely delve into polymorphism. There is no inheritance, interface implementation, or anything resembling the up/downcasting of types. You are completely misreading the answer.
      – Flater
      16 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
    2 days ago




    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
    2 days ago




    11




    11




    I think the whole car thing is a bit belaboured and confusing
    – Ewan
    2 days ago




    I think the whole car thing is a bit belaboured and confusing
    – Ewan
    2 days ago




    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
    2 days ago




    @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
    2 days ago




    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
    yesterday




    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
    yesterday




    2




    2




    @gbjbaanb: At no point does my answer even remotely delve into polymorphism. There is no inheritance, interface implementation, or anything resembling the up/downcasting of types. You are completely misreading the answer.
    – Flater
    16 hours ago






    @gbjbaanb: At no point does my answer even remotely delve into polymorphism. There is no inheritance, interface implementation, or anything resembling the up/downcasting of types. You are completely misreading the answer.
    – Flater
    16 hours ago












    up vote
    4
    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























    • @IMSoP Better now?
      – candied_orange
      yesterday










    • Yes, that's much more friendly :)
      – IMSoP
      19 hours ago

















    up vote
    4
    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























    • @IMSoP Better now?
      – candied_orange
      yesterday










    • Yes, that's much more friendly :)
      – IMSoP
      19 hours ago















    up vote
    4
    down vote










    up vote
    4
    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 yesterday

























    answered 2 days ago









    candied_orange

    49.4k1686173




    49.4k1686173












    • @IMSoP Better now?
      – candied_orange
      yesterday










    • Yes, that's much more friendly :)
      – IMSoP
      19 hours ago




















    • @IMSoP Better now?
      – candied_orange
      yesterday










    • Yes, that's much more friendly :)
      – IMSoP
      19 hours ago


















    @IMSoP Better now?
    – candied_orange
    yesterday




    @IMSoP Better now?
    – candied_orange
    yesterday












    Yes, that's much more friendly :)
    – IMSoP
    19 hours ago






    Yes, that's much more friendly :)
    – IMSoP
    19 hours ago












    up vote
    1
    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
      1
      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
        1
        down vote










        up vote
        1
        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 22 hours ago









        AnoE

        3,827716




        3,827716






















            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
              2 days ago










            • @DavidArno Yeah, you're right. I've adjusted the terminology.
              – jpmc26
              2 days 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
              22 hours ago










            • @Flater Dependency injection still results in strong coupling. It ties the logic to a particular interface and requires the code in question to know about whatever that interface does. Consider code that transforms results fetched from a DB. If I use DI to separate them, then the code still needs to know that a DB fetch happens and invoke it. The better solution is if the transformation code doesn't even know a fetch is happening. The only way you can do that is if the results of the fetch are passed in by a caller, rather than injecting the fetcher.
              – jpmc26
              12 hours ago












            • @jpmc26 But in your (comment) example the database didn't even need to be a dependency to begin with. Of course avoiding dependencies is better for loose coupling, but DI focuses on implementing dependencies that are needed.
              – Flater
              12 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
              2 days ago










            • @DavidArno Yeah, you're right. I've adjusted the terminology.
              – jpmc26
              2 days 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
              22 hours ago










            • @Flater Dependency injection still results in strong coupling. It ties the logic to a particular interface and requires the code in question to know about whatever that interface does. Consider code that transforms results fetched from a DB. If I use DI to separate them, then the code still needs to know that a DB fetch happens and invoke it. The better solution is if the transformation code doesn't even know a fetch is happening. The only way you can do that is if the results of the fetch are passed in by a caller, rather than injecting the fetcher.
              – jpmc26
              12 hours ago












            • @jpmc26 But in your (comment) example the database didn't even need to be a dependency to begin with. Of course avoiding dependencies is better for loose coupling, but DI focuses on implementing dependencies that are needed.
              – Flater
              12 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 2 days ago

























            answered 2 days ago









            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
              2 days ago










            • @DavidArno Yeah, you're right. I've adjusted the terminology.
              – jpmc26
              2 days 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
              22 hours ago










            • @Flater Dependency injection still results in strong coupling. It ties the logic to a particular interface and requires the code in question to know about whatever that interface does. Consider code that transforms results fetched from a DB. If I use DI to separate them, then the code still needs to know that a DB fetch happens and invoke it. The better solution is if the transformation code doesn't even know a fetch is happening. The only way you can do that is if the results of the fetch are passed in by a caller, rather than injecting the fetcher.
              – jpmc26
              12 hours ago












            • @jpmc26 But in your (comment) example the database didn't even need to be a dependency to begin with. Of course avoiding dependencies is better for loose coupling, but DI focuses on implementing dependencies that are needed.
              – Flater
              12 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
              2 days ago










            • @DavidArno Yeah, you're right. I've adjusted the terminology.
              – jpmc26
              2 days 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
              22 hours ago










            • @Flater Dependency injection still results in strong coupling. It ties the logic to a particular interface and requires the code in question to know about whatever that interface does. Consider code that transforms results fetched from a DB. If I use DI to separate them, then the code still needs to know that a DB fetch happens and invoke it. The better solution is if the transformation code doesn't even know a fetch is happening. The only way you can do that is if the results of the fetch are passed in by a caller, rather than injecting the fetcher.
              – jpmc26
              12 hours ago












            • @jpmc26 But in your (comment) example the database didn't even need to be a dependency to begin with. Of course avoiding dependencies is better for loose coupling, but DI focuses on implementing dependencies that are needed.
              – Flater
              12 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
            2 days ago




            "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
            2 days ago












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




            @DavidArno Yeah, you're right. I've adjusted the terminology.
            – jpmc26
            2 days 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
            22 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
            22 hours ago












            @Flater Dependency injection still results in strong coupling. It ties the logic to a particular interface and requires the code in question to know about whatever that interface does. Consider code that transforms results fetched from a DB. If I use DI to separate them, then the code still needs to know that a DB fetch happens and invoke it. The better solution is if the transformation code doesn't even know a fetch is happening. The only way you can do that is if the results of the fetch are passed in by a caller, rather than injecting the fetcher.
            – jpmc26
            12 hours ago






            @Flater Dependency injection still results in strong coupling. It ties the logic to a particular interface and requires the code in question to know about whatever that interface does. Consider code that transforms results fetched from a DB. If I use DI to separate them, then the code still needs to know that a DB fetch happens and invoke it. The better solution is if the transformation code doesn't even know a fetch is happening. The only way you can do that is if the results of the fetch are passed in by a caller, rather than injecting the fetcher.
            – jpmc26
            12 hours ago














            @jpmc26 But in your (comment) example the database didn't even need to be a dependency to begin with. Of course avoiding dependencies is better for loose coupling, but DI focuses on implementing dependencies that are needed.
            – Flater
            12 hours ago






            @jpmc26 But in your (comment) example the database didn't even need to be a dependency to begin with. Of course avoiding dependencies is better for loose coupling, but DI focuses on implementing dependencies that are needed.
            – Flater
            12 hours ago







            protected by gnat yesterday



            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

            Quarter-circle Tiles

            build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

            Mont Emei