Dependency Injection Breaks Encapsulation

I’m not discussing this any further until you provide examples of a situation where DI is measurably inferior to another approach and explain the metric you are using to measure that difference. If you actually had a reason for not using DI this would be very easy for you. All you’re proving by avoiding the question is that you are unable to back up your claims.

Never employ a particular design pattern or technique unless you can prove that it has benefits

Once again you miss an obvious fact. If you’re not using a technique to solve a problem (locating dependencies) you’re using something else . that other technique can therefore be compared directly with the one you “cannot prove has benefits” and in fact must have some benefit of its own, by your own logic that you won’t use something unless it has benefits. What is the benefit of this alternative approach?

Edit: please demonstrate this benefit with code examples. What is the benefit of your approach over di if what you say is true and you don’t use something unless it has a benefit then you must have a reason for using the approach you use.

I’m not sure why this is such a difficult concept for you but I’ll explain it in more detail if you genuinely do not understand.

I have already told you that I do not use DI in those places for which it was not designed,so I do not use DI because it is inferior over my alternative method, I do not use it because it is inapplicable. If you study Robert C. Martin’s “copy program” in his article http://www.objectmentor.com/resources/articles/dip.pdf you should see that he uses DI in the situation where a dependent object can be supplied from a selection of alternatives - in the “copy program” it is a choice of devices - and the non-DI way causes the program to have knowledge of each of the alternatives and to contain code which selects which one to use. By implementing DI the choice is made outside of the program, and the program simply uses whatever object it is told to use.

Robert C. Martin clearly demonstrates that DI only has benefits where a dependency can be supplied from a selection of alternatives, which therefore implies that the opposite is also true, that DI does not have any benefits where there are no alternatives.

I have never claimed that DI is inferior to my method, just that DI is unnecessary when used in circumstances for which it was not designed.

You are missing a significant point, as usual. In those circumstances where I need to locate a dependency from a selection of alternatives I do actually use DI, but where there are no alternatives I don’t need to locate that dependency using DI because I can simply hard-code the name. This method is quicker and easier to write, easier to read as the code is not fragmented, and therefore easier to maintain. Furthermore it is also more efficient as the dependent object is only instantiated when it is actually needed instead of because it may be needed. I suggest you look up the difference between lazy loading and eager loading.

Tony. Stop. Back up your claims or stop arguing.

I have never claimed that DI is inferior to my method, just that DI is unnecessary when used in circumstances for which it was not designed.

You said

Never employ a particular design pattern or technique unless you can prove that it has benefits.

You have not provided an example of those benefits.

[citation needed]. Supply a code example where DI is “inapplicable” and the solution you are using in its place.

Backtracking and rewording your argument isn’t helping your case.

All you’re doing is proving that you are incapable of backing up your claims. If you actually had an argument you would be able to easily demonstrate it with code examples. At this point the argument is this, as an analogy (I know you struggle to understand them but do try)

We both have a problem: We have to boil water to make a cup of tea.

Tom: I’m going to use a kettle. It’s fast, it’s portable and it’s self-contained. I can easily move it around the kitchen and if I want to, move it to a different room.

Tony: I’m going to use a saucepan on the hob. No real reason, it just works for me. I use a kettle where it’s appropriate for making a hot drink but I can’t demonstrate an example where it’s not. Tom you’re wrong for always using a kettle for this. I like using a saucepan despite being unable to provide any reasoning for doing so even though a kettle has many advantages.

2 Likes

Hi @tony_marston404. Again, it may be that this discussion has gone the way it has because of a simple misunderstanding of the terminology involved:

From Wikipedia’s article on Dependency Injection:

dependency injection is a software design pattern that implements inversion of control for software libraries

As I said in my previous post, practicing Dependency Injection is one way for your code to exercise Inversion of Control. To me, your notion that your code illustrates DI rather than IoC is a misunderstanding of those two terms. As my quote from Wikipedia shows, the goal of practicing Dependency Injection is to achieve IoC in your code. Can you comment on this?

By specifying the number of constructor arguments your component classes will be instantiated with, you have defined the implementation of the construction of the object.

From Wikipedia’s article on Inversion of Control, one of the purposes of IoC is:

To decouple the execution of a task from implementation

As I’ve shown, practicing DI is done to achieve IoC, and defining the implementation of that dependency in your executing code is going to remove a lot of the benefits you might achieve from practicing DI and IoC otherwise.

I still hold that the code sample you have provided in order to demonstrate Dependency Injection in your framework does not illustrate Dependency Injection. The code sample does illustrate a method to achieve Inversion of Control, but by definition, does not illustrate Dependency Injection. Again, from Wikipedia’s article on Dependency Injection:

An injection is the passing of a dependency (a service) to a dependent object (a client). The service is made part of the client’s state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

Your code has instantiated a variable ($table) that is used by your client code to build a it’s service based on the value of that variable. This is in direct opposition to the definition provided.

Please understand that I am not making any assumptions about the effectiveness, scalability, portability or usefulness of your framework. I am only hoping to show how the code you have provided is not an example of Dependency Injection, and that this misunderstanding may be the reason this discussion has continued for so long without resolution.

Discussion Point 1

Are there circumstances where using DI would not provide any benefits and therefore should not be used?

In my example, I made no claim that practicing Dependency Injection was necessary. As you quoted, I said

As I said, if nothing else, code that is properly Dependency Injected will likely be layer separated and testable. Given that implementing dependency injection will provide these two benefits, there is no situation where using DI will not provide any benefits.

Discussion Point 2

Are there circumstances where using Dependency Injection breaks encapsulation?

Again, from Wikipedia’s article on Dependency Injection:

Dependency injection diminishes encapsulation by requiring users of a system to know how it works and not merely what it does

Your assertion here is extremely valid. Thanks for pointing this out.

To me, this then becomes an issue of scope. By practicing Dependency Injection, your controller code will/must break encapsulation by instantiating the objects needed at execution time. This is a fact.

If we narrow the scope of our discussion to object level, though, and then to method level, we’ll find that as far as those constructs are concerned, encapsulation has been enforced. The method will have all of it’s dependencies met and can operate on those dependencies the same as if that method had instantiated their own dependencies (lazy loaded).

This is where it is up to the dev to determine the best action to take, and they’ll have to define in what scope their objects are to maintain encapsulation.

Does a process that emails a client belong in a Client object because it will interact with some of the properties of the Client? When the system needs to be updated to allow emailing other users of the system, does that process belong as a method of a User object in order to keep all processes related to Users together?

Or do we create a new Emailer construct that just has scope over all interactions related to email? (Hint: this is what you should do :slight_smile: )

Again, this is a matter of scope. Being able to re-use code as requirements change is obviously desirable, and one way to make sure code is re-usable is to narrow the scope of what that code is doing. If we have an Emailer class that can send an email to a Client and to a User, logically, we will be able to also email other entities as the system grows (perhaps we will need to email Vendors, HelpDesk or something else).

Again, encapsulation must be thought of with respect to scope. If we want to use one object to handle all email interactions, our controller will be responsible for instantiating multiple objects (the emailer and the object representing the recipient), and the controller becomes our scope of encapsulation. If instead the emailTo methods exist on the objects representing the recipients, our encapsulation scope changes to be the recipient object, but we risk losing at least some measure of re-usability within our application.

1 Like

You are misreading what I wrote. I distinctly said that I use DI in those situations where it has benefits, and I don’t use DI in those situations where it does not produce benefits. The “benefit” of not using DI in inappropriate circumstances is not littering my software with code that has no useful purpose.

If you bothered to do proper research on Dependency Injection you will see that in Robert C. Martin’s paper on the Dependency Inversion Principle at http://www.objectmentor.com/resources/articles/dip.pdf he uses a “copy” program to identify where DI would provide a better solution. If you look carefully you will see that each of the two dependent objects can be for any one of a number of different devices. Without DI the copy program has to contain logic to identify which of the several possible dependencies are required so that it can use the correct one, and new devices cannot be added without updating the program. By implementing DI the choice is made outside of the copy program, and the copy program does not have to contain any code for any particular device - it simply uses whatever objects it has been told to use. Moreover, new device objects can be created and injected without having to make any amendments to the copy program.

It is quite obvious to me that DI is only useful when a dependent object can be supplied from a collection of possible alternatives, but when there is only a single choice without any alternatives then DI has zero benefits. This is precisely how I use DI in my framework - I use it when there is a choice between alternatives, and I don’t use it when there are no alternatives.

You are one of these people who seem to think that just because a design pattern or technique provides benefits in some circumstances that it should also be used in all circumstances, and in this you are totally wrong.

It is not up to me to prove that my non-use of DI is superior to its use in inappropriate circumstances, it is up to you to prove that using DI in inappropriate circumstances actually produces benefits, which you will never be able to do.

Rubbish. I have identified circumstances where DI was not designed to be used, and I have provided extremely simple code samples which show how I do not use DI in those circumstances. I have also provided code samples where I show how I use DI in those circumstances where it is actually appropriate.

Wrong. You have said words to the effect of “I sometimes use DI but I can’t demonstrate a situation where an alternative is measurably superior”.

Each time you post without backing up your claims you reinforce the fact that you are incapable of doing so and further diminish the strength of your own argument. Your words are meaningless without something tangible to back them up. In this case a simple code example… which should be incredibly easy to provide for someone who is so adamant they’re right and who is spending a lot of time/effort trying to make a point. Redirect that energy into something tangible and we can have a discussion.

Otherwise, no amount of avoiding the question and steering the conversation away from the topic at hand is going to help your argument. The fact that rather than answer a simple request (Demonstrate the benefit of alternative approaches) you instead rely on persistent obfuscation further proves that your underlying point is either invalid or non-existent and that you know it.

You keep saying “I don’t want testable code”, “My code doesn’t need to be maintainable”, “I don’t do it like that”, “I don’t want A to have a different instance of B”, “My code doesn’t work like that”, “I don’t need to change my code after it’s been written” but none of this has any bearing on whether DI is better or worse than an alternative . Then you follow it with the false assertion that “I DON’T HAVE THE PROBLEM THAT DI SOLVES” which is demonstrably incorrect, somehow you need to make A know about B. This is the problem that DI solves. To do this you are using a different technique. DI Solves the problem of how one instance of an object becomes visible to another, you must be solving this problem if you have more than one object in the application.

As you must be using a different approach for locating dependencies and as you have stated, in your own words that you

Never employ a particular design pattern or technique unless you can prove that it has benefits.

Please prove those benefits of the design pattern or technique you are using to locate dependencies and explain why those benefits make it better than DI. If the benefits you list also apply to DI then your point is moot as they are not an advantage over DI.

Why am I asking for code examples?

I’ll take a step back for a second and explain why we need code examples for this discussion. Do you understand why this is important? Because I don’t think you do. You’re on this “Everyone is wrong apart from me” tirade but you cannot back up the claims you make, you’re just trying to justify your poorly thought out code to us and yourself.

You started this discussion, Tony, claiming that DI is somehow inferior to some mythical other approach which you persistently fail to adequately demonstrate. It’s up to you to back up the claim you are making. Words alone are meaningless because they don’t do anything to make your case as we simply do not know exactly what you are referring to. It’s like saying “My car is better than a Ferrari” without either telling us what your car is or explaining in what way you are measuring “better” (Price? MPG? Speed? Looks?)

If we are going to have a discussion about the merits of different solutions to the same problem we need to see both those solutions solving the problem to analyse their efficacy and you must explain how you are measuring the difference. Something you have never managed to do.

In science this is known as a “fair test” by only changing one variable at a time. To analyse the efficacy of one approach over another we must be able to see both methods producing the same result knowing that nothing else is interfering with the test. We can then analyse how well they perform relative to one another. To do this we must remove the concept we are testing from all other external influences and compare it directly to another solution which has also been isolated, otherwise it’s not clear whether it was the approach we are testing that had the effect or something else.

Once again for clarity as this seems to be a sticking point for you. Yes, you do have the problem that DI solves. That problem is locating dependencies. Trying to argue that you do not need to do that is demonstrably wrong. If you have more than one object in the application and one object needs to communicate with another then you need to solve the problem of how one object can see another. DI is a solution to this. Please demonstrate your solution to this problem and explain why it is better than DI.

I will just reiterate my previous point:

You know what tony, I’ll help you out in order to try to progress this discussion in a meaningful way. As you’re finding it so incredibly difficult to make your own point, I’ll try to steer you towards something that isn’t meangingless by giving you a 3 step template to follow. I’ll restate my argument in the manner I’m asking you to, I think that’s only fair. (I have done this several times already but hopefully another demonstration will help). Note that all code examples are complete, can be run and do not rely on anything else and contain only code relevant to the concept being demonstrated.

Please make your point by:

  1. Providing some example code that uses DI
  2. Providing some example code that achieves the same result without using DI where an improvement has been made
  3. Explain briefly the metrics you are using you measure that improvement.

Here, I’ll start:

###1) Here is an example of using DI. Note that this code is minimal and contains only code that is relevant to the concept I am trying to convey.

class A {
	private $b;

 	public function __construct(B $b) {
 		$this->b = $b;
 	}

 	public function doSomething() {
 		$x = $this->b->x();
 	}
}

new A(new B);

2) Here is an example using Tony Marston’s singleton class to achieve the same result:

class Singleton {
	private static $instances = [];

	public static getInstance($name) {
		if (!isset(self::$instances[$name])) {
			self::$instances[$name] = new $name;
		}
		return self::$instances[$name];
	}
}

class A {
	public function doSomething() {
		$b = singleton::getInstance('B');
		$x = $b->x();
	}
}

new A;

3) Reasons that (1) is better than (2)

  • Less code therefore less scope for bugs
  • Less code therefore easier to read
  • Lower memory usage
  • Lower execution time due to fewer lines of code being executed
  • In (2) it’s impossible to instantiate B if it has different constructor args to anything else managed by the singleton
  • In (2) the singleton must know about the dependencies of any class it instantiates
  • In (2) there is no way to use a subclass or different implementation of the B class unless I add some logic to the singleton, however that will affect any other place where B is requested
  • (1) does not suffer a law of demeter violation. I’m not going to explain why that’s good but see here: http://misko.hevery.com/code-reviewers-guide/flaw-digging-into-collaborators/
  • (2) is not portable. To move it to another project I must move all the singleton and all the classes the singleton knows about (and all the classes those know about, and all the ones they know about, ad infinitum)
  • (1) doesn’t rely on global state. This means I can create two instances of A that use different instances of B, alternatively I have the option to use either the same instance or a different instance each time.
  • In (2) if I want to move the A class to a different project I have to look through the class line by line and read the implementation of the singleton class to work out which other classes I need to copy to the new Project. In (1) I only have to look at the constructor.
  • As above but in (2) I need to move 3 classes (A, B and the Singleton class) into the new project adding extra weight. In (1) I only need to move two (and I can immediately work out which two)
  • (2) is harder to understand and follow for a new developer. If I look at the A::doSomething() method I cannot know what methods are available on the $b variable without looking into the singleton::getInstance() class and finding out what class it returns. In (1) I simply look at the constructor and know what class/interface is being used.
  • (1) can be isolated for testing
  • (1) Allows me to instantiate the A object with any subclass of B. This means my subclasses can have their own set of unique dependencies and A doesn’t need to know about them. In (2) this is impossible.

Disclaimer. Please read

I want to be clear because I know what you’re going to do: I’m not asking you to debate my points in section 3 I am asking you to make an argument using the same 3 step structure. Once you have demonstrated your approach and the benefits of it, only then can we compare those benefits relative to one another.

If you actually have a valid argument or a point to make, this should be an incredibly easy request to respond to. If you don’t do this, you are are admitting you cannot.

Let me turn the question around - can you have Dependency Injection without Inversion of Control? Can you have Inversion of Control without Dependency Injection? What is the difference between DI and IoC? Until someone can come up with a description that these two concepts are completely different and not interchangeable I shall stick with my claim that this thread is about DI and not IoC.

But I don’t use constructor arguments in my framework as I don’t need to configure an object an object before I can use it.

Your interpretation of that definition of DI is too tight, in my opinion. I AM passing a dependency (a service) to a client object which then becomes part of the client’s state. The fact that I am passing in the name of a class which has to be instantiated into an object instead of a pre-instantiated object is merely a minor technical detail. The client does not have to find or build the service, it simply executes the “new” function on whatever class name it has been given. Using “new” without any arguments is not the same as “building” an object by supplying a variety of constructor arguments which can vary according to the circumstances.

I do not agree that code is not “more testable” because it is separated. By having code fragmented across several different places you are actually making it more difficult for a human to follow, and code that is easy for a human to understand should take priority.

I do not agree that using DI will always provide benefits, and you will never convince me otherwise. DI was designed to be used in particular circumstances, and I use it where those circumstances appear in my framework. Where those particular circumstances do not exist then there is no benefit in using DI, so where those circumstances do not exist in my framework I do not use DI.

My opinion on this matter has two parts:

  • when used in appropriate circumstances DI does not break encapsulation
  • when used in inappropriate circumstances DI does break encapsulation.

My Controllers are designed to work with one of any number of possible alternative Model objects, so I need to inject the identity of that Model so that the Controller can work…

Where I have a Model which needs to access another Model I know which Model it is as there are no alternatives, no choices, so I don’t need, nor do I use, DI.

Incorrect. I have said that I use DI in those circumstances where it is appropriate, and I do not use DI in those circumstances where it is not appropriate. I have never said that my non-use of DI is superior, but I have said that the use of DI in inappropriate circumstances is not a good idea.

You bare misquoting me. I have never said “I don’t want testable code”, just that I don’t use automated tests. I have never said “My code doesn’t need to be maintainable” as I have been happily maintaining both my framework, and the applications which I have created with it, for many years. I have said “I don’t do it like that” but only in those circumstances where my implementation is different from yours. I have never said “I don’t want A to have a different instance of B” but there are circumstances where I know that there will never be a choice of instances of B, so I choose not to waste my time in implementing code to deal with a choice of alternatives when that choice will never materialise. I have said “My code doesn’t work like that” in those circumstances where you have assumed that my code works differently. I have said “I don’t need to change my code after it’s been written” but only in those circumstances where I would be doing nothing but changing the method of implementation but not changing the result…

As for your statement “none of this has any bearing on whether DI is better or worse than an alternative” you are completely missing the point - again. I do not have to prove that my non-use of DI is superior, I simply have to prove that the use of DI in inappropriate circumstances is a waste of time and that I have done. The fact that you cannot see that is your problem, not mine.

Where I do not have to locate a dependency from a collection of possible alternatives - because there are no alternatives, only a single choice - I do not have to use DI, therefore I choose not to use DI.

I did not say that DI is wrong under all circumstances, just that it is a waste of time under some circumstances. I have used Robert C. Martin’s paper on DI as my source for which circumstances are appropriate and which circumstances are not, yet you consistently fail to respond. Robert C. Martin is considered to be somewhat of an authority on such matters, yet you seem to totally disregard what he has to say.

Incorrect. In those places where I do not use DI it is because I do not need to locate a dependency from a collection of possible alternatives simply because there is only (and will ever only be) a single choice without the possibility of alternatives.

You are inventing a problem that does not exist. An object communicates with another object simply by call the object’s methods. The only “problem” is which object when there is a choice.

.

If nobody has anything new to say is there any reason to keep this topic open?

Incorrect. I have said that I use DI in those circumstances where it is appropriate, a

Yet you cannot demonstrate a single situation where it is not “appropriate” or even what you mean by “appropriate” in this context.

And you just proved my point. If you have to call $a->b(); you must get the $a instance from somewhere. One method is DI… I’ve been asking you to demonstrate your alternative… How is that so difficult to understand? Anyway, thanks for playing.

[quote]If you actually have a valid argument or a point to make, this should be an incredibly easy request to respond to. If you don’t do this, you are are admitting you cannot.
[/quote]

Like a monster class with 9000 lines in it?

You have no foot to stand on Tony and every argument you make just puts you deeper in your own quagmire of self-buffoonery, which I clearly see from my own perspective. This discussion isn’t about DI anymore. It is about your incorrect views about DI and how you dance around making the point of a better alternative.

All you have to do is agree, that DI is a proper and helpful design pattern and that modern, well written PHP applications should be modular and testable and those are the main reasons why the DI pattern is good, useful, beneficial, advantageous, etc.

Then go and rewrite your post about DI being evil and reword the title to be “DI is pretty cool, but I choose not to use it like everyone else does!”

Scott

2 Likes

I have already provided code samples showing where I use DI and where I do not use DI.

Where I do use DI I cannot show sample code which does not use DI for the simple reason that not using DI in those circumstances would require a convoluted and complicated solution which I am not prepared to consider.

Where I do not use DI is in those circumstances where DI is not appropriate, and I am not going to waste my time in implementing an inappropriate solution.

My objective is to write simple, readable code, and in my humble opinion the implementation of an inappropriate solution breaks this objective.

There is no rule that says a class cannot have more than N methods or N lines of code. A class should have as many methods and lines of code that is necessary to service the needs of an entity.

Who says my views regarding DI are incorrect? I took my inspiration from that article written by Robert C. Martin (see http://www.objectmentor.com/resources/articles/dip.pdf) which clearly shows that DI has benefits ONLY when a dependency can be supplied from a collection of alternatives. If there are no alternatives then clearly DI is superfluous.

I have provided code samples showing where I use DI, where a Controller can work with any one of my 300+ Model classes, so I inject the class that I need at runtime. I have also provided a two-line code sample which shows where I do NOT use DI - in my Person class which calls the Address class - for the simple reason that there is only one Address class without the possibility of any alternatives.

I agree that DI is a useful design pattern when used in circumstances for which it was designed, and when those circumstances exist in my framework I actually use it. There are too many people in this forum who cannot grasp that simple concept and who labour under the false impression that there are NO circumstances in which DI is inappropriate. I flatly refuse to follow that line of thought, and no amount of name calling will make me change my mind.

Where have you provided this? I’ll reiterate my point that

If you actually have a valid argument or a point to make, this should be an incredibly easy request to respond to. If you don’t do this, you are are admitting you cannot.

By refusing to provide a code example you are simply admitting that you are incapable of doing so. Obfuscation and avoiding the question is just digging yourself further into a hole.

You keep using the word “appropriate” but you have never explained what you mean by that term. Similarly, you have never shown what solution you use in its place. If you want to use the word “Appropriate” you need to tell us what metric you are using to measure “appropriateness” and demonstrate a solution that is appropriate under that metric.

I want to re-answer this now the thread has reopened because this is a concept you really seem to be struggling with. And I genuinely think this is your sticking point.

and here:

You clearly fail to understand so I’ll make it even clearer as I can see that this is where you are failing to understand what DI is used for.

An object communicates with another object simply by call the object’s methods.

This statement presents a problem: How does one object know about another? In order to call a method on another object I must have a reference to it in a visible scope. So answer these questions:

  1. Do you have more than one object in your application?
  2. Does any one of those objects need to call a method on any other one of those objects?
  3. If yes to (1) and (2) assuming your objects are $a and $b and $b needs to call $a->foo(), how does the $b instance know about the $a instance in order to call the method?

One method of answering 3 is DI. If you answer yes to 1 and 2 you have the problem that DI solves. If you’re not using DI you are solving that problem in a different way, with another technique. Please explain, with code examples, that alternative technique and why you believe it is better suited to solving this problem than DI is. See #287 for an example of the format you should use to do this.

Once you’ve grasped that, and that if you’re not using DI to solve this problem you are using another technique go and re-read this thread from the start as it will be enlightening.

tl;dr Yes, you do have the problem that DI solves if you have more than one object and no amount of claiming otherwise will change that fact. As mentioned numerous times, “I don’t have the problem DI solves” is a factually incorrect claim.

Where have you provided this? I’ll reiterate my point that

If you actually have a valid argument or a point to make, this should be an incredibly easy request to respond to. If you don’t do this, you are are admitting you cannot.

By refusing to provide a code example you are simply admitting that you are incapable of doing so. Obfuscation and avoiding the question is just digging yourself further into a hole.

You keep using the word “appropriate” but you have never explained what you mean by that term. Similarly, you have never shown what solution you use in its place. If you want to use the word “Appropriate” you need to tell us what metric you are using to measure “appropriateness” and demonstrate a solution that is appropriate under that metric.

I want to re-answer this now the thread has reopened because this is a concept you really seem to be struggling with. And I genuinely think this is your sticking point.

and here:

You clearly fail to understand so I’ll make it even clearer as I can see that this is where you are failing to understand what DI is used for.

An object communicates with another object simply by call the object’s methods.

This statement presents a problem: How does one object know about another? In order to call a method on another object I must have a reference to it in a visible scope. So answer these questions:

  1. Do you have more than one object in your application?
  2. Does any one of those objects need to call a method on any other one of those objects?
  3. If yes to (1) and (2) assuming your objects are $a and $b and $b needs to call $a->foo(), how does the $b instance know about the $a instance in order to call the method?

One method of answering 3 is DI. If you answer yes to 1 and 2 you have the problem that DI solves. If you’re not using DI you are solving that problem in a different way, with another technique. Please explain, with code examples, that alternative technique and why you believe it is better suited to solving this problem than DI is. See #287 for an example of the format you should use to do this.

Once you’ve grasped that, and that if you’re not using DI to solve this problem you are using another technique go and re-read this thread from the start as it will be enlightening.

tl;dr Yes, you do have the problem that DI solves if you have more than one object and no amount of claiming otherwise will change that fact. As mentioned numerous times, “I don’t have the problem DI solves” is a factually incorrect claim. DI is an “appropriate” solution for allowing one object to call methods on another.

I have done so several times by referring to the article written by Robert C.Martin, yet you keep ignoring it.

In my code sample where my Person class calls the Address class the Address object is obtained using my singleton->getInstance(‘class’) method immediately before the line of code which accesses it. This is what I do in those circumstances where I don’t use DI. I have pointed this out several times, but you refuse to see it (except by telling me that singletons are bad).

Ok I’m glad that’s clear. So where I asked for you to provide:

The first two steps I provided:

1) Here is an example of using DI. Note that this code is minimal and contains only code that is relevant to the concept I am trying to convey.

class A {
	private $b;

 	public function __construct(B $b) {
 		$this->b = $b;
 	}

 	public function doSomething() {
 		$x = $this->b->x();
 	}
}

new A(new B);

2) Here is an example using Tony Marston’s singleton class to achieve the same result:

class Singleton {
	private static $instances = [];

	public static getInstance($name) {
		if (!isset(self::$instances[$name])) {
			self::$instances[$name] = new $name;
		}
		return self::$instances[$name];
	}
}

class A {
	public function doSomething() {
		$b = singleton::getInstance('B');
		$x = $b->x();
	}
}

new A;

Are, in your mind, correct? my second example using the singleton class is what you’re using in place of DI? Please answer with a simple yes or no.

Ok I’m glad that’s clear. So where I asked for you to provide:

The first two steps I provided:

1) Here is an example of using DI. Note that this code is minimal and contains only code that is relevant to the concept I am trying to convey.

class A {
	private $b;

 	public function __construct(B $b) {
 		$this->b = $b;
 	}

 	public function doSomething() {
 		$x = $this->b->x();
 	}
}

new A(new B);

2) Here is an example using Tony Marston’s singleton class to achieve the same result:

class Singleton {
	private static $instances = [];

	public static getInstance($name) {
		if (!isset(self::$instances[$name])) {
			self::$instances[$name] = new $name;
		}
		return self::$instances[$name];
	}
}

class A {
	public function doSomething() {
		$b = singleton::getInstance('B');
		$x = $b->x();
	}
}

new A;

Are, in your mind, correct? my second example using the singleton class is what you’re using in place of DI? Please answer with a simple yes or no.

edit: The reason I didn’t want to use this example is because I know you’d have said “Well that’s not how I’d done it” and claim it was a strawman. I genuinely wanted you to provide your own code examples so you couldn’t use that excuse.

Oh my Tony. There is no rule that says you shouldn’t drive your car into a wall. Does that mean, when you do it, everything is fine? There is a rule in good OOP, which says, your classes should have a single responsibility. 9000 lines of code means, that clearly IS NOT happening. Edit: And you totally missed the point of readability. A 9000 line monster class is not exactly fun to read.

Ok. This is true. Please now go change your post to say that and change the title and take out the insult to the smart people out there, who use DI properly.

Yay! We agree on something and we can stop arguing about DI and it being “evil”. It certainly isn’t, just like Robert clearly says at the end of his article.

The principle of dependency inversion is at the root of many of the benefits claimed for object-oriented technology. Its proper application is necessary for the creation of reusable frameworks. It is also critically important for the construction of code that is resilient to change. And, since the abstractions and details are all isolated from each other, the code is much easier to maintain.

Can you also agree that there isn’t a better alternative to DI, when DI is appropriate to use?

Scott