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

Programmer Productivity takes Precedence over Paradigm Purity

Posted on 10th July 2024 by Tony Marston
Introduction
Not-so-best practices
Comments

Introduction

Let me start with some universal truths:

The topic of "best practices" is often talked about as if it were a set of rules that is cast in stone and universally accepted by every programmer on the planet, but that is not the case. What some people regard as being best for them others will dismiss as second-best or even nowhere-near-best. In the 1980s and 90s I worked in several teams for different organisations, and each team had its own set of programming standards. The idea of a single set of universal standards simply did not exist, mainly because getting a group of programmers to reach a consensus on the definition of "best practice" is like herding cats, with the likelihood of success being inversely proportional to the size of the herd.

In those decades I was mostly employed by software houses where we designed and built bespoke solutions for different clients, and as we had to compete against other software house for business we had to demonstrate that we were the most cost-effective, that we had higher rates of productivity. By the time I became team leader I had begun to formulate my own set of standards by sifting through what I had encountered previously and filtering out any practices which I saw as getting in the way of productivity. I did not follow a rule as if it was cast in stone, I examined it, and if it did not measure up to my expectations I discarded it in favour of something better. By "better" I mean the most cost-effective. This means that I am results-oriented, not rules-oriented. I am a pragmatist, not a dogmatist.

I have built enterprise applications in COBOL, UNIFACE and PHP, and because they are different what works in one language may not work in another. While the objectives remained the same, the means of achieving those objectives were different in each language. In other words "what needs to be done" was consistent, but "how can it be done" is always different, and each team has its own version of "how" based on their set of experiences. It is one thing to learn the capabilities of the language, but it is another to learn how to utilise those capabilities to best effect. Whenever a new version of the language was released I took the time to examine any new features, and if any looked as if they could add value to the code I would evaluate them to compare the costs against their benefits. Anything which enabled me to replace duplicated code with reusable code, and hence increased my productivity, was always beneficial.

When I switched to PHP with its Object Oriented capabilities at the start of this century I carried on with this habit. After learning the mechanics of Encapsulation, Inheritance and Polymorphism I began writing code which incorporated high cohesion and loose coupling to produce the best results with the least amount of effort, thus contributing to higher levels of productivity. After completing several modules I would often see repeating patterns that could be turned into code that could be reused instead of being duplicated. Another practice I follow to reduce the amount of code which I write is not to write code that is not necessary, to always choose the simplest solution instead of a complex one which invariably ends up by resembling a Rube Goldberg machine.

By following only those practices which actively contribute to my high levels of productivity (what used to take me 1 week in COBOL and then 1 day in UNIFACE I reduced to 5 minutes in PHP) I have found myself discarding quite a number of practices and principles which other programmers regard as being sacrosanct. They criticise me for having the audacity to break their precious rules while totally ignoring the results which I have achieved. I single-handedly designed and built the RADICORE framework which I released as open source in 2006, I used this framework to single-handedly design and build TRANSIX, my first ERP package application, in 2008 which has now grown into the GM-X Application Suite which has been sold on three continents.

Not-so-best practices

Ever since I started publishing articles regarding my experiences with PHP other programmers have told me that the code which I write and the methods which I use are completely wrong simply because I am not following the same practices as them. I refute this claim for the simple reason that my methods cannot be wrong simply because they work, and something that works cannot be wrong just as something which does not work cannot be right. I did not follow these practices for one simple reason - I did not know that they existed. When I came to examine them I quickly realised that by changing my code to conform to this "advice" it would have a negative effect on my productivity by using code that was more complicated than mine, more convoluted than mine and less efficient than mine, so I did the only sensible thing which was to ignore it, to consign it to the dustbin, to flush it down the toilet.

To counter my detractors I have written a number of blog posts which identify the "best practices" which I choose to ignore as well as explain precisely why I ignore them and why I believe that my own practices are better. These are listed below:

  1. Object Relational Mappers are EVIL

    The "need" for an ORM is caused by deliberately using one methodology to design the database and a separate methodology to design the software, thereby causing a mismatch. My solution is not to create this mismatch in the first place. I design the database first, then build the software around that design using my framework.

  2. Dependency Injection is EVIL

    Some programmers insist that I use a complicated mechanism to inject every dependency even when there is not a selection of dependencies to choose from. While I do inject entities into services where there are multiple choices, I do not inject entities into entities as there is never more than a single choice.

  3. Not-so-SOLID OO principles

    I only follow those principles which I consider to be appropriate.

  4. I fail to GRASP these principles

    I only follow those principles which I consider to be appropriate.

  5. Singletons are NOT evil

    Singletons can be implemented in one of two ways - either as a separate method within each class, or as a static method within a single singleton class. The latter choice does not have the problems encountered in the former.

  6. Getters and Setters are EVIL

    In each of my table classes I do NOT have a separate property for each column with its own getter and setter, I pass all the data around, both in and out, in a single array argument which is precisely how it is handled in the HTML front end and the SQL back end. This reduces the amount of code which I have to write, and directly contributes to loose coupling which is supposed to be a good thing.

  7. Object Interfaces are EVIL

    I don't use object interfaces as they were invented for a problem which does not exist in PHP. I get better results from using abstract classes.

  8. Object Associations are EVIL

    The "approved" technique is to handle associations and aggregations using custom code with each entity. I prefer to use standard solutions which I have built into the framework.

  9. Inheritance is NOT evil

    The rule "favour composition over inheritance" was formulated by someone who never learned how to use inheritance properly. Instead of inheriting from one concrete class to create a different concrete class you should only ever inherit from an abstract class. As well as giving instant access to reusable code it also enables the Template Method Pattern which lies at the heart of framework design.

  10. Composition is a procedural technique for code reuse

    As an argument against inheritance some bright spark argued that "Inheritance is a procedural technique for code reuse", but as someone who programmed in COBOL, the most widely used procedural language of all time, I know that this is not true. Instead I contend that it is object composition which deserves that description.

  11. Namespaces are for numpties

    Namespaces were added to PHP to solve a problem when importing third-party libraries, but as RADICORE is a framework and not a library the effort of changing my code would be a complete waste of time.

  12. Autoloaders are abominations

    Autoloaders are the solution to the self-inflicted problem of requiring multiple files to be loaded from multiple locations before a class can be instantiated. I only have a single file for each entity's class and I keep the number of locations to a minimum, thus conforming to the principles of Encapsulation and high cohesion and avoiding the problem completely.

  13. Decoupling is delusional

    The idea that "decoupling" your software is a good idea shows a complete lack of understanding of the term "coupling". If there is a call from one module to another then they are coupled whether you like it or not, and the strength of that coupling is either tight or loose. To "decouple" means to remove the call. To introduce a third module to act as an intermediary between the first two does not remove the coupling, it actually doubles it by replacing one method call with two.

  14. Strict typing is for stick-in-the-muds

    PHP was designed from the outset to be dynamically and weakly typed, which means that type errors are not detected until run time, and values can be automatically coerced into the desired type. Millions of programmers have become used to this approach which is also used by 60% of all programming languages. Despite this there are some stick-in-the-muds whose brains are still fixated on the idea that strict typing is "best", so they have forced the language to be modified to suit their preferences. Despite the fact that the use of strict types is supposed to be entirely optional, those ham-fisted core developers made a cock-up made it obligatory for all internal functions.

  15. Value objects are worthless

    OO purist love to say that "everything is an object", which is why they favour the use of value objects instead of primitives/scalars. However, PHP does not have any native support for value objects, and neither does HTML nor SQL, so to use them in PHP would require a great deal of effort. Having successfully used primitives in PHP for the last 20 years I cannot see any benefit in amending my code to use value objects as there is nothing I can do with them that I cannot already do without them, so I regard them as a complete waste of time


counter