On PHP 5.3's Namespace Backslash Backlash: The PHP InternalsTeam was Right?

July 31, 2009

When the PHP internals team announced that it would be using the backslash as a namespace separator my stomach turned a bit. I wasn't alone. But why the backslash? The whole debacle last October left an awful taste in my mind. It killed the anticipation of transitioning the Recess Framework to native namespaces. Was PHP dying the slow death it seemed? The dread of it enabled me to put off using namespaces until forcing myself to this week.

Putting off moving forward with namespaces until now was a big, regrettable mistake.

Prior to native namespace support frameworks and libraries could optimize for either:

  1. Simple class names, at cost of higher collision potential.
  2. Few class name collisions, at cost of convoluted class names.

Since 2003 I've been using a Library class that simulates namespace-style naming and importing, allows for sensible source code organization, and optimizes for simple class names.

<?php
// Recess Namespace Work-around Pre 5.3
// In Folder: recess/db/orm/
Library::import('recess.lang.Object');
class Model extends Object {}
$model = new Model();
?>

In the PHP community at large this wasn't the recommended style because of the higher likelihood of class name clashing. The recommended style, that PEAR and Zend standardized around, brings the namespace information into the classname itself and would look like this:

<?php
// Community Standard Namespace Work-around Pre 5.3
// In Folder: recess/db/orm/
class Recess_DB_ORM_Model extends Recess_Lang_Object {}
$model = new Recess_DB_ORM_Model();
?>

The upside of the PHP community-at-large solution is a simple autoloader can replace underscores with slashes and you'll find the file. You're also unlikely to find someone else who wants to name a class Recess_DB_ORM_Model. (I'm not sure you'll find anyone who wants to name a class that.)

The bottom line is without namespace support PHP developers had to make really dumb trade-offs. Either use ridiculous class names like 'Zend_Gdata_Calendar_Extension_Timezone' or accept that clashing could happen if you're trying to mix and match lots of 3rd party libraries.

Finally namespaces in PHP 5.3 remove the need for any of these trade-offs, and even with backslashes, are a joy to use:

<?php
// Namespacing with 5.3
namespace recess\\db\\orm;
use recess\\lang\\Object;
class Model extends Object {}
$model = new Model();
?>

The good news for Recess is that this means updating the codebase involves adding a namespace directive to the top of each class file and changing all occurances of "Library::import('foo.bar.Class');" to "use foo\\bar\\Class;" and we're pretty much set.

After using namespaces in 5.3 I'm more than sold, I'm in lust. Contrary to my initial, reactionary beliefs PHP's new namespaces are incredibly well thought out and incredibly well implemented. Sure, they'd look a lot better if they were in the language from the start, but so goes the life of a language whose design is driven by demand and not theory.

Namespaces are not going to be the straw to break PHP's back, in fact, they're likely the brace that saves PHP's back. Of all of 5.3's new features including lambdas/closures, late static binding, etc., namespaces are the feature that will impact the community-at-large the most by enabling consistency between 3rd-party libraries with no naming ugliness or compromising.

So Why all the Bikeshed Discussion on HN and Proggit?

I remember that sinking moment in October when I saw the thread on HN revealing the new namespacing scheme. I read the PHP internals team discussion on it. I ran into Joel's office and lamented over PHP. "Idiots! They considered using the smiley face as a namespace seperator! Are they trying to kill PHP?" My gut reaction was along the lines of most of the responses on HN. It looked like a bad idea, it read like a bad idea, it felt like a bad idea.

In retrospect the circus of negativity around the new namespaces boiled down to three things:

  1. As programmers and language lovers it's really easy to get drawn into a heated bikeshed debate on something as trivial as the character a language chooses for delimiting a new token in their programming language.
  2. It's easy to dismiss PHP's every move as a programming language. What's hard to appreciate is that PHP is the most widely used dynamic language that exists. The internals team carries the weight of knowing when they change the PHP language it has wider-ranging impact than every other dynamic language.
  3. The internals team dropped the ball when communicating the change with the outside world. After using namespaces it is clear that the IRC conversation and wiki-justification did not capture or express the amount of forethought that went into PHP's new namespace design. Reading the IRC log it's easy to conclude "these people are idiots!", but after using what they were deciding upon it's easy to conclude "these people are brilliant!"

Still don't believe me? Before reacting try building something with it.

The future of PHP is looking bright again, folks, much thanks to the internals team. The bad news is for language lovers: your prettier, princelier languages won't be killing the homely, pragmatic monster anytime soon. PHP is now much stronger as language and a platform repositioned for growth.

Comments

Dave's avatar
Dave
I see less of a type-ability/readability issue with this:
protected $middleware = [
/App/Http/Middleware/CheckForMaintenanceMode::class,
/Illuminate/Foundation/Http/Middleware/ValidatePostSize::class,
/App/Http/Middleware/TrimStrings::class,
/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull::class,
/App/Http/Middleware/TrustProxies::class,
];
than this:
protected $middleware = [
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
The former clearly delineates the path-like structure of the namespaces while being easy to type and distinguish from actual file paths that would be in single/double-quotes (and likely colorized differently in your editor), and I'm not seeing where the namespace paths with slashes (forward) would collide with anything (other than someone just not liking it).
Dave's avatar
Dave
Forward-slashes are easier to read and type... I don't know why anyone thinks backslashes are.
Branko Vukelic's avatar
Branko Vukelic

PHP namespaces just make sense. Period. I've only recently started coding in PHP, and 5.3 release was a long time ago when I started. I was using namespaces after a day. I don't understand what the fuss is about them. I really like how they are implemented.

 AlmostAlive's avatar
AlmostAlive

@Kris I've read that link and I understand it. They treat namespace access and static class access as different things. If they were the same, and namespaces and classes shared the same hash, and static class access and namespace access where the same (like in C++) this would be a non-issue.

As for your ambiguity, it's a simple name clash. On the second declaration, you should get an error because foo::bar is already defined. You know, like you would in C++.

 AlmostAlive's avatar
AlmostAlive

@Kris I've read that link and I understand it. They treat namespace access and static class access as different things. If they were the same, and namespaces and classes shared the same hash, and static class access and namespace access where the same (like in C++) this would be a non-issue.

As for your ambiguity, it's a simple name clash. On the second declaration, you should get an error because foo::bar is already defined. You know, like you would in C++.

 Kris Jordan's avatar
Kris Jordan

Here is an example of an ambiguous case:

// classes.php /////
namespace foo::bar;
function baz() {}
namespace foo;
class bar { static function baz() {} }

// someotherfile.php /////
include('classes.php');
foo::bar::baz(); // Ambiguity
/////

A proposed work around for the ambiguity was using explicit imports in ambiguous cases.

The internals team *wanted* to do ::, they *did* ::, and they convinced themselves otherwise (and suffered through a lot of pain in the process).

[17:00:05] <@CelloG> I am the strongest advocate for :: - every patch I have made up to this one was designed to preserve it, and I am convinced it just isn't technically possible to use it

http://wiki.php.net/rfc/backslashnamespaces#resolution_of_t_string_t_paamayim_nekudotayim_t_string_and_why_this_kills_as_namespace_separator

 AlmostAlive's avatar
AlmostAlive

@Kris -- It's obvious it could be implemented without breaking backwards compatibility. PHP didn't have namespaces, so there isn't anything to break.

namespace foo1; function bar();
class foo2 { function bar(); }

foo1::bar(); // Namespace call
foo2::bar(); // Static method call

namespace foo2; // Syntax error; class foo2 already exists.

The problem is, the internals of PHP are that namespaces and classes are in different hashes and the call to either compile to entirely different byte code. The "correct" implementation would have namespaces and classes together and both calls compile to the same code. Now I accept that the PHP internals are perhaps too convoluted to resolve this issue but that doesn't make this any less terrible. It's a hack solution.

 Kris Jordan's avatar
Kris Jordan

@Gavin - you would not call a function in a namespace like that. You would simply reference it with the namespace: my_namespaced\function("foobar");

@AlmostAlive - The internals team tried :: and implemented it in earlier releases of 5.3. I have a hard time believing if it could have been made to work without tremendous downside and a breaking of backwards compatibility with the existing :: operator they would have gone that road and not reimplemented with a new operator.

 Gavin's avatar
Gavin

Yes namespaces are great but call_exec("my_namespaced\\function") makes me sad.

 Andrew Cassell's avatar
Andrew Cassell

Using a mac & linux I almost never type the "\" key. So pressing that key is a deliberate action to qualify a name space. I can see where Windows users might be a little more annoyed.

 AlmostAlive's avatar
AlmostAlive

"In retrospect the circus of negativity around the new namespaces boiled down to three things"

You missed the only valid argument: PHP already has a namespace operator! It is '::' just as it is in C++. Classes are namespaces and PHP should have worked just like in C++ where they stole the design from in the first place.

Instead, because nobody wanted to fix the bunged up internals to make it work properly, they decided to add this new character and make the whole language that much more complicated. Now we have this new operator that we didn't need and a bunch of different syntax and semantics for accessing static class members and namespaces.

Leave a comment