Dependency Injection Breaks Encapsulation

Wrong. Each Model class holds the business rules for each business object (which in my application is the same as a database table) while all database access is handled by a separate DAO. This allows me to switch the DBMS between MySQL, Oracle or SQL Server without having change any Model class.

Wrong. Encapsulation was NEVER meant to mean information hiding, which is a view that every one of those articles supports.

As I said, if you haven’t managed to figure it out on your own by now you never will but you can’t say “WRONG” and then demonstrate that you didn’t even read what I said.

Again you’re using straw man arguments and misrepresenting other peoples position. Where did I say that encapsulation meant information hiding? I said that information hiding is the only way to guarantee encapsulation in PHP and Java.

Nobody has said you MUST use DI either.

Would you agree, when I say that any decent middle to large application or framework, which multiple developers work on, should aim to have decoupled, modular components and be testable?

Scott

To be fair I have said you should use DI unless you’ve got a better alternative and can explain how you’re defining "better"and nobody has managed this. DI cannot be used when you don’t know the class name you’re using but that is often better delegated to a factory anyway.

Hmm…I don’t know. You should do DI or you must do DI? There is a difference. :wink:

“Should” to me means, you are saying it makes more sense, if you do do it. “Must” means to me, you are saying you have no other choice than to do it. I don’t think you are saying that. Are you?

That is Tony’s whole argument. He says, he has a choice. You say Tony should use DI, which I agree with. Tony then twists that around to say, he mustn’t, because he does DI “his own way” and only when he sees fit to use it.

And, as you mentioned, he doesn’t prove his way is a better one. He only says, it functions in his framework, so it must be at least as good and that is the fallacy he is stuck in.

Oh, but I am just a dogmatic noname developer, so what do I know?

Scott

1 Like

EDIT: I posted in the wrong thread - moved to: Are today's major frameworks capable of enterprise capable applications? - #139 by fretburner

What is the issue, exactly, if you acknowledge that while you prefer your way of doing things, others are entitled to their own way?

Tony, as much as you can, please consolidate your replies into one reply - you can quote multiple people in a reply. It makes it easier to view the thread :slight_smile:

The problem, still, is despite all the talk about pragmatism and dogma you still cannot back up claims you make. You make claims about being a pragmatist but if that were true you’d be able to quantify your claims in some way using a metric of practicality.

You cannot do that, you just spout the same nonsense about DI being “inappropriate” without being able to quantify what that means, practically or otherwise. I’d argue that from a practical perspective, more lines of code = less practical yet your solution is more lines. Incidentally, the same is true of autoloaders. Perhaps lines of code isn’t how you’re measuring it, the problem is, you refuse to tell us what metric you use to measure the abstract concepts you discuss like “appropriateness” and “practicality”.

You talk a good talk and like throwing around fancy words (often wrongly) and you’re very good at evading questions, changing the subject and making it look like you have a point, but even a slight peek behind that curtain reveals you have nothing of substance at all.

1 Like

@tony_marston404 Could you please answer the above question with just a “yes” or a “no”?

Scott

I’d actually even take out the “which multiple developers work on” qualifier there. Even if there is only one developer, decoupled, modular, testable code is beneficial. I say from experience because I work for a small company and a lot of the projects just get assigned to a single developer.

Agreed.

So the question now is:

Would you agree, when I say that any decent middle to large application or framework should aim to have decoupled, modular components and be testable?

Scott

This video doesn’t directly say DI does or doesn’t break encapsulation. Still, it is a good video nonetheless and demonstrates clearly why one would use DI and its advantages over not using DI.

Scott

I beg to differ. I have been told repeatedly that in all those situations where I could use DI (but where I choose not) that I should use DI otherwise I am not following best practice.

Modular, yes. Testable, yes. Decoupled? No.

I have seen too many people who seem to think that there are only two conditions - tightly coupled or completely decoupled. This is a fundamental mistake.

In the first place, as described in http://en.wikipedia.org/wiki/Coupling_(computer_programming) coupling can either be described as tight (which is bad) or loose (which is good). Coupling is also contrasted to cohesion where high cohesion is good and low cohesion is bad. A good programmer should therefore aim for low coupling and high cohesion. That is exactly what I have achieved.

In the second place it is not possible to write completely decoupled methods, otherwise the program simply will not work.

Read what you wrote. The statement “information hiding is the only way to guarantee encapsulation” means exactly the same thing as “encapsulation means information hiding”. You are tying the two together by saying that you cannot have one without the other, and that is wrong.

No, you’re just further demonstrating that you don’t understand the relationship between them. I am saying you cannot guarantee one without the other there’s a difference.

This code has encapsulation:

class Player {
	
	public $health;

	public function damage() {
		$this->health--;
		if ($health == 0) echo 'YOU DIED';
	}

	public function heal() {
		$this->health++;
	}
}

The problem is, without information hiding there’s no way to guarantee encapsulation. As soon as this happens encapsulation has been broken:

class Enemy {
	public function attack($player) {
		$damage = rand(1,50);
		$player->health -= $damage;
	}
}

Because the data being acted upon has been unpacked from the functions acting upon it. Alternatively it’s really easy for someone to write a cheat:

function cheat($player) {
      $player->health = 99999999999;
}

Again, the data has been unpacked from the functions acting upon it. The only way to guarantee that this cannot happen is information hiding.

It’s possible to write a program using encapsulation without information hiding, but when someone uses my player class, without it there’s no way for me as the author of the player class to guarantee encapsulation hasn’t been broken.

This is a fundamental concept. As you don’t understand this it’s not surprising you are struggling with more nuanced topics like DI.

Your 9000 line monster class begs to differ with such a claim of achievement. It’s a poster boy for this statement on low cohesion from wikipedia

whereas low cohesion is associated with undesirable traits such as being difficult to maintain, test, reuse, and even understand.

And it’s also tightly coupled to things that exist outside of itself, even though it relies entirely on those things in order to be able to operate, not least the db settings being maintained in the $GLOBALS super.

1 Like

It is your definition of “better” with which I have an issue. As far as I am concerned there are two ways to tackle a problem - a simple way or a complicated way. If I have a dependency which can only come from a single source then the simplest way is to avoid the complication of DI and instantiate the object right where I want to use it. In that situation the extra work involved in using DI would do nothing but add an unnecessary complexity to the code, and as a follower of the KISS principle I seek to avoid unnecessary complexity.

Whoa! Hold your horses!! Did you actually read what you just wrote? The whole point of using DI is for those situations where the dependency can come from one of several sources, so when the choice of class name is made outside of the consumer and then injected into it, the consumer does not need to know the class name, just that it supports the method that it wants to call.

If there is a single class name, which you know, then that is a situation where DI is not necessary.

If you do not believe me then take a look at the description of the “copy” program in Robert C. Martin’s article at http://www.objectmentor.com/resources/articles/dip.pdf. Here you will see that the device objects are chosen and instantiated outside of the “copy” program and then injected into it. The “copy” program does not know or care what the actual devices are, just that they have a read() and write() method.

This nonsense AGAIN!? Your proposed alternative adds significantly more complexity than DI.

I agree we should reduce complexity… which is one reason why your singleton approach is measurably worse than DI. You’re arguing in favour of DI here, tony.

This is the same backwards logic. “Necessary” is irrelevant here… A singleton is not “necessary” either… you have no point.

I have never said that I must not use DI, just that I choose not to when the circumstances do not meet the design parameters for using DI.

I don’t have to prove that my way is better, just that your way is unnecessary.