Dependency Injection Breaks Encapsulation

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?

I have described in several places what I mean by “appropriate” and “inappropriate” circumstances for the use of DI, and even Scott has eventually agreed with me (see post #310). Just for your benefit I shall explain AGAIN:

  • DI is appropriate when a dependent object can be instantiated from a number of alternative classes.
  • DI is inappropriate when a dependent object can only be instantiated from a single class where there are absolutely no alternatives.

[quote]- DI is inappropriate when a dependent object can only be instantiated from a single class where there are absolutely no alternatives.
[/quote]

Why? What makes it “inappropriate”. This is an baseless assertion. Why is DI inappropriate in this scenario?

edit: More importantly, what makes a singleton “more appropriate”?

I am using a singleton instead of DI in those places where the circumstances for which DI was designed do not exist. I could easily have used the “new” verb, but as the same class could be instantiated several times it is more efficient to instantiate it just once and use the same instance in multiple places.

“I chose not to” is not a valid argument and doesn’t explain why a singleton is better than DI in this case.

This is a red herring. The singleton class adds its own overhead. the result of this is that:

  1. When the condition is not met and the class is not used, the singleton version is faster
  2. When the condition is met (e.g. is valid) and the class is passed in with DI then the DI version is faster
  3. If the lazy loaded class is already used somewhere else in the script (likely) then all you’re doing is adding the overhead of the singleton for no advantage.

Let’s bench it:

<?php
$t1  = microtime(true);

class X {

}


for ($i = 0; $i < 1000000; $i++) {
	new X();	
}



$t2 = microtime(true);

echo $t2 - $t1;

0.11410284042358

<?php
$t1  = microtime(true);

class singleton {
	private static $instances = [];

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

		return self::$instances[$name];
	}
}
class X {

}


for ($i = 0; $i < 1000000; $i++) {
	singleton::getInstance('X');
}



$t2 = microtime(true);

echo $t2 - $t1;

0.27273297309875

And this isn’t even a fair test. In reality, the singleton isset condition would evaluate to false once per request, so this is more fair for this test:


<?php
$t1  = microtime(true);

class singleton {
	private static $instances = [];

	public static function getInstance($name) {
		if (true) {
			self::$instances[$name] = new $name;
		}

		return self::$instances[$name];
	}
}
class X {

}


for ($i = 0; $i < 1000000; $i++) {
	singleton::getInstance('X');
}



$t2 = microtime(true);

echo $t2 - $t1;

which gives 0.41565203666687.

So the singleton is unsurprisingly slower. In this case 4 times slower. For the singleton version to offer an average benefit in performance then:

  • The condition must not be met at least 80% of the time
  • and nowhere else in the code must be constructing the dependency. If other places are instantiating the dependency then you get the overhead twice or more… which is inarguably slower.

No it isn’t. That is like saying that a purr method and a fly method and an open method are more readable all attached to the same class than if purr were attached to a cat class, fly to an aircraft class and open to a door class. With all of them on the same class you imply that a cat can open a door can fly and an aircraft can purr.

2 Likes

Hmm… the definitions I know of are a bit different or rather I understand them differently. The definition of encapsulation I know of is about the hiding of data or methods in order to simplify a client’s usage of the objects or modules in question.


http://www.adobe.com/devnet/actionscript/learning/oop-concepts/encapsulation.html

The last one offers the closest reasoning to yours, but notice in his example.between the position class and the route class. Why didn’t Mr. Rogers just add the position methods into the route class? That would follow your understanding of encapsulation. Why he doesn’t do it? It is in his “2nd rule of encapsulation”, which is.

Encapsulation rule 2: Use responsibility-driven design to determine the grouping of data and operations into classes

which is the rule you ignore to make your 9000 line monster class viable in your mind. It is wrong. It is bad coding. It is hard to understand (which readability is all about). It basically kills all your arguments about DI.

No, you take issue with those who say it is ok to use it everywhere. The appropriate is a given (and why I agreed with you.) You are adding the “inappropriate and superfluous” to the equation and then you pull it into your world of programming to say, most of the time it is inappropriate and superfluous and that is YOUR issue. As Tom is trying to get you to explain to us, what is your definition of “appropriate”? If it is based on your own code, it thus shows basically NOTHING about what appropriate means. Your now and then usage of DI is NOT appropriate, because the basis your code is built on is NOT appropriate. You have absolutely no grounds to judge what appropriate is, because you don’t know what appropriate means. You DO NOT follow the second rule of encapsulation.

Encapsulation rule 2: Use responsibility-driven design to determine the grouping of data and operations into classes

Scott

1 Like

You are missing the point, as usual. All those methods are contained within my abstract table class and are inherited by each concrete table class. Those methods cover everything that I may wish to do with a database table, so it is perfectly valid that they belong in the same class.