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

Namespaces are for numpties

Posted on 27th March 2024 by Tony Marston
Introduction
Name collisions
Name aliases
Conclusion
Links to other pages
Comments

Introduction

Here is a thought that I have been repeating for many years:

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

The indiscriminate use of an idea, principle or practice which turns out to be inappropriate will always be a complete waste of effort, but it could also end up by becoming a hindrance instead of a help. Programmers who implement an idea without thinking, without understanding the logic behind that idea, and without gaining benefit from its implementation are in serious danger of becoming nothing more than a Cargo Cult Programmer. If an inappropriate idea is implemented is should be treated as a violation of the You Ain't Gonna Need It (YAGNI) principle.

Namespaces were added to PHP in version 5.3 with the following explanation:

In the PHP world, namespaces are designed to solve two problems that authors of libraries and applications encounter when creating re-usable code elements such as classes or functions:
  1. Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
  2. Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.

You should be able to see that this feature was designed to be used by those whose code may be plugged into an unknown codebase with an unknown naming convention, and this applies only to the authors of third-party libraries. This means that its use in other places is not actually necessary as the problem for which it is the solution does not actually exist. This leads me to a second thought which I have also been repeating for many years:

If I don't have the problem for which that solution was devised then surely I don't need that solution.

If you implement a solution that you don't actually need, then surely you are violating the You Ain't Gonna Need it (YAGNI) principle. If you spend time adding code that does not do anything nor provide any benefit then surely you are wasting your time. How can doing either of those things be justified?

I developed my framework years before namespaces became available, and I never had any issues. Now that they do exist I see no point in refactoring my code as it would be all cost and no benefit.

Namespaces did not exist in PHP until version 5.3.0, and their use is entirely optional, but should you use them or not? In my humble opinion their use should be avoided in your code unless the potential for name collisions with somebody else's unknown code actually exists. In any PHP application the names used can appear in one of the following levels:

  1. The PHP language itself, known as PHP core.
  2. In an optional extension, which is a pre-compiled object written in C and documented in the PHP manual.
  3. Application code.
  4. Third-party libraries, such as those to be installed via composer.

Name collisions

Problem #1: Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.

Name collisions can only occur when code from two of these levels is mixed when names used in a lower level clash with names used in a higher level. Functions and classes inside PHP core (level 1 above) do not need to use namespaces as this is at the top level and has nothing with which it can clash.

When writing a PHP extension (level 2 above) the practice has always been that each extension has its own unique mnemonic, as documented in the PHP manual, which is used as a prefix in all class and function names. As an example the different database extensions prefix their query function with the extension name, as in mysqli_query, pg_query and sqlsrv_query. Methods inside a class need no such prefix as it is only the class name which need be unique. No extension can be released if it has names which clash with either PHP core or another extension. This convention has been in operation for several decades and has worked flawlessly, so why change it?

When writing application code (level 3 above) the developer should not use a name which is documented in the PHP manual, either within PHP core or an extension, as this would generate an error and the code would refuse to run. This is an error which the application developer should correct in his own code by using another name.

When writing a 3rd-party library (level 4 above) the library developer has no knowledge of any application in which it may be incorporated, so it is possible to use both class and function names which may already be used within that unknown application. Collisions are avoided by using a namespace which usually incorporates a unique mnemonic similar to that used in extensions (level 2). In this way none of the code within any 3rd-party library can ever clash with any other code. Nowadays the standard practice is to install 3rd-party libraries via composer which forces the use of namespaces. When using an older library which is not installed via composer or which does not use namespaces then collisions may occur and will be cumbersome to resolve.

The only time that name collisions could legitimately occur is when adding third-party libraries (level 4) into application code (level 3), but as this is done nowadays via composer which requires the use of namespaces the potential for any collisions is avoided.


Name aliases

Problem #2: Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.

This to me is a cure for a self-inflicted problem which was caused by feeble-minded programmers who are following the "suggestion" made in Robert C. Martin's article One Thing: Extract Until You Drop which states the following:

For years authors and consultants (like me) have been telling us that functions should do one thing. They should do it well. They should do it only.

The question is: What the hell does "one thing" mean?

Is a function doing one thing if, and only if, you simply cannot extract any other functions from it? What else could "one thing" mean? After all, If I can extract one function out of another, the original function must have been doing more than one thing.

As an example he takes a class that contains three functions (methods) with 25 lines of code and converts it nine functions with 49 lines of code. In it you see that 4 of those functions contain only a single line of code while the others only contain two lines of code each. As a result of adding more and more functions he has had to create longer and longer names so that each name helps to identify what that function actually does. After all, it would be considered bad practice to give a function a name which is meaningless.

I personally think that this level of extraction goes too far. Calling each line of code a "single thing" which can be put into it own method does nothing but make the code more bloated and difficult to follow. It is easier to just write a line of code than it is to call a method that executes that line of code. It is also easier to read as you can see what statement is being executed immediately instead of having to hunt for that method and then examine its contents. My philosophy has always been to start with all code in a single function. As the function may require several steps I keep all the code for each step together with a comment at the top to briefly describe what the step does. I also put a blank line before each comment to separate it from the next step. In this way each step has its own block of code, and you can easily separate one step from the next. The only time I would extract a block of code into a separate function would be for one of the following reasons:

  1. I need to execute that block of code in another place, it which case I pull it out and convert it into a reusable function.
  2. It is a large block of code which is subject to an IF condition or a loop, in which case it makes the code more readable (in my opinion) to move that code into its own function (with a meaningful name, of course).

Note here that I do not keep extracting blindly just because I can, I only extract when it makes sense to me, to make the code more readable in my eyes. There is no hard and fast rule which is carved in stone and carried down from the mountain top, it is purely subjective, a matter of personal preference or aesthetics.

The end result of following this dubious practice is the proliferation of one-line functions with longer and longer names so that you can differentiate one function from another. Even worse is the practice, which I am seeing in more and more in third-party libraries which are installed via composer, of putting each of these small functions into its own class and even its own subdirectory so that if method#1 calls method#2 then the class which holds method#2 is in a subdirectory below the directory which holds the class for method#1. This means that instead of having a single class which exhibits high cohesion you have a jumble of subclasses which are held in a jumble of subdirectories. I don't know about you, but this makes it VERY difficult and time consuming to follow a path through the code.

This to me is a prime example where following a practice without thinking it through has unintended consequences which are far worse than the theoretical problem which you are attempting to solve. If I think that following a "suggested" practice makes the code less readable then I will move that practice from the suggestion box and straight into the rubbish bin where it belongs.


Conclusion

While some application developers think that using namespaces in their code is a good idea it actually is not. The potential for name collisions with third-party libraries which are installed via composer has already been negated, so the only possible collisions are with PHP core or an extension, in which case the developer should choose a different name. Namespaces in application code are therefore redundant. The could be used, but they would be solving a problem which does not exist.

Similarly the PHP core developers need not worry about name collisions as they only concern application and library developers. If a core developer uses a name that already exists in core then his code will fail to compile and he will have to choose a different name.

While some people say that now namespaces exist they should be used everywhere whether they are useful or not I believe that this would violate the YAGNI principle. When people look at my code and ask me why I don't use namespaces they do not seem to understand when I answer "Because I don't have the problem which they solve". They respond with "But you are not keeping up with changes to the language". They seem to think that just because a new feature has been added to the language then I should use it to make my code somehow "better" or "up-to-date".

Namespaces are only necessary in 3rd-party libraries, and as these are installed via composer which already requires the use of namespaces, the potential for name collisions no longer exists.

So, to the question "Is there a case for adding namespaces to PHP core?" my answer is "No, there is not".

To the question "Is there a case for adding namespaces to PHP extensions?" my answer is "No, there is not".

To the question "Is there a case for adding namespaces to application code?" my answer is "No, there is not".

To the question "Is there a case for adding namespaces to 3rd-party libraries?" my answer is "Yes, but these are (or should be) installed via composer which already requires the use of namespaces".

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


Links to other pages

These are reasons why I consider some ideas on how to do OOP "properly" to be complete rubbish:


counter