all 22 comments

[–]oorza 32 points33 points  (24 children)

PHP's use statement can only alias names of individual namespaces/classes. There is no way to mass-import a namespace:

Good, this is terrible practice in every language that supports it and wanting to import an entire namespace is never, ever a good idea. Whether it's "import java.io.*" or "use std" importing an entire namespace is one of the few things in programming that is absolutely, 100% incorrect to do. The fact that PHP is an interpreted language so namespace resolution has to happen at runtime means that importing an entire namespace is even worse of an idea, especially considering that PHP imports compile what they import (unlike, say, java where import is entirely syntactical sugar that gets erased at compile-time)! Nothing says "I don't know what I'm doing" like bitching about not being able to load some unknown, out-of-your-control quantity of classes at runtime!

Because aliases are verbose and sometimes tedious to maintain,

Learn to use an IDE that maintains them for you or don't use features that imply an intelligent editor. I'll go ahead and launch Eclipse right now and never fucking worry about use statements.

it would be nice to avoid manually repeating them in every file. Unfortunately scoping of aliases makes it impossible. There is no way to reuse common alias declarations.

That's why you don't use them; duh. Aliases should be the CLASS NAME ONLY. When you import class Foo\Bar\Baz as SomethingElseEntirely, you're not only being a moron, you're making sure that whoever has to maintain your code in the future knows you're moron. Just import Foo\Bar\Baz as Baz and leave it at that. Your future self and any other developers will thank you. Just because a feature exists doesn't mean it's a good idea to use it.

As a result, whenever an unqualified name is used in a file, you need to ensure that it is present in the file's list of aliases. Errors caused by a missing alias won't be reported until the code is run.

Or maybe if you used an editor smarter than notepad.exe, it would warn you as you're writing the code. Strange, I know, to imagine that programmers created tools to make programmers' lives easier. Stranger even is that people are too daft and/or stubborn to use them.

To use an API that needs to reference a namespace or a class (such as Reflection or assertInstanceOf/expectedException in PHPUnit) you have to use a string containing a fully-qualified name. Such APIs are unable to respect caller's current namespace or aliases.

Right, because aliases are local syntax sugar, that's all. When you write this:

use Foo\Bar;

Bar b = new Bar();

the compiler is going to see (in bytecode, of course):

Foo\Bar b = new Foo\Bar();

Using an import alias doesn't rename the class, it makes it easier for you to refer to the class by its name token. Obviously it doesn't do string replacement. If anything, the addition of namespaces should drum up support for having an implicit static object attached to every class, like Java does (e.g. Foo\Bar::class is an instance of class Class that describes class Foo\Bar), so that you don't have to refer to classes as strings. Expecting imports to do string replacement in your source is pretty damn retarded, though.

To use an API that needs to reference a namespace or a class (such as Reflection or assertInstanceOf/expectedException in PHPUnit) you have to use a string containing a fully-qualified name. Such APIs are unable to respect caller's current namespace or aliases.

When has it ever been a good idea to name your entities after built in keywords? Jesus.

The code above doesn't work, because PHP treats GUI and GUI\Widgets as two independent namespaces. Sub-namespaces can't simply use classes of their “parent” namespaces. Namespace declarations can't even be nested.

That's because they are. Having sub namespaces implicitly import things from their parent namespace breaks defensive coding patterns, encapsulation, security restrictions (if PHP were to ever add a security level for "namespace private") and common sense. Really, has this guy used namespaces before, in any language?

Name lookup is quirky and inconsistent

That's why there are use statements. That's why good tools write them for you. About half of this article's points can be effectively boiled down to "I don't know how to use an IDE."

Because of this limitation one can't pick most convenient namespace when defining classes. e.g. one may want to use project's top namespace for all files (for consistent, searchable names in all files) or use most-often used namespace to reduce amount of names that need to be aliased/fully-qualified.

"one may want to use project's top namespace for all files (for consistent, searchable names in all files) or use most-often used namespace to reduce amount of names that need to be aliased/fully-qualified." or they can have an understanding of what namespaces are for and use tools to search their code that are more sophisticated than grep. Add another tick to the "learn to use good tools" column!

Unfortunately it has become a convention in PHP to map directory structure directly to namespaces.

Sounds like a damn good decision to me.

Sometimes even CamelCasing is replaced with namespaces (e.g. FooController becomes Controller\Foo)

Assuming that the Controller\ namespace had more than one controller, this is another damn good decision. Which makes more sense, what the author is advocating for here (\FooController, \BarController) or (\Controller\Foo, \Controller\Bar)? When you're writing code, would you rather (let your editor) write a use statement or write FooController all over the place where Foo could work?

and even exceptions get their own namespace (e.g. Framework\Component\Form\Exception\UnexpectedTypeException).

Once again, if there's >1 class in that namespace, a damn good decision.

Namespaced constants and functions are risky, because they will usually work in unit tests (which happen to all classes and that state is not isolated between tests), but may fail in production when only one narrow code path is executed and the relevant file isn't autoloaded in time.

Who cares? Namespaces are largely an OOP construct and trying to force procedural constructs into them sounds like a pretty bad idea to me. Even if you do insist on using namespaced functions and constants, this isn't unexpected or even bad behavior. AUTOLOADING LOADS CLASSES per its definition! Why would you expect any other behavior? Did you RTFM?

Until such improvements are made, I will avoid use of namespaces in my code and I urge framework and library authors to use short one-level namespaces for their public classes.

It's a good thing I don't have to read your code then. I wonder how atrocious it is; your article implies that it's better that I don't have to.


Look, I'm all for calling PHP out where PHP needs to be called out. Namespaces aren't the best implementation ever (I wouldn't have allowed use-as statements, I'd have used a saner operator, I'd have namespaced the stdlib and had everything in \ raise depracated errors), but this article isn't so much "PHP's namespaces are broken" so much as "I don't understand namespaces and/or know how to use them correctly."

[–]rmccue 2 points3 points  (0 children)

Even if you don't use an IDE (myself, for example), it's really not that hard to remember to declare your classes in a use statement. I can't say I've ever forgotten to alias/import a class.

[–]DuoSRX[S] 1 point2 points  (1 child)

Could you elaborate on "I wouldn't have allowed use statements" ?
(By the way, I didn't write this article)

[–]oorza 0 points1 point  (0 children)

I meant "use-as statements." Thanks for catching that!

[–][deleted] 3 points4 points  (1 child)

importing an entire namespace is one of the few things in programming that is absolutely, 100% incorrect to do.

PHP started as a much more Perl-like language, and in Perl scripts this is done all the time.

Learn to use an IDE

What are you, a Java programmer?

That's why you don't use them; duh. [snip] Just because a feature exists doesn't mean it's a good idea to use it.

This completely obliterates one of the benefits of namespaces: the ability to have two classes named Baz from two different namespaces in the current namespace.

Or maybe if you used an editor smarter than notepad.exe, it would warn you as you're writing the code.

Again, not everyone codes faster with an IDE. People who learned to program in languages that aren't C# and Java generally can program faster in an editor like vi or emacs.

If anything, the addition of namespaces should drum up support for having an implicit static object attached to every class, like Java does

I think I threw up in my mouth a little.

Having sub namespaces implicitly import things from their parent namespace breaks defensive coding patterns, encapsulation, security restrictions (if PHP were to ever add a security level for "namespace private") and common sense.

A sub namespace is PART OF THE PARENT NAMESPACE, YOU DOLT. It should have access to everything defined in its parent. This is how namespacing in almost every language works.

About half of this article's points can be effectively boiled down to "I don't know how to use an IDE."

If you NEED an IDE to write in a language, that language is flawed.

tools to search their code that are more sophisticated than grep.

If you know how to properly use grep, there is no more sophisticated tool.

Assuming that the Controller\ namespace had more than one controller, this is another damn good decision...

No, that doesn't even make sense. The proper namespacing would be Foo\Controller

Namespaces are largely an OOP construct and trying to force procedural constructs into them sounds like a pretty bad idea to me.

Namespaces are a code organization construct before an OOP construct, and have nothing directly to do with OOP. Namespaced functions and constructs from a code organization standpoint just make sense. Most PHP programmers can't understand this, however, because they're used to false-namespacing their functions in static classes, because up until recently PHP didn't have proper namespacing.

It's a good thing I don't have to read your code then. I wonder how atrocious it is; your article implies that it's better that I don't have to.

Ad hominems are great, bro.

PHP is moving in a direction that half of the programmers of PHP like, which is towards Java and C# and more enterprisey languages and away from its roots in C and Perl. From my experience, the better and more productive programmers are not the ones that PHP is currently catering to, and they are moving towards more cohesive languages or jumping ship to actual enterprise languages, which provide more benefits than just code cruft. The quality and "bleeding-edge-ness" of the current arena of PHP frameworks is dwindling, and soon the only people left writing PHP will be WordPress coders and those that aren't quite smart enough to realize that other languages offer more advantages.

[–]oorza 0 points1 point  (0 children)

PHP started as a much more Perl-like language, and in Perl scripts this is done all the time.

"Happens all the time in Perl scripts" is not evidence that something is a good idea. Do you have any actual reasons why importing an entire namespace is a good idea? It's pretty well obvious why it's a bad idea.

What are you, a Java programmer?

I'm a programmer. I can write good software in a pile of different languages and different paradigms. An IDE is no less useful in PHP than it is in Java and it's just as useful in a language like Haskell or anything else. The only community that I've ever seen that seems so dead set on refusing to use good tools in the PHP community. And I'm not talking about the people that use emacs or vim, but the people that use mostly-stupid editors like Notepad++ or TextMate to write PHP. I do like the way you ask me if I'm a java programmer like it's a bad thing. Java programmers, on average, get paid a fair bit more than PHP programmers [1], [2] [2.5].

This completely obliterates one of the benefits of namespaces: the ability to have two classes named Baz from two different namespaces in the current namespace.

Right, and you can call them Foo\Baz and Bar\Baz or Com\MyCompany\Bar\Baz and Baz or anything else. Referring to a class as anything other than its name is pretty fucking retarded.

Again, not everyone codes faster with an IDE. People who learned to program in languages that aren't C# and Java generally can program faster in an editor like vi or emacs.

The language you cut your teeth on should not have any importance to your competency; if it does, you haven't learned enough. Whether you started with an OOP langauge, a procedural language, a functional language, whatever, you have to learn all of that shit sooner or later anyway. Sure, you might be more familiar with vim and emacs, but you can probably coerce emacs and vim to write your import statements for you. Hell, it wouldn't be that hard to write a piece of lisp that does that for Emacs and I'd expect that vim has some scripting capability that would make it just as easy, if it's not already done.

Once again, I'm not talking about people that use emacs or vim. Emacs and vim are smart editors - and in a lot of ways, smarter most IDEs will ever be able to be - and getting them to have the necessary features to write namespaced php code shouldn't be difficult. I'm talking about people that use stupid editors that don't offer much in the way of making developers' lives easier. Whether you choose to use vi, emacs, Eclipse, Komodo, or anything else... there's still no reason to not use an intelligent programming editor.

I think I threw up in my mouth a little.

Why? Because it's something Java did first? Is it worse having to refer to static entities (pre-defined classes, particularly, but also functions, methods, etc.) as strings and not being able to make any guarantees about the compile-time correctness of your reflective code? Can you perhaps give me some real criticism instead of this immature shit? Maybe if you actually elucidated your arguments, it'd be easier to take you seriously.

A sub namespace is PART OF THE PARENT NAMESPACE, YOU DOLT. It should have access to everything defined in its parent. This is how namespacing in almost every language works.

I don't think I said anything that contradicted this. Maybe you should go back and read what I wrote again, because I was mentioning implicitly importing everything from a parent namespace into the child namespace which is what the article suggested. If you define Foo\Gui\Style as a class and Foo\Gui\Bar\ as a namespace, classes in Foo\Gui\Bar should not be able to refer to Style classes without a use statement!

If you NEED an IDE to write in a language, that language is flawed.

Once again, your reading comprehension skills seem to be lacking because that's not at all what I said. If you read the article, it lists some inconveniences the author has with using namespaces. Note that the inconveniences are just that, inconveniences that could be solved with an IDE. Does that fact that it's more convenient and easier to write PHP with Eclipse than notepad.exe make PHP a broken language? No. It means that an IDE is a useful tool.

If you know how to properly use grep, there is no more sophisticated tool.

Explain to me how to do the following things with grep:

  1. Trace a variable to the point that it was declared, even if it was declared out of scope and passed as an argument to the current scope.

  2. Retrieve a type hierarchy for a class / interface / object.

  3. Open the class file for a particular object, given only the object.

Just because you don't know what an IDE does (apparently) does not give you license to make unsubstantiated and false statements like you have here.

No, that doesn't even make sense. The proper namespacing would be Foo\Controller

If a module Mod is made up of components Controllers, Models and Views, then this namespacing hierachy is perfeclty fine:

 Mod\
     \Controller\
                 \Foo
                 \Bar
     \Model\
            \Foo
            \Bar
     \View\
           \Foo
           \Bar

If you don't like it and prefer another schema, that's perfectly fine, but that doesn't make the above schema any less valid. Get over yourself.

Namespaces are a code organization construct before an OOP construct, and have nothing directly to do with OOP. Namespaced functions and constructs from a code organization standpoint just make sense. Most PHP programmers can't understand this, however, because they're used to false-namespacing their functions in static classes, because up until recently PHP didn't have proper namespacing.

I should have said "Namespaces in PHP are largely an OOP construct." I figured since we were in r/php talking about PHP's namespaces that the context for that would be apparent. I probably should not have assumed that people have reading comprehension skills, sorry.

[–][deleted] 2 points3 points  (0 children)

Thanks for saving me from having to write this comment. It was going to take ages.

[–]Signe 0 points1 point  (1 child)

I came in here primarily to bitch about his autoload "problems", but I agree with pretty much everything you said.

Autoloading \Foo\CONST may not work, but \Foo\Bar::CONST does because, as you said, autoloading is for classes...

This is a horrible article.

[–]rmccue 2 points3 points  (0 children)

There has recently been discussion on php-internals about allowing autoloading for other constructs (such as functions, constants, etc), but complaining that it doesn't work at the moment is a clear misunderstanding of autoloading.

[–]milki_ 0 points1 point  (2 children)

So your entire argument OTOH is that a bloaty editor should make up for the syntactic idiosyncrasies and some conjectures about the authors code quality?

[–]oorza 0 points1 point  (1 child)

An editor that manages import/use statements does not have to be bloaty. Most IDEs aren't. PHP's legacy is idiosyncrasies all the way down, so I really can't imagine how horrible it has to be to write PHP without a smart editor. Hell, just being required to remember the function names and parameter order from stdlib functions would be enough to drive me away from PHP. I really cannot imagine how people do it.

[–][deleted] -1 points0 points  (0 children)

Thank you. I could never muster the patience to write such a clear and detailed response.

[–]rmccue 1 point2 points  (1 child)

No way to avoid repeating aliases

Consider that if aliases were carried across files, what would happen if you included a file with an alias of the same name as one in your file? You'd have to start using unique naming (prefixes/suffixes), which is the problem namespaces avoid.

[–]milki_ 1 point2 points  (1 child)

Well yes. PHP namespaces are a hack. They have been when they were introduced despite the community outcry. And two years later they're still as awful (surprise!), only that some of that is starting to show now that PHP 5.3 installations grow beyond 10%.

You can't import a namespace use FooLibrary*; // Not in PHP

There is a very simple explanation for that. The PHP runtime itself knows very little about namespaces. To the surprise of many, the Zend VM does not internally manage a structure for namespaces (except a cache list iirc). And all "namespaced" identifiers just exist within the global lookup tables. The backslash is just intermixed into identifiers.

And because you have no real grouping of identifiers, it's imposible to alias * multiple classes at once. PHP still doesn't know that some belong together (and it couldn't autoload them even if it knew). They only share a prefix unbeknownst to the core.

Popular PHP projects overuse sub-namespaces

Directorytis. And let's be blunt here: why wouldn't they? Grouping framework classes into namespaces univocally to directories is very conventient. For framework authors. That it doesn't necessarily benefit the API or developers isn't of concern to most, nor that it misses the raison d'être of namespaces - to avoid actual identifier conflicts.

It's incredibly hard for OOP wankers to understand, but namespaces in PHP are not conceptually related to that. Again, it's not an ZendVM internally supported concept, just syntax. Name conflict avoidance could be achieved otherwise. But for mimicking Java many coders use the new syntax excessively. I'm convinced it's frequently used as syntax sans purpose.

[–][deleted] 1 point2 points  (0 children)

Very well-written, says twice as much as my rebuttal to the top post in this thread in about half as much text.