Tony Marston's Blog About software development, PHP and OOP

Response to personal attack on reddit.com

Posted on 31st January 2020 by Tony Marston

Amended on 4th June 2020

Introduction
The basic principles of Object Oriented Programming (OOP)
The true meaning of the Single Responsibility Principle (SRP)
The wrong meaning of SRP
Programming is a balancing act
The class does too much
This is a GOD class
if ... else structures
method_exists
endif
Calls to is_True()
This is PHP 4 code
This class is utterly terrible
A message for Robert C. Martin
It's not the Rules which count, it's the Results
Comments from the not-so-clueless
Comments from other reddit posts
References
Amendment History
Comments

Introduction

In March 2017 one of my clueless critics posted an article on reddit which criticised the abstract table class which exists in my RADICORE framework. I refer to him and the other respondents to this thread as being "clueless" for the simple reason that they are all exhibiting the traits of clueless newbies as they don't fully understand the principles of OOP and how to apply them in an efficient and effective manner. This therefore makes them nothing more than cargo cult programmers in that they do not understand the words they read and therefore have difficulty in putting them into practice. By continually broadcasting their ill-informed ideas they become nothing more than echo chambers for outdated ideas.

The main idea behind the reddit post is that the code sample is so large that it surely must be breaking the Single Responsibility Principle (SRP). The contents of the post clearly indicate to me that these clueless newbies do not have a proper understanding of either the principles of OOP or the true meaning of SRP.

I have resisted till now the impulse to reply to this post as I felt that it would be a complete waste of time, like casting pearls before swine, but as the army of swine (aka "clueless newbies") is apparently growing at a faster rate I felt that another dose of pearls (aka "wisdom") is about due.

WARNING - this article contains opinions that those of a delicate nature might find offensive, so it may be advisable to have a dose of smelling salts at hand. You have been warned!

The basic principles of Object Oriented Programming (OOP)

As stated in What OOP is a language or technique is object-oriented if and only if it directly supports:

  1. Abstraction/Encapsulation - providing some form of classes and objects.
  2. Inheritance - providing the ability to build new abstractions out of existing ones.
  3. Runtime polymorphism - providing some form of runtime binding.

Everything else I regard as an optional extra which means that it is my choice whether I use them or not, and I can safely ignore any criticism from those who complain that I am not making the same choices as them.

The first lesson that clueless newbie programmers need to learn is what type of objects to create. In his article How to write testable code the author identifies three distinct categories of object:

  1. Value objects - an immutable object whose responsibility is mainly holding state but may have some behavior. Examples of Value Objects might be Color, Temperature, Price and Size.
  2. Entities - an object whose job is to hold state and associated behavior. Examples of this might be Account, Product or User.
  3. Services - an object which performs an operation. It encapsulates an activity but has no encapsulated state (that is, it is stateless). Examples of Services could include a parser, an authenticator, a validator or a transformer (such as transforming raw data into XML or HTML).

This is also discussed in When to inject: the distinction between newables and injectables.

The PHP language does not have value objects, so I shall ignore them.

It would be advisable to avoid the temptation to create Anemic Domain Models which contain data but no processing. This goes against the whole idea of OO which is to create objects which contain both data and processing.

The true meaning of the Single Responsibility Principle (SRP)

The problem with this principle is that the original definition was badly written which left it open to enormous amounts of interpretation and thus mis-interpretation. This definition was:

The Single Responsibility Principle (SRP) states that each software module should have one and only one reason to change.

But what exactly is a reason to change? Different people came up with different interpretations which led to different implementations, and several clueless newbies came up with the idea that if a module did "too much" then it must be handling more than one responsibility and therefore should be split into smaller modules. Note that while "too much" can be interpreted as "having more than one responsibility" the clueless newbies out there prefer the simpler interpretation of "a class with more than N methods" or "a method with more than N lines of code" where "N" is a totally arbitrary number. This indicates to me that these clueless newbies have the ability to count but not the ability to think. I have seen the number 10 quoted more often than not for this theoretical limit, which leads me to believe that these clueless newbies cannot yet count to higher than 10 without taking their shoes and socks off.

In two later articles the author of this principle, Robert C. Martin (Uncle Bob), came up with some better and more meaningful descriptions. In Test Induced Design Damage? he wrote:

How do you separate concerns? You separate behaviors that change at different times for different reasons. Things that change together you keep together. Things that change apart you keep apart.

GUIs change at a very different rate, and for very different reasons, than business rules. Database schemas change for very different reasons, and at very different rates than business rules. Keeping these concerns separate is good design.
In The Single Responsibility Principle he wrote:

This is the reason we do not put SQL in JSPs. This is the reason we do not generate HTML in the modules that compute results. This is the reason that business rules should not know the database schema. This is the reason we separate concerns.

What Uncle Bob is describing here is the 3-Tier Architecture which has three separate layers - the Presentation layer, the Business layer and the Data Access layer - and which I have implemented in my framework. This architecture also has its own set of rules which I have followed to the letter. So if I have split my application into the three separate layers which were identified by Uncle Bob then who are you to tell me that I am wrong?

Later on in the same article Uncle Bob also says the following:

Another wording for the Single Responsibility Principle is:

Gather together the things that change for the same reasons. Separate those things that change for different reasons.
If you think about this you'll realize that this is just another way to define cohesion and coupling. We want to increase the cohesion between things that change for the same reasons, and we want to decrease the coupling between those things that change for different reasons.

If you bother to read what Uncle Bob wrote in his articles you should see that he talks about areas of logic which are responsible for (or concerned with) different parts of a program. Nowhere does he state that each part should be limited in size, only in what it does. This totally destroys the argument that my abstract class is breaking SRP simply because of the amount of code it contains. Anyone who has ever written a large enterprise application will be able to tell you that there is no limit to the lines of code that a module may contain, only that it should contain only one type of logic - presentation (UI) logic, business logic or data access (SQL) logic.

The idea of breaking an application down into three separate layers has also been discussed by Martin Fowler in his article Presentation-Domain-Data Layering.

While it is possible to take one of those modules and to break it down further, care should be taken it not going too far otherwise you will create a fragmented system with low cohesion which becomes more difficult to maintain. An example which I have employed is where I have taken my Presentation layer module and split it into two parts giving me a Controller and a View. Note that the View can come in different flavours - one for HTML output, one for CSV and another for PDF. This produces the structure shown in Figure 1:

Figure 1 - The MVC and 3-Tier architectures combined

infrastructure-faq-05 (5K)

The four components used in the RADICORE framework have the following object types as identified previously in The basic principles of OOP:

  1. Model - this is an entity. One of these is created for each entity in the application and holds all the business rules for that entity.
  2. View - this is a service, a reusable component which is provided by the framework.
  3. Controller - this is a service, a reusable component which is provided by the framework.
  4. Data Access Object - this is a service, a reusable component which is provided by the framework.

Note that all domain knowledge is kept entirely with the Model classes for each domain/subsystem, which means that the Controllers, Views and DAOs are completely domain-agnostic. This means that they are not tied to any particular domain and can therefore be used with any domain.

As the Controllers, Views and DAOs are provided by the framework the only classes which the application developer needs to create are the Models. An enterprise application does not communicate with objects in the real world, it only communicates with objects in a database, and every database developer will tell you that each object in a database is a table. Each table follows a standard pattern in that it has a unique name, a structure which is comprised of a set of columns each of which has a name and a data type which is taken from a fixed list, a primary key, optional additional candidate keys, any number of one-to-many relationships with other tables either as the "one" or the "many". Regardless of what data a table holds there are only four operations which can be performed on it - Create, Read, Update and Delete (CRUD). Because each and every table follows a standard pattern it is therefore possible to create an abstract table class which contains all standard processing which can then be inherited by each concrete table class which provides the specific details for a particular table. Those of you you have gone beyond the stage of being clueless newbies should recognise this as being an implementation of the Template Method Pattern where invariant methods are provided by the abstract class and variable/customisable methods are provided within individual subclasses.

Note here that the abstract table class contains ALL the standard processing which may be performed on ANY table in the database, and as it contains a mixture of invariant methods (which have fixed implementations) and variant/variable methods (which may or may not be overridden in any subclass) this explains why it has a large number of methods. Note also that the Template Method Pattern does not place any sort of limit on the number of methods nor the number of lines of code within each method.

Using this arrangement I achieve vast amounts of polymorphism by virtue of the fact that each method which a Controller can call on a Model is defined within the abstract table class. No Controller is tied to a particular database table so can potentially be used with any table in the database. So if I have 40 Controllers (one for each Transaction Pattern) and 450 database tables this produces 40 x 450 = 18,000 (yes, EIGHTEEN THOUSAND) opportunities for polymorphism. Note that you must have polymorphism before you can implement Dependency Injection, so the more polymorphism you have the more dependencies you can inject. If you cannot produce similar amounts of polymorphism in your framework then I would suggest that your understanding of the principles of OOP and how to implement them to full effect is seriously impaired. Yet you clueless newbies have the audacity to tell me that I don't know what I'm doing!

The wrong meaning of SRP

A clueless newbie called plectid posted these comments:

SRP is about replaceable implementations behind interfaces

Rubbish. SRP has nothing to do with replaceable implementations behind interfaces, it is about splitting code into separate areas of responsibility. Replaceable implementations come from inheritance and polymorphism. Implementing SRP does not guarantee any level of polymorphism.

while the use of interfaces increases cohesion

The use of interfaces does not guarantee high cohesion, that comes from grouping those methods which form part of the same responsibility into the same class. Besides, I don't use interfaces as I get more from abstract classes.

And encapsulation says non-public-interface members should be hidden, and I don't see a single protected/private method.

Encapsulation does NOT mean data hiding, as discussed in Your class methods are too visible as well as A minimalist approach to Object Oriented Programming with PHP. The idea of data hiding has always seemed strange to me. Surely in an application whose sole purpose is to move data between a GUI and a database then hiding that data defeats that purpose?

Programming is a balancing act

There are a lot of principles which need to be taken into consideration when writing a program, and each of them has its own set of costs and benefits.

When to apply a rule or principle, and when to stop applying it are matters for the individual programmer. Writing code requires that several objectives need to be taken into consideration such as ease of development, ease of testing, ease of maintenance, ease of deployment, speed of execution and meeting user expectations. It is very rare to score highly in all these areas as aiming for a high score in one area usually ends up by having an opposite effect in another. This therefore requires a balancing act on the part of the programmer to apply "just enough" of each principle to obtain its benefits, but not "too much" so that it obliterates the benefits of a different principle. This is what prompted me to make the following statement:

There are two ways in which an idea can be implemented - intelligently or indiscriminately.

Those who apply an idea or principle indiscriminately, who apply it in inappropriate circumstances, or who don't know when to stop applying it, are announcing to the world that they do not have the brain power to make an informed decision. They simply do it without thinking as they assume that someone else, namely the person who invented that principle, has already done all the necessary thinking for them. This leads to a legion of Cargo Cult programmers, copycats, code monkeys and buzzword programmers who are incapable of generating an original thought.

This is why, in my own framework, I have implemented "just enough" of the principles of encapsulation, inheritance, polymorphism, high cohesion and loose coupling to achieve a huge amount of code reusability. Anything more would not provide any additional benefits, only erode them and apply additional costs, so I regard that "anything more" as being "too much".


The class does too much

That clueless newbie called plectid also posted this comment:

Whoa. A single class responsible for validation, building sql, i18n, pagination, file uploads, and handling custom button clicks. Maintaining? No. I'd stop all other activities and take a month to refactor it into separate, loosely coupled, single responsibility components.

This person clearly does not understand that encapsulation requires that ALL the properties and ALL the methods which relate to a single entity MUST be placed into the same class. Each of these entities is a business entity, therefore forms the Model in the MVC design pattern. None of my Model classes contains any Controller, View or Data Access code, therefore does not violate SRP. The individual complaints I will dismiss separately:

If you write applications where all this functionality is provided in separate classes then you are creating a highly fragmented system with low cohesion which would be a maintenance nightmare. In my design all the business rules for a particular database table are contained within a single class which is dedicated to that table, and as far as I am concerned this adheres to the original definition of encapsulation. When I say "original" I am allowing for the fact that over a period of time certain clueless newbies may decide to offer up some alternative and corrupt definitions.

Someone once asked me to explain what that class does in no more than 20 words, and this is my revised reply:

It is an abstract class that contains methods for any operation that can be performed in any Model class. (that's 19 words)

This version specifically mentions the Template Method Pattern:

This abstract class implements the Template Method Pattern for every operation called by a Controller on a Model. (that's 18 words)

Note here that it only contains code which is used in Model classes. Controller code only exists in Page Controllers. View code only exists within View objects. Data access code only exists within Data Access objects. If you cannot see that this degree of separation follows precisely what Uncle Bob wrote about then you are blind.

I should also point out that according to the genuine rules of OOP it would actually be impossible for me to break that large class down into a series of smaller classes. Why? Because it is an abstract class which is inherited by every one of my 400 domain classes. Everyone knows that multiple inheritance is not supported in PHP, therefore I cannot inherit from multiple small classes, only a single large one.

This is a GOD class

A clueless newbie called gskema made this statement:

This is literally a GOD class file.

This twat is obviously confusing my code with a GOD object, but as I have already responded to that criticism in another article I shall not repeat myself.

if ... else structures

A clueless newbie called Disgruntled__Goat made this statement:

if (condition) {
    // do nothing
} else {
    doSomething();
}
I don't think there is any way to help someone who after many years of programming, still doesn't understand boolean logic.

Yes, I DO understand boolean logic, but as I obviously have decades more experience than you I have seen that mistakes can be made when dealing with complex conditions which contain several negative statements. In these circumstances I have found it easier to test for an all positive set of conditions and only perform the doSomething() action if the positive condition fails.

method_exists

The same clueless newbie also made this statement:

over 100 occurrences of method_exists
Someone needs to learn what an interface is.

It may surprise you that, unlike some people who have only programmed with PHP for a very short time, I started to write my software in PHP 4 several years before version 5 existed and interfaces were introduced. Consequently I never used interfaces and have no intention of doing so. The method_exists() function predates interfaces by several years and is a perfectly acceptable way of testing for a method before calling it. You may not like it, but your personal preferences are of no concern to me.

Using interfaces does not guarantee that the method exists in that object for one simple reason - you cannot guarantee that the object implemented the interface that contained that method.

I also prefer to use abstract classes instead of interfaces as they allow me to implement the Template Method Pattern which provides the ability for an enormous amount of code reuse which would otherwise not be available.

endif

The same clueless newbie also made this statement:

Also the prevalence of } // if is just cringeworthy.

It may come as a surprise to you but I find the practice of using the "}" character (closing brace) on its own to close a control structure, any control structure, to be a cause of problems rather than a solution. Where you have the "{" character (opening brace) used to open a class, a method and structures such as if, while, do-while, for, foreach and switch which are in a nested structure, then you have to end those nested structures with a series of closing braces without any indication of which brace closes which structure. If the count of these closing braces is incorrect then it will cause an error, but the error message may not be able to indicate which control structure has the incorrect number of braces. This can lead to the situation where a missing brace in the middle of a script cannot be detected until the end of the script, and it can take quite a bit of effort to go through the whole script trying to match up each opening brace with its corresponding closing brace. I have heard that some programmers try to avoid this problem by automatically appending some extra closing braces at the end of each script, but this only avoids the generation of an error message without preventing the code from continuing down the wrong path.

Such a problem did not exist in an earlier language which I used as it did not utilise opening and closing braces but instead provided the ability to end each structure with an end<structure> statement. Thus if you had nested structures of different types and accidentally missed out the corresponding end<structure> statement, or even inserted the wrong end<structure> statement, the compiler was instantly able to report the actual line number where the error was detected.

Although PHP does provide for alternative syntax for control structures I have found that this alternative is rarely used, especially in all the code samples I have seen, so I am following the crowd by using braces. However, I do employ the following rules:

You may not like my rules, but ask me if I care.

Calls to is_True()

A clueless newbie called EnragedMikey posted this comment:

I like the is_True() calls.

You may not be aware of the need for such a function, but when you grow up and start doing some big boy programming which involves communicating with various database engines you will become aware of one simple fact - not all databases support the BOOLEAN data type. In this case there are various options:

There may also be some settings in config/ini files which use the following values:

Because of all these possibilities I created a simple is_True() function as follows:

function is_True ($value)
// test if a value is TRUE or FALSE
{
    if (is_bool($value)) return $value;

    // a string field may contain several possible values
    if (preg_match('/^(Y|YES|T|TRUE|ON|1)$/i', $value)) {
        return true;
    } // if

    return false;

} // is_True

This allows me to deal with all possible combinations with a simple function call, so it's not as stupid as it looks.

This is PHP 4 code

A clueless newbie called 0x18 posted this comment:

Interface? This is PHP 4 code.

It may come as a great surprise to you, but a great deal of the functionality which existed in PHP 4 still survives to this day in PHP 7 simply because it is useful. While there have been numerous additions and changes with PHP 5 and PHP 7 I have ignored most of them for one simple reason - I cannot find a use for them. Some of the additions provide functionality which I do not need, while others simply provide a different way of doing something that can be done already. I am an old school engineer who follows the maxim "if it ain't broke don't fix it", which means that if I already have code which works then why should I spend time and effort in changing it so that it produces the exact same result, but differently? I have to weigh up the cost of making the change with its benefits, and if there are no visible benefits then any effort would be a waste of time.

A prime example of this concerns arrays. In all versions of PHP an array can be constructed with code like this:

$array = array(1,2,3,4,5);

PHP 5.4 introduced the short array syntax which allows the same result to be achieved with slightly fewer keystrokes:

$array = [1,2,3,4,5];

While some dimwits out there may think that this is a good idea, I do not, and I do not see the point in trawling through my entire code base, which has been continuously growing since 2003, to make a change that has zero benefit. Some of you may think that employing the latest addition to the language means that you are "with it" and "fashionable", and if you don't you are "out of date" and writing "legacy code", but I do not. I see my job as the ability to write code which solves problems for my paying customers, and once I have solved a problem I file the code away and move on to the next problem. My paying customers are only interested in code which is functional, not fashionable, and they are only willing to pay me for dealing with a change in functionality, not fashion.

This approach also avoids the problem highlighted in When is Enough, Enough?.

I am not the only one who thinks that using the latest features in the language simply because they are shiny and new may not actually be a good idea. This is known as the Magpie Syndrome and is discussed by Matt Williams in his article Oooh Shiny! Magpies don't know what's just enough! as well as Does Your Team Have STDs?

This class is utterly terrible

A clueless newbie called codays posted this comment:

Yes, the class is utterly terrible, ....

There then follows a list of complaints which I shall address one at a time.

it violates every principle of software engineering

If you mean the The basic principles of OOP then you should understand that I have managed to run through all the crap written about OOP and have managed to filter out what OOP is as well as what OOP is not.

If you mean the SOLID principles then you should read why I think that they are not so solid after all. I cannot follow those principles which do not apply, and I will not follow those principles with which I do not agree.

As for other principles such as seeking high cohesion and loose coupling, if you bothered to read my code properly and compared it with the crap that you obviously write, you should see that I score high marks in both categories.

According to the Gang of Four my use of an abstract class which is inherited by concrete classes is the best way to avoid problems with inheritance, and as multiple inheritance is not supported it should be obvious that the same result cannot be achieved with multiple abstract classes. It should also be obvious that instances of the Template Method Pattern, which is used quite heavily in the RADICORE framework, must be defined in a single abstract class.

Writing code is more about achieving results as quickly and efficiently as possible and less about following a series of artificial rules. It is more about pragmatism and less about dogmatism.

is deeply unmaintainable

Really? I have had absolutely no problem in maintaining and enhancing this code since its inception in 2003, and neither has my business partner and his team of programmers.

exhibits a weak grasp on boolean logic and how basic control flow constructs work

You are talking out of the wrong end of your alimentary canal.

disagrees with any sensible style guide that has ever or will ever exist

Rubbish. There is absolutely no such thing as a single style guide which every programmer on the planet is obliged to follow. I have been programming for over 30 years, and I have been on many different teams for many different companies, and each of them had their own style guide. Every one of these style guides was different, sometimes contradictory, so it was impossible to follow all of them all of the time. Some of my experiences have been documented in Development Standards - Limitation or Inspiration? and On not using the "right" standards.

trashes the SRP so hard that it's almost painful to look at

Then you clearly do not understand the true meaning of SRP.

and reads a bit like the result of just running the last twenty Daily WTF posts through a shredder and then having a blind man glue the results back together randomly

By saying that you are showing that you have done nothing more than noticed that my code does not follow the same rules as yours, and it does not adhere to the same coding style as yours. But why should it? There is no such thing as a single set of rules or a single programming style which every programmer is obliged to follow as different groups of programmers adopt whatever rules or styles which suit them best. What one group defines as excellent another group could define as excrement. This idea is expressed in the phrase One man's meat is another man's poison.

The idea that you should not have more lines of code in a method than can fit into a single screen on your monitor because your brain cannot cope with more than one screen full of data at a time is quite ludicrous. A typical object may require hundreds lines of code to deal with all of its business rules, so when you are maintaining or debugging it you need to be aware of all those lines. If you don't have the brain capacity to deal with that number of lines in a single class then you sure as hell would struggle even more if those lines were split across multiple classes.


A message for Robert C. Martin

A clueless newbie called Martel_the_Hammer posted this comment:

Robert Martin would shit bricks if he saw this...

To which that clueless newbie called Hall_of_Famer replied:

Uncle Bob's reaction:

https://cdn.discourse.org/sitepoint/uploads/default/23597/79c18c0a5d43158a.jpg (broken link)

That link pointed to an image which did not contain an intelligible response, so my message to Robert C. Martin is this:

You really need to brush up on your communication skills. Your original definition of SRP, that of "reason for change", was so woefully inadequate and imprecise that it was open to far too much interpretation. Some clueless newbies took the idea of splitting so far that they would take a perfectly cohesive module and split it into tiny fragments, thus decreasing cohesion and increasing coupling, both of which are deemed to be bad things. Some even think that SRP is completely different from Separation of Concerns (SoC) for such ridiculous reasons as:
You eventually provided a more meaningful definition by identifying three areas of logic - UI, business rules and database - which incidentally creates the same levels of separation as the 3-Tier Architecture on which my framework was based from the outset, but even this can be perverted by some. For example:
If you were any good at your job you would be able to provide a more meaningful description, with examples, of what this principle really means so that it would be less confusing for all those clueless newbies out there.

The problem with the idea that you should take a large piece of code which does "too much" and break it down into smaller cohesive modules each of which does "just enough" is that if you go too far you will end up with a plethora of tiny modules each of which does "too little". So how do you recognise "too much", "too little" and "just enough"? This question was raised by Brandon Savage in his article Avoiding object oriented overkill in which he said:

The concept that large tasks are broken into smaller, more manageable objects is fundamental. Breaking large tasks into smaller objects works, because it improves maintainability and modularity. It encourages reuse. When done correctly, it reduces code duplication.
...
But once it's learned, do we ever learn when and where to stop abstracting? Too often, I come across code that is so abstracted it's nearly impossible to follow or understand.

For me the definitions of "too much" and "too little" are quite straightforward:

It's not the Rules which count, it's the Results

Whenever I am told "You are breaking the rules!" my immediate response is to ask "What rules?" There is no single published set of rules which all programmers are obliged to follow, only a mish-mash of genuine rules, guidelines and personal preferences. Quite often a "rule" by one person can be totally contradicted by another, so whose version is correct? This topic is discussed further in You are not following Best Practices.

The big problem is that these "rules" never originated from a single authoritative source, they have been added to and re-interpreted over several decades by any Tom, Dick and Harry with an opinion. This is like trying to combine the recipes from a multitude of different cook books and expecting the result to be a gourmet meal when in fact it is more likely to be a dog's dinner.

Those who think that by following the rules the results which are obtained are automatically acceptable are nothing more than dogmatists. Those whose primary concern is the result, and who ignore any artificial rules which impede that result are called pragmatists. This topic is discussed further in The difference between "dogmatic" and "pragmatic".

What you clueless newbies totally fail to take into consideration is the results of my approach, and these results can only be achieved by following those rules which can be proved to be beneficial and ignoring all the others. This is mentioned in the results of my approach.

As has already been stated in What OOP is the basic definition is as follows:

Object Oriented Programming is programming which is oriented around objects, thus taking advantage of Encapsulation, Polymorphism, and Inheritance to increase code reuse and decrease code maintenance.

The idea is that the more reusable code you have at your disposal then:

I have used my heretical methods to build a large enterprise application which consists of 400+ database tables and 3,500+ user transactions, and the amount of reusable code beats your paltry offerings into a cocked hat:

The only unique components which have to be produced are as follows:

After having created a new table in my database I can use my heretical methods to do the following:

I can do all this in 5 minutes without the need to write any code - no PHP code, no HTML code and no SQL code. If you cannot achieve the same level of productivity with YOUR development environment I strongly suggest that you stop telling me that my obviously superior methods are wrong and start learning how the experienced pragmatists can write better code than you clueless newbie dogmatists.

Here endeth the lesson. Don't applaud, just throw money.

Comments from the not-so-clueless

Believe it or not there was a comment from someone who could not see anything wrong with my approach.

A wise person called KiwiThunda made this comment:

This has the single responsibility of being a working back-end. I see nothing wrong here.

Comments from other reddit posts

When I post something on reddit I try to make a valid point and invite others to enter into intelligent debate, but sadly the vast majority of respondents are incapable of such a simple task. They instead prefer to replace intelligence with ignorance, to replace debate with insults and falsehoods. Instead of "reddit" this forum should be called "cesspit". Here are some recent examples:

  1. In this comment a confused individual called Hall_of_Famer wrote:
    You dont even understand OOP at all
    to which I replied
    What aspects of OOP do I not understand? I have written extensively on such topics as encapsulation, inheritance, polymorphism, coupling, cohesion, design patterns, frameworks, dependency injection, Object-Relational Mappers, singletons, Domain Driven Design and the SOLID principles, so can you explain in plain English exactly why my understanding of any of those aspects is wrong? All you need do is pick just one of the questions in my Pop Quiz article and explain either why the question or the answers I have provided are invalid.
    As I expected he could not explain why anything I wrote on any single aspect of OOP was wrong. That just tells me that he cannot explain why it is wrong, and that just reinforces my opinion that it is NOT wrong at all.
  2. In this comment the same Hall_of_Famer said the following:
    your alternative to DI was proven to be ineffective and outdated years ago and theres no amount of time and effort you can take to overturn this proven fact.
    I pointed out two terminological inexactitudes in that single statement:
  3. In this comment the same Hall_of_Famer made the following claim:
    I am a better and more productive programmer because almost everyone on this reddit will agree with me
    to which I answered:
    Where is the proof? Where have you posted any code samples that you have written so that people can judge for themselves instead of having to take your word for it?
    He responded with:
    Not like you can prove you are more productive at all.
    I informed this person of questionable intelligence that the "proof" could be found in this challenge where I demonstrate that using my framework I can take the definition of a database table, load it into my Data Dictionary at the press of a button, create the class file for that table at the press of a button, then create and run a family of six tasks to maintain the contents of that table at the press of another button, all in the space of 5 minutes and without having to write a single line of code - no PHP, no HTML and no SQL. That is the level of productivity which *I* can achieve, so if you think you are more productive with your methods then you have to prove it by bettering that 5 minutes. Instead of putting his money where his mouth is he bottled out by saying:
    I will not take on your challenge since you aint qualified to make one
    That just proves to me that he is all mouth and no trousers, someone who can talk-the-talk but not walk-the-walk, he is all wind and piss.
  4. In this post a respondent called hubeh made the following criticism:
    This method literally has a comment which says "perform custom formatting before values are shown to the user." By your own words ("Display logic is that logic which transforms that data into the format required by the user"), that is display logic inside your model class.
    to which I gave this reply:
    You obviously do not understand the difference between display logic in the presentation layer and display logic in the business layer. That method called _cm_formatData() which exists in the business layer is concerned with changing the contents of individual fields before the entire set of data is given to the presentation layer. Other formatting may change the way in which date fields are displayed, or to use the correct thousands separator for large numbers. That is business logic and is therefore allowed to exist in the business layer.

    The presentation layer, on the other hand, does NOT change the contents of individual fields, it takes the entire data set and transforms it into the document type required by the user. This is usually HTML, but could be CSV or even PDF.

    Nowhere in the business layer does it write to the HTML, CSV or PDF document. Nowhere in the presentation layer does it perform any business logic.

    This is the CORRECT separation of logic according to my interpretation of both the 3-Tier Architecture and the MVC design pattern.
  5. In the context of the 3-Tier Architecture the presentation/display logic in the Presentation layer is responsible for transforming the data obtained from the Business layer from its internal format, which is a PHP array, into a different format which is more presentable to the user, such as HTML, CSV or PDF. There is no code in the Business layer which performs this transformation, so it is completely wrong to say that there is presentation logic in the Business layer. The "formatting" logic in the Business layer does not transform the PHP array, it does nothing but format dates and decimal numbers within the array according to the user's language preferences.

  6. In this post the same hubeh wrote the following:
    And your methods are not different. They are not innovative. The sort of code you are writing has been done by pretty much everyone when they first started programming. We all wrote code like that at first!
    You are contradicting yourself and all my other opponents on this thread. You all claim that my methods are wrong because they ARE different, and now you are saying that they are not different at all, so which is it? If my methods are not innovative then they would be the same as yours, and if they are wrong then you would be too! There is no evidence that anyone ever wrote code using the same style as me and gave it up as a bad job! Can you point to any article which says I used to do it this way but I gave it up because ...? On the contrary, my methods are full of innovations simply because they ARE different. Look at the following list:

    Can you point me to any other framework that offers that volume of polymorphism? Can you point me to any other framework that supplies pre-written and reusable Controllers and Views? Can you point me to any other framework that produce over 3,000 different HTML documents from just 12 XSL stylesheets?

    If I were to do everything the same as you then I would be no better than you, and I'm afraid that your best is simply not good enough. In order to do better I have to start by being different, yet all you and all your cronies can do is say "Your methods are different, you are not following the same rules as us, therefore your methods are wrong!"

  7. In this post the same hubeh wrote the following:
    No, they are pointing out that your code follows your own twisted interpretations of those principles. Everyone else has a common understanding of these principles, you are the only one who is struggling.

    This is the reason we do not put SQL in JSPs. This is the reason we do not generate HTML in the modules that compute results. This is the reason that business rules should not know the database schema. This is the reason we separate concerns.
    He's referring to separation of concerns here, a completely different principle. This is just a comparison because it's a basic concept that anyone can grasp, even you. He is most certainly not suggesting that you achieve SRP just by separating those 3 layers.
    My reply pointed out that my interpretation of SRP is based on what he actually wrote, not what he didn't write.
    I am following the words that he actually used, not the words which he didn't use. When he specifically identifies UI logic, business logic and database logic as being separate responsibilities then how can you say that my splitting of those three areas of logic into three separate components is a twisted interpretation of what he wrote?

    His article is only talking about a single principle, and anybody who understands English will tell you that "responsible for" and "concerned with" mean exactly the same thing. He never says that once you have followed SRP you must follow it with SoC, he never says or even hints anywhere that SoC is a completely different principle, so you are using an interpretation which is not supported by the facts.

    His reply shows that his thought processes are so out of touch with reality I'm surprised that he is allowed out of the house without adult supervision:
    I am following the words that he actually used, not the words which he didn't use.
    Oh you follow his words, just completely out of context. You're essentially the cassetteboy of programming, mixing and matching what he says to form some kind of interpretation.

    How can you say that my splitting of those three areas of logic into three separate components is a twisted interpretation of what he wrote
    If you tell me that is separation of concerns then fine. If you tell me doing that means you have achieved SRP then that is a twisted interpretation.

    His article is only talking about a single principle
    So because his article is talking about one principle he can't make reference to another? The level of mental gymnastics you are performing to keep up this whole illusion continues to amaze me.
    I replied by quoting the words that Robert C. Martin actually wrote on the subject of SRP. Note that I *DID NOT* cut words out of different sentences and paste them into different sentences, I quoted complete and unedited sentences. How anybody can suggest that I am quoting his words out of context is beyond me.
    You left out the bit where you claim that doing that achieves SRP. That is where you take his words out of context.
    You are obviously not reading what Uncle Bob wrote. In Test Induced Design Damage? he wrote the following:
    How do you separate concerns? You separate behaviors that change at different times for different reasons. Things that change together you keep together. Things that change apart you keep apart.

    GUIs change at a very different rate, and for very different reasons, than business rules. Database schemas change for very different reasons, and at very different rates than business rules. Keeping these concerns separate is good design.

    Here he is identifying three areas of logic which have different "reasons for change" and which are different "concerns".

    In his article The Single Responsibility Principle he says the following:
    This is the reason we do not put SQL in JSPs. This is the reason we do not generate HTML in the modules that compute results. This is the reason that business rules should not know the database schema. This is the reason we separate concerns.

    Another wording for the Single Responsibility Principle is:

    Gather together the things that change for the same reasons. Separate those things that change for different reasons.
    If I am quoting the words that he wrote where he explicitly states that UI logic, business logic and database logic each have separate "reasons for change" how can you possibly claim that I am mis-quoting him or taking his words out of context. What context is he using, and how is my context any different?
    Far too many people complain that my interpretation of SRP is wrong simply because it does not follow their interpretation, but their interpretation converts "reason for change" into a set of arbitrary numbers such as "no more than X lines of code in a method" and "no more than Y methods in a class". This just proves that "reason for change" was such a pathetic description in the first place, and that they have replaced their ability to think with the ability to count. I suspect that the reason for the actual values for X and Y in the previous statements not being greater than 10 is that they cannot count any higher without taking their shoes and socks off.
  8. In this post a respondent named secretvrdev wrote the following:
    To be fair this guy jumped on the wrong IT train back in the days and missed the cool stuff the last 20 years. How would you feel like stuck in these days?
    This person knows nothing of my history, yet feels knowledgeable enough to make such a ridiculous claim. The facts tell a different story as I outlined in my reply:
    When you call me a dinosaur who's stuck in the past and hasn't learned anything new in the 20 years I'm afraid that you are talking out of the wrong end of your alimentary canal.
    • I started programming in the 1970s using COBOL on a mainframe with punched card input.
    • In the 1980s I moved to mini-computers with green-screen terminals using COBOL and a mixture of hierarchical and network databases.
    • In the 1990s my employer switched to the UNIFACE language, Windows-based micro-computers (that's a PC to you clueless newbies) and relational databases.

    At the start of this century I decided to move from desktop applications to internet applications which involved learning new things:
    • PHP, with its OO capabilities
    • HTML
    • CSS
    • SQL (for MySQL, PostgreSQL, Oracle and SQL Server)
    • XML
    • XSL
    • Web services, using XML-RPC, SOAP, EDIFACT, AS2 and RosettaNet.

    In the last 2 years I have done the following:
    • Changed all the thousands of HTML forms in my ERP application to have a responsive interface. This took just over a month.
    • Added blockchain integration so that I can exchange any application data with any number of nodes in a chain. This did not involve changing any application components, only the framework, and took just over a month.

    Not bad for an old duffer, eh?

References

The following articles describe aspects of my framework:

The following articles express my heretical views on the topic of OOP:

These are reasons why I consider some ideas to be complete rubbish:

Here are my views on changes to the PHP language and Backwards Compatibility:

The following are responses to criticisms of my methods:

Here are some miscellaneous articles:


Amendment History

04 Jun 2020 Added Comments from other reddit posts

Other comments are available on this reddit post where, as usual, adult debate has given way to childish insults.

counter