Dependency Injection Breaks Encapsulation

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

I suggest you read the article written by Robert C. Martin which I have referred to several times. This describes those circumstances where DI is appropriate, which implies that in other circumstances it is not appropriate.

Where a dependency can be supplied from a collection of alternative objects then I DO use DI. But where a dependency can only be supplied from a single object without the possibility of any alternatives I instantiate the object in the calling module without it being injected. Why can’t you understand such a simple concept?

If my Person module wants to talk to my Address module, then what is wrong with instantiating the Address object right where I need to use it? There is only one Address class that I can use, so DI would be overkill in these circumstances.

But it all depends on whether the object I wish to use can have may sources or just a single source. If it has many sources I use DI. If it only has a single source I do not use DI. Instead I use code similar to the following inside my Person class:

$addressOBJ =& singleton::getInstance('address');
$data = $addressOBJ->getData($where)

The only difference between using or not using DI is where the class is identified from which the object is instantiated. If there are several alternative possibilities then I use DI to inject the dependency. If there are no alternatives - such as in the above example where there is only one class in my entire application from which I can obtain a postal address - then I prefer to take the simpler non-DI approach and hard-code the reference to the dependency immediately before I need to use it. This technique is called lazy loading (see http://en.wikipedia.org/wiki/Lazy_loading) which is more efficient than your method of eager loading.

Because you don’t seem to realise that DI can be used in any place you are using a singleton. Answer my question about the code examples (with a simple yes/no) and then answer this: What makes the singleton more “appropriate” than DI.

which implies that in other circumstances it is not appropriate.

Implies != demonstrates. Please demonstrate these circumstances with code examples.

which is more efficient than your method of eager loading.

Wrong again, if you provide some code I’ll benchmark it, thinking about it for a split second proves that statement incorrect: Lazy Loading creates more lines of code and therefore a higher execution time.

You’re going to say “Well what if it never gets loaded” to which the answer, as Scott is trying to tell you, is that your application has a flawed design because it breaks single responsibility principle

Then your definition of the SRP is different from mine. That 9000 line class to which you refer is an abstract class that contains every single method that may be used in any of my concrete table classes. Whether you like it or not every single method in that class is used somewhere in my application, so every method is necessary, and having all those methods in a single class is much more readable than having then scattered across dozens of smaller classes.

The definition of encapsulation is that a class should contain ALL the methods and ALL the properties relevant to the object which it serves, so splitting them across multiple classes would violate the rules of encapsulation.

[quote=“s_molinari, post:310, topic:113596”]

tony_marston404
If there are no alternatives then clearly DI is superfluous.

Ok. This is true.[/quote]
Wait a minute!!! Are you actually agreeing with me??? Well, I’ll go to the foot of our stairs!

I have no argument with those who use DI properly and in appropriate circumstances, but I do take issue with those who use it everywhere even when it is inappropriate and superfluous.

I cannot disagree for the simple reason that I regularly use DI in my framework when it is appropriate to do so, but when it is not appropriate then I don’t.

Tony please stop using the word “appropriate” it’s ambiguous and you haven’t defined it. How are you measuring “Appropriateness”?

Yes, it can, but you seem to be confusing “can” with “must”. I could use DI in those circumstances, but I choose not to because there would be no advantage in doing so.

Incorrect. Eager loading requires that you instantiate an object in a different part of the code from the place where it is actually used, and if you never run the code which uses it then you have wasted time in creating an object (plus all of its dependencies) which is never used.

Having an object which never gets used is not a symptom of a flawed design. Suppose you have a dependency which is only used when some conditions are met at run-time, but those conditions (such as data validation) are not met. That means that the object you instantiated before evaluating those conditions is thrown away without being used.

So what is the advantage of using a singleton? What makes your singleton approach more “appropriate” than DI?

In your own words you only use a technique if there is a “benefit”. What is the benefit of a singleton over DI?