Home » Php » Should we namespace functions in PHP?

Should we namespace functions in PHP?

Posted by: admin July 12, 2020 Leave a comment

Questions:

We all know that namespacing your application code is a best practice and a PSR recommendation. The only thing PSRs take stance on is the whitespace and side-effects when it comes to functions and their declaration.

But what about functions which are not related to any single class? Should they be namespaced or left in the global namespace?

Some developers are saying that namespacing functions is bad practice but I wasn’t able to grasp why.

From what I’ve learned/read and seen recommended regarding to namespacing functions:

  • NO: Don’t use global functions without classes as they cannot be auto-loaded (this means creating supporting static classes or similar).
  • NO: Don’t use global functions as they cannot be imported/used (fully qualified function name is always needed).
  • YES: Use namespaces for global functions to prevent collisions and to denote functions that are not part of PHP itself (you can safely assume you’re calling the correct function).
  • NO: Don’t use namespaces for global functions because the functions are not tied to a OO application structure anyways (has a point, but see previous point).

Are there best practices for global functions and namespacing them? Currently I use the application root namespace for global application related functions, but I keep wondering why some people strongly believe no namespacing should happen outside objects (classes, interfaces, traits, etc.)?

How to&Answers:

Namespaces are a concept that allow you to impose a structure on smaller-scale constructs. With namespaces, you can put things together that belong together. It doesn’t matter whether these things are classes or functions. If you have a free function that is only used together with two or three specific classes, I’d certainly put that function in the same namespace as the classes.

Whether or not you want to use free functions at all is a different question. Many OO languages such as Java and C# don’t support them. But there are cases where a function just doesn’t fit into a class. In these cases, I prefer creating free functions (in the appropriate namespace).

That being said, I’m pretty sure you will get both YES and NO answers here on SO as well. So discuss it with your team, and establish a guideline.

Answer:

[…] I keep wondering why some people strongly believe no namespacing
should happen outside objects (classes, interfaces, traits, etc.)?

To me it’s convoluted thinking. A name is a name. It shouldn’t matter what it belongs to.

Namespaces are organizational tools for names. Before they existed, people often used naming conventions like prefixes to avoid clashes, like ike_rsqrt. Namespaces take that kind of convention and turn it into a formal language feature, and by doing so, allows some additional options like aliasing in addition to promoting a more consistent way to do it.

The benefits of namespaces apply to names — it should matter little what a name belongs to, so long as a name exists that can possibly clash with another. Any thought revolving around namespaces that considers significantly more than that is probably complicating the issue. Namespace aren’t so abstract, they aren’t so magical. And they’re intended to be general-purpose. We might look at them beyond naming and in terms of packaging and cohesion, but that likewise applies even when adopting a prefix-based convention in a language lacking namespaces — mostly an identifier shouldn’t be exempt from this kind of organization merely because of what it identifies. How things are organized is an interesting question revolving around cohesion: whether things should be organized based on their type isn’t so much.

A name is a name. Namespaces are intended to tackle the issue of identifier clashes and organization, and especially among disparate libraries of code. It superficially diminishes their usefulness to suggest they should only apply to one kind of identifier but not another.

Answer:

But what about functions which are not related to any single class?

In my code I usually do not use pure PHP functions at all. I prefer static methods of classes. If I have some functions, which will never need any state, I group them into some static class by function and place this class into appropriate namespace. For example, \Util\Str::camelize() or UI\Util\TextCleaner::prettifyHtml().

Should they be namespaced or left in the global namespace?

Namespacing allows not only solve a problem with name clashes. Namespacing serves the most important purpose of all: it helps slicing your application into modules, which are something logically complete and can be understood by a developer as a whole. A module should follow SRP itself.

So, I believe you should namespace functions also. I do not think there can be function, unrelated to anything in the project so that you could put it into a global namespace.

NO: Don’t use global functions without classes as they cannot be
auto-loaded (this means creating supporting static classes or
similar).

I think this is important enough reason. Using include() pollutes the code and is error prone. It clouds our project vision 😉

NO: Don’t use global functions as they cannot be imported/used (fully
qualified function name is always needed).

Well, this also a valid reason to me, although slightly less important. I prefer not to use fully qualified names in my code to increase readability. I tend to create modules / classes with a strong cohesion so that there is no need for long names for the sake of understandability.

YES: Use namespaces for global functions to prevent collisions and to
denote functions that are not part of PHP itself (you can safely
assume you’re calling the correct function).

I guess this is a little irrelevant to software design. You should focus on maintaining SOLID across your application. Not just to prevent collisions. If you follow SOLID, collisions are…well, rare.

NO: Don’t use namespaces for global functions because the functions
are not tied to a OO application structure anyways (has a point, but
see previous point).

I guess this is also a point I already expanded upon.

Are there best practices for global functions and namespacing them?

Yes. But don’t expect something “use this, don’t use that” from me. You should not blindly follow some syntactical best practice you encountered in the internet. Object oriented design should guide your reasoning, not some dogmatic rule about namespacing functions or not.

Currently I use the application root namespace for global application
related functions, but I keep wondering why some people strongly
believe no namespacing should happen outside objects (classes,
interfaces, traits, etc.)?

Well, I don’t know. If something has no real state, you have every right to make it a function and namespace it as you like. But function namespacing has some limitation against class namespacing so I tend to use classes anyway.