Dependency Injection Breaks Encapsulation

Excellent summary! As I mentioned earlier in the thread, if you do follow the logic of “DI Breaks encapsulation” then any method argument breaks encapsulation in the same way. What is the difference between a constructor and another method for this discussion? Zero.

I disagree. Saying that a method argument breaks encapsulation is complete and utter nonsense. Encapsulation requires that all the methods and all the properties for an entity be “encapsulated” in a single class, and method arguments do not violate this simple rule.

While an outsider can know of an object’s methods and properties, it does not have any idea of how any method is actually implemented. This is called implementation hiding and exists in all languages whether they are OO or not. By injecting a dependency you are exposing the implementation by telling the object how to carry out the service which you are requesting. By exposing the implementation you are therefore breaking encapsulation.

This is not just my personal view. In his article http://www.bryancook.net/2011/08/on-dependency-injection-and-violating.html Bryan Cook has this to say:

He does quite clearly say that entities are newables (can be instantiated as needed) and service objects are injectables (can be injected). This tells me that it is perfectly acceptable to instantiate an entity only when it is actually needed, and that only services objects are candidates for injection. How can this be “twisting” what was written in that article?

As for not writing testable code, that is not my aim. I write “production-ready” code that I can sell to customers, and I am not going to butcher that code just to make it amenable to a unit-testing framework.

Incorrect. Entities are newable. Period.

I disagree. The wikipedia article at https://en.wikipedia.org/wiki/Dependency_injection contains the following caveat:

I disagree. Unit testing has nothing to do with OOP or any other programming paradigm. It is just a tool such as data flow diagrams or UML diagrams. Some people like TDD, but there are plenty of others who, like me, think that it’s overrated.

I assume that you are referring to my post #469 which was in response to your post #466.

Firstly, my default table class is not a database access class which exists in the Data Access layer, it is an abstract class which is inherited by every Model class in the Business layer. It is code within the abstract class which allows the Model to talk to the database through the DAO.

Secondly, I do not inject the data access object into any Model as this would violate one of the principles of the 3-Tier Architecture which states that only the Business layer can have any communication with the Data Access layer. The Presentation layer, which contains the Controller and the View, can only talk to the Business layer where the Models reside.

Thirdly, the only reason that the _getDBMSengine() function specifically mentions the MySQL and Oracle DBMS engines is that different extensions for those two databases became available over time, so I needed code which chose which extension to use.

Fourthly, where a DBMS has only a single extension, such as PostgreSQL or SQL Server, I do not need any code which in _getDBMSengine() which mentions that DBMS by name as the contents of the $engine variable, whatever it may be, is sufficient to identify the only possible class name for that DBMS extension.

Does this clear up your confusion?

Why do you keep waking up this thread Tony? Your objective isn’t to show how dependency breaks encapsulation, but rather prove how your framework avoids DI as best as you could?

Scott

Incorrect. My framework does not seek to avoid DI at every possible opportunity. I have demonstrated where I DO use DI in those circumstances for which it was designed and where I can show that it has genuine benefits. Those of you who say that DI should be used in ALL circumstances, even in those for which it was not designed and where it cannot be demonstrated that there are genuine benefits, are guilty of abusing and over-using this design pattern, and in doing so you are effectively breaking encapsulation.

According to Robert C. Martin, dependency injection provides benefits ONLY when a program’s dependency can be supplied from a number of alternative sources. This means that when a dependency can only come from a single source which never changes then the DI pattern does not provide any benefits at all. In these circumstances its usage would therefore be overkill and inappropriate.

I disagree. In order to call itself Objected Oriented a programming language need only support three features - Encapsulation, Inheritance and Polymorphism. That is not just MY opinion, it is also the opinion of Alan Kay (who invented the term) and Bjarne Stroustrup (who designed and implemented the C++ programming language),

All those “features” which have been added since then are not “requirements”, they are “optional extras”. As far as I am concerned any programmer who is incapable of developing effective software using nothing more than Encapsulation, Inheritance and Polymorphism is just that - incapable.

You may not agree with my opinion, but that will not stop me from expressing it.

I disagree. It is possible to break up a monolithic piece of code into smaller, more manageable pieces which are easier to read and therefore maintain WITHOUT using an OO language. This is called “structured programming” or “modular programming” which I learned in my COBOL days. When I moved from COBOL to the UNIFACE language I learned about the 3-Tier Architecture which broke an application down into 3 distinct and separate layers:

  1. Presentation/UI layer
  2. Business layer
  3. Data Access layer

Using this architecture it should be possible to change the Presentation layer without affecting the Business layer, or switch the Data Access layer from one DBMS to another without affecting the Business layer. These are examples of interchangeability and reusability.

I created development frameworks in both COBOL and UNIFACE, so when I switched to web development I saw no reason why I should not develop a similar framework using PHP and its OO capabilities. To be called Object Oriented a programming language need support for only three features - Encapsulation, Inheritance and Polymorphism. OOP can therefore be summed up as

Although lots of new “features” have been added to OO languages over the years I do not consider these to be “requirements”, just “optional extras”. Being optional it is therefore MY decision whether to use them or not, and I choose to use them only where they provide genuine benefits.

As far as I am concerned any programmer who is incapable of writing effective software using nothing more than encapsulation, inheritance and polymorphism is just that - incapable.

I initially developed my framework around the 3-Tier Architecture, but after I had done so a colleague pointed out that as I had broken the Presentation layer component into two separate parts - what he saw as a Controller and a View - that I had also implemented the MVC design pattern. Not only that, but I had also produced more reusable code than he had ever seen:

  1. All my Controllers are contained within the framework and do not have to be created or modified by the developer. I have a separate Controller for each Transaction Pattern.
  2. All my Views are contained within the framework and do not have to be created or modified by the developer. I have a separate View for HTML, one for CSV and another for PDF output.
  3. All my Data Access Objects are contained within the framework and do not have to be created or modified by the developer. I have separate objects for MySQL, PostgreSQL, Oracle and SQL Server
  4. All the Model classes are generated by the framework and provide default behaviour by inheriting large amounts of code from an abstract class which is also part of the framework. The default behaviour can the overridden or extended by placing code into a Model’s class file.

As far as I can see my implementation of OO has provided software which fulfils the objective of OO, which is to increase code reuse and decrease code maintenance.

I disagree. You cannot understand how an application works by looking a one class file just as you cannot understand the “big picture” by looking a single piece of a 1,000 piece jigsaw. The idea that a class should not have more than N methods or N lines of code is a totally artificial rule. The golden rule of encapsulation is, after identifying an entity, you should create a class for that entity which contains ALL the properties for that entity and ALL the methods which may be performed on that entity. If this requires 120 methods then it requires 120 methods whether you like it or not. You may think that this produces unreadable code, but there are plenty of people who would say that by splitting the “monster” class into 120 “proper” classes you are making the code less readable. It is easier to follow methods which exist in the same class than methods which are scattered across multiple classes. By splitting the class you are also converting a cohesive and unified module into a series of fragmented parts where all unity is lost. Not only that, but you are also adding in volumes of additional “glue” code to transfer control from one object to another. Not only does this have an adverse affect of the code’s readability, it also has an adverse affect of the code’s execution time. If you want an example of such code I can point you to a PHP email library which has 120 classes spread across a complex directory structure just to send an email. Is that overkill or what?

People keep telling me that my Model classes are too big, but I disagree. The methods in each Model do one of the following

  1. They allow the Model to be called from the layer above it.
  2. They allow the Model to call the layer below it.
  3. They perform processing steps between methods 1 and 2.

So you are agreeing with me that if Dependency Injection was designed to deal with those circumstances where a dependency can be supplied from a variety of sources then DI is appropriate? But where a dependency can only be supplied from a single source which never changes then DI is not appropriate?

I disagree. Tested code is that code which has been examined by the QA department and proven to meet all its deign objectives. It is also code which has passed User Acceptance Testing (UAT).

This is like saying, I can have a new 2015 Mustang. It has features in it like air conditioning as standard, so when it’s hot, I can stay cool. It has a navigation system, so I can find places faster. It has cruise control, so my driving long distances is less stressful. It has a powerful, but much more efficient V8 engine, so I can go faster for less money.

Or I can just stick with my 1968 Mustang. It drives from A to B too.

I can’t be knocked for sticking with my nostalgic 68 Mustang, but I definitely couldn’t hack on those people driving the new model, because I chose to not get a newer model with all the “optional extras”.

Scott

Your analogy is like comparing apples with house bricks. You are confusing how software is developed with how software is perceived by the user. The former is concerned with what rules you follow to get the results while the latter is concerned only with the results.

If I have written an application which works and which sells then it would be commercial suicide to spend time rewriting the software to make it do what it already does but in a different manner. I only look at an existing piece of software in the process of dealing with a change in user requirements. This may require adding new modules or changing existing modules, and it may also involve some refactoring so that any new codes looks as if it was always there rather than being forced in as a bodge.

If my customer asks for new features - such as air conditioning, satnav or cruise control - then I add those features, and it will be easier to add those features if my software was well written in the first place.

But when it comes to using new features that have just been made available in the language I’m afraid it’s a different story. I cannot spend any time working on the software unless I can charge it to the customer, and the customer will be unwilling to pay for any work unless he can see the benefit.

I don’t need to change my code to use the “new” way of loading classes (using autoloaders) because the “old” way still works.

I don’t need to use namespaces as I don’t have any naming clashes with third-party libraries.

I don’t need to use any of that other junk that was added in PHP 5 because it doesn’t do anything new, it just does what can already be done, but does it differently.

No, I am confusing nothing. I am comparing programming in PHP to driving a Ford Mustang. Yes, newer versions of PHP and frameworks have “nice optional equipment” and you don’t have to use them, if you don’t want to. But, if you do choose not to use them, you are missing out on a lot of good things that make your programming experience a lot better. That is the analogy.

The whole thing with you Tony is you try and justify that all those good new optional things in PHP and used in Frameworks aren’t worth using, because your old legacy code framework, and you as a coder, don’t take advantage of of them. You even go so far as to constantly push your framework forward as something better, when it really isn’t. It is just like you trying to say your driving the old 68 Mustang is a better experience than driving a 2015 Mustang. It just isn’t true from a modern, comfortable and safe driving perspective.

Scott

1 Like

Exactly my point. Structured and modular programming existed long before OO, If they were all that were needed to break up code into manageable pieces then OO would never have existed.

It is the fact that each OO class is complete within itself and can be reused in different situations that makes all the difference.

You are writing structured/modular code and calling the whole thing a class. That doesn’t make it OO at all.

Why on earth not? My code is oriented around objects, therefore it IS object oriented. I am using encapsulation, inheritance and polymorphism to increase code reuse and decrease code maintenance, therefore I am using the features of OO which do not exist in non-OO languages. The idea that OOP is supposed to be more complicated than that is quite ridiculous as well as being counter to one of the “promises” which OO was supposed to deliver in the first place. This is a quote from an article I read years ago which promoted OO over other paradigms:

If OO is supposed to be easier to learn then why is a simple implementation of the OO features not considered to be “good enough”?

Incorrect. Just because a new feature is added to the language does not mean that I should rush out and incorporate it in my code. If I don’t NEED the facility that the new feature provides the effort would be completely wasted.

If I never drive my car in a hot climate then I don’t need air conditioning. If I only ever drive my car from A to B along a straight road then I don’t need satnav. If I never drink in my car then I don’t need cup holders.

Your only criticism of my coding style is that it is not the same as yours, as if YOUR coding style was the ONLY coding style which was acceptable. I choose a different coding style which is simpler than yours, yet it still works. You cannot prove that it doesn’t.

If you stop attacking my coding style then I will have no reason to keep defending it.

I consider that proving a negative is something of a waste of time. I cannot prove that God doesn’t exist either but I’m not going to accept that he does for no good reason either. After all, the purpose of all these religions might be a test to see who’s gullible enough to believe based on flimsy evidence.

Getting back to the programming, I would be interested in hearing more on your testing process. Is there anything that you want to share with us in that regard, that we can learn from?

2 Likes

Puh, Again you twist this around to fit your own prerogative. Nobody is saying you need to do or change anything. You are the one who constantly pushes your framework forward saying it is superior in architecture and coding style, despite not using “the shiny new options” and that is terribly incorrect.

And thus you limit yourself considerably.

It isn’t MY coding style, but a style that is being prescribed by the greater minds leading the language. How much of your framework fits the standards on that site Tony? If you consider the things on that site as anything but good, then you are really in hurting status. Instead of being a PHP heretic, with your experience, you should have been one of the leaders. But, at one point, you decided to stop learning and advancing your skills and knowledge. And now we are here arguing with you on what is right and wrong, where your perspectives and skills are wrong and outdated.

You keep using your code/ your framework as a basis for your argumentation. Stop using it for argumentational purposes and it won’t get attacked.

Scott

Then why do people in this forum keep telling me that my coding style is wrong? Something that works cannot be wrong just as something which does not work cannot be right. My coding style and design methodology are not WRONG, simply DIFFERENT.

I cannot teach anyone anything new about testing because I still carry out testing the old fashioned way. Unit testing did not exist when I built my framework and the enterprise application which I wrote using it, and attempting to retro-fit unit tests into such a huge code base would be phenomenally expensive in both time and money, so it isn’t going to happen.

If I have a choice between doing something for a customer that earns me money and doing something just to please a bunch of knuckleheads that earns me nothing, where do you think my priorities would be?

Can you at least address Paul’s response?

Paul stated:

At least describe what you do in your QA process for him as, he is interested. Just saying you use the “old fashion way” doesn’t describe anything. That could mean, none, it could mean, deploy it and see what breaks, it could mean having a QA department manually execute tasks, it could mean you as a dev execute tasks, et al.

At least indulge those who are showing interest in the style you choose to implement.

His question of

Was likely rhetorical, as without knowing what process you used, one cannot assess if they learned something new from it. So unless you provide him your workflow for QA/testing, he can’t determine if there was something he didn’t know about that area.

Also, let’s please take note that he didn’t say “unit testing” or “integration testing” or “automated testing”, he simply said “testing”. So he isn’t specifically referring to TDD, he simply wants to know how you test your changes/features (we all already understand that you do not use TDD, that’s well understood and he isn’t trying to challenge that).

No I do not. You, or people like you, keep telling me that I should use a new feature in the language for no good reason other than it is there.

What greater minds? There is no such thing as a single document called “best practices” which is universally accepted by all programmers. There never was and there never will be. All there are is a series of different opinions from different individuals, so a lot depends of whose opinions you choose to follow. You may think that Dependency Injection is the best thing since sliced bread, but I (and others) do not. If you don’t believe me then take a look at the following:

http://www.natpryce.com/articles/000783.html

http://www.innoq.com/blog/hw/2007/08/29/dependency_injection_good_or_bad_practice.html
http://www.elilopian.com/2007/08/19/dependency-injection-keep-your-privates-to-yourself
http://geekswithblogs.net/chrisfalter/archive/2008/02/15/new-statement-considered-harmful.aspx
http://java.dzone.com/articles/dependency-injection-makes
http://web.archive.org/web/20111020043053/http://www.jordanzimmerman.com/index.php?n=9
http://blogs.msdn.com/b/simonince/archive/2008/06/30/dependency-injection-is-dead.aspx
http://richardmiller.co.uk/2011/05/19/when-dependency-injection-goes-wrong
http://www.javalobby.org/java/forums/t78371.html
http://johannesbrodwall.com/2010/11/10/this-dependency-injection-madness-must-end
http://devhawk.net/2009/07/17/the-texas-dependency-injection-massacre
http://web.archive.org/web/20130916185759/http://theruntime.com/blogs/jacob/archive/2007/08/07/dependency-injection.aspx
http://web.archive.org/web/20130516130335/http://theruntime.com/blogs/jacob/archive/2007/12/10/dependency-injection-objection.aspx
http://web.archive.org/web/20130516124415/http://theruntime.com/blogs/jacob/archive/2007/08/20/poking-bears.aspx
http://web.archive.org/web/20130516122222/http://theruntime.com/blogs/jacob/archive/2007/12/13/dependency-injection-house-call.aspx
http://comoyo.github.io/blog/2013/02/06/the-inverse-of-ioc-is-control/
http://www.loosecouplings.com/2011/02/non-di-code-spaghetti-code.html
http://www.loosecouplings.com/2011/01/how-to-write-testable-code-overview.html
http://www.loosecouplings.com/2011/01/dependency-injection-using-di-container.html
http://www.daedtech.com/encapsulation-vs-inversion-of-control
http://davidscode.com/blog/2015/04/17/when-does-dependency-injection-become-an-anti-pattern/
http://www.bryancook.net/2011/08/on-dependency-injection-and-violating.html
http://www.javacodegeeks.com/2014/10/di-containers-are-code-polluters.html
http://www.xmsxmx.com/the-dependency-injection-debate/