Problem/Motivation

There's a couple of pieces here. First, we've adopted PSR-0 for *core* classes, which has its own specification for how code is laid out on disk. That fact needs to be added to the coding standards.

Second, we need to document how we reference namespaced classes. There's a number of different ways that it could be done, technically speaking. The following are all PHP-syntax-legal:

use Drupal\Subsystem\Foo;
$f = new Foo();
use \Drupal\Subsystem\Foo;
$f = new Foo();
$f = new Drupal\Subsystem\Foo();
$f = new \Drupal\Subsystem\Foo();
$f = new Drupal\Subsystem\Foo();
$f = new Drupal\Subsystem\Foo();
namespace Drupal\Subsystem;
$d = new \DateTime();
namespace Drupal\Subsystem;
use \DateTime;
$d = new DateTime();

Clearly we want to try and standardize...

Proposed resolution

(description of the proposed solution, the rationale behind it, and workarounds for people who cannot use the patch)

Based on the PSR-0 standard, the conventions that Symfony appears to be using, and a desire to not completely invalidate all existing code, I would propose the following:

A file that declares a namespace:

- Must "use" all classes that it will reference that are in a namespace.
- Must "use" all classes that it will reference that are not in a namespace (including PHP-native classes).
- Must not change the name of a class when importing unless not doing so would cause confusion or name collision.

A file that does not declare a namespace (which right now is everything in core except the Symfony directory):

- Must "use" all classes that it will reference that are in a namespace.
- Must not "use" all classes that it will reference that are not in a namespace (including PHP-native classes).
- Must not change the name of a class when importing unless not doing so would cause confusion or name collision.

All files should:

- Always reference a class literal name by its short name (whether because it's in the same namespace or has been imported with "use").
- Always reference a dynamic class name in a string with a fully qualified name, which does NOT begin with a leading \.
- When importing a class with "use", must include a fully qualified name and do NOT include the leading \.

(The lack of a leading \ is recommended by the PHP documentation.)

That is, all code should look like this:

// Foo.php
namespace Drupal*Subsystem;
use DateTime;
use Drupal\Othersystem\Cat;

// Bar is a class in the Drupal\Subsystem namespace in another file.

class Foo {
  public function __construct(Bar $b, Cat $c) {
    $d = new DateTime();
  }
}
// example.module
use Drupal\Subsystem\Foo;

function do_stuff(Foo $f) {
  $d = new DateTime();
}

Note that this puts all of the \ silliness up at the top of the file, and also creates a nice index of everything a given file depends on.

When importing multiple classes, if they would cause a name collision then they should both be aliased in the use statement for clarity. The alias should be formed by adding the preceeding namespace as a prefix. That is:

use Foo\Bar\Baz as BarBaz;
use Stuff\Thing\Baz as ThingBaz;

function test() {
  $a = new BarBaz(); // This will be Foo\Bar\Baz
  $b = new ThingBaz(); // This will be Stuff\Thing\Baz
}

That helps keep clear which one is which, and where it comes from. Aliasing should only be done to avoid collisions of that sort.

Remaining tasks

Convert the above into proper handbook-ese once we agree on it.

API changes

I don't know that this qualifies as an API change per se.

Comments

webchick’s picture

Every PHP tutorial I've ever read in my life (such as http://www.php.net/manual/en/language.oop5.basic.php) has used the following syntax for instantiating an object:

$c = new ClassName();

So I would reject any of the $f = new Drupal*Subsystem*Foo();-type variants on their face for that reason.

Looking at PHP.net's documentation for namespaces http://ca.php.net/manual/en/language.namespaces.nested.php shows:

namespace MyProject\Sub\Level;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

Nowhere is there reference to a \Foo\bar syntax, so let's reject that as well.

The "use" documentation I couldn't really make heads or tails of http://ca.php.net/manual/en/language.namespaces.importing.php but I think your proposal is inline with the suggestions there.

So in other words, I think the proposed resolution is fine, though I lament the additional complexity this pushes down to module developers. :(

Crell’s picture

Status: Active » Needs review
neclimdul’s picture

I'm against ruling out the $f = new Drupal\Subsystem\Foo(); syntax because its handy for one off references and explicitly specifying the namespace where it might otherwise be confusing. Crell has voiced that this can be handled with aliases which if that's that solution need to be discussed here. I think that sometimes that could be useful but breaks the simplicity of a language construct provided to us.

I'd like to hear why Symfony doesn't use the leading /. That said, I think its probably fine and a good idea we stay consistent with them. I seem to remember it existing as a under-documented feature in C++ too that existed so you could say "using namespace Foo::std" but also reference "::std" so the same logic probably applies to PHP.

I think the more important we should provide guidelines and and leave some interpretation to the developer to leverage the language. Something like:
1) We don't use leading \'s
2) Only use namespace when defining namespace's as it must be the first line of the file(http://www.php.net/manual/en/language.namespaces.definition.php) and expect it has some different semantics.
3) Prefer use over explicit inline resolution except where it makes the code more clear.
4) Notes on aliases which I don't really have any ideas on ATM.

socketwench’s picture

I'm unsure if anyone has noticed, but the day after webchick's comment, the PHP Nested Namespace documentation page was updated. It now reads:

<?php
namespace MyProject*Sub*Level;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

?>

Where the *s are replaced with backslashes.

Crell’s picture

Um, how is that different than what webchick wrote? (Give or take the \ in her post getting eaten by codefilter...)

neclimdul’s picture

@Crell it has more then one namespace and clearly shows not using the leading \. I'm not sure it really affects the discussion in anyway though.

jhodgdon’s picture

Crell: webchick specifically wrote "Nowhere is there reference to a \Foo\bar syntax, so let's reject that as well." , so I am assuming she didn't see the slashes.

socketwench’s picture

@jhodgdon Right. My guess is that the PHP doc page might have been missing the slashes at the time Webchick looked at it. The next day the doc page was updated -- adding the slashes.

webchick’s picture

Sorry. Codefilter did indeed eat my slashes in #1. The page showed the same content as #4 when I read it.

What it did not show though, and still doesn't, is the \MyProject\Sub\Level variant with a leading \. Which is why I'm saying we shouldn't use it.

Crell’s picture

I'm going to make two additional notes here before moving them up into the summary:

1) When in a namespaced file, global functions must be prefixed with \. That is not a Drupal standard; it's a fatal error if you don't. :-) Sucks, but that's PHP for you. (We just ran into this in WSCCI earlier today.)

2) When importing a class, if you DO need to alias it to a new name in order to avoid collision with another imported class, it should always be imported as the preceeding namespace used as a prefix. That is:

use Foo\Bar\Baz as BarBaz;
use Stuff\Thing\Baz as ThingBaz;

That helps keep clear which one is which, and where it comes from. Aliasing should only be done to avoid collisions like that.

3) (Nobody expects the Spanish inquisition!) I grant that some of our epically long files may get a bit clumsy with an imported class all the way at the top of the file (where it has to be) that is then used down around like 3000. I view that as a very good incentive to stop having 3000 line files, which are a terrible idea anyway. It's already impossible to follow those things.

webchick’s picture

Can you provide a code snippet that demonstrates 1) ?

Crell’s picture

Hm. OK, ignore #1. I thought we ran into it, but it was actually something else. My error. (I told you I only had 2 points to make! :-) )

Any objection to moving #2 (aliasing pattern) up into the summary?

neclimdul’s picture

Ran across an example of needing(or at least a logical usage of) the leading \. Documenting it here for discussion: https://github.com/fabpot/Pimple/blob/master/tests/Pimple/Tests/Service.php

Basically, its a class in the Pimple\Test namespace extending a class in the global namespace. It might also be logical(if not necessary) for us to use this in situations like:

namespace Drupal*Foo;
class Bar extends *Symfony*Component*Baz {}

catch’s picture

Priority: Normal » Major

Bumping this to major, would be good to get this resolved before we add any more namespaced code.

Crell’s picture

According to lsmith, the reason Symfony doesn't use a leading \ on use statements is that by the time they decided they should standardize that, they seemed to be not using it more than they did. It was a completely arbitrary decision.

Personally I prefer having the leading \ on use statement myself; the only reason to not use it would be consistency with Symfony, but they have different internal coding standards anyway (4 spaces, non-inline braces on functions, etc.) So that shouldn't be a deciding factor either way.

As long as we're consistent it doesn't make a huge difference.

Since there were no objections I will add the aliasing recommendation to the summary.

pounard’s picture

The leading slash seems good to me, it definitely wipes out potential conflicts. (namespace A\B\A\B for example could create conflicts if you use A\B\Something within \A\B).

neclimdul’s picture

@Pounard same reason I'd prefer the leading \ too.

casey’s picture

I'd like to suggest the following pattern:

namespace {module-name}\{module-name-of-api-being-implemented}\ClassNameSuffixedWithBaseClassName;

For example:
core/modules/entity/entity/Entity.inc

namespace entity\entity;
class Entity {}

core/modules/node/entity/NodeEntity.inc

namespace node\entity;
  use entity\entity;
class NodeEntity extends entity\Entity {}

Or:
core/modules/field/field/FieldWidget.inc

namespace field\field;
class FieldWidget {}

core/modules/text/field/TextareaFieldWidget.inc

namespace text\field;
  use field\field;
class TextareaFieldWidget extends field\FieldWidget {}

And a little bit off topic, I think blocks, pages, forms, input filters, etc, should be controller classes too:
core/drupal/page/Page.inc

namespace drupal\page;
class Page {}

core/modules/node/page/AdminTypesPage.inc

namespace node\page;
  use drupal\page;
class AdminTypesPage extends page\Page {}

Crell’s picture

casey: We're discussing the syntax in this thread, not the organization. The organization is in another thread somewhere. :-) The key there is class loading performance. Let's keep this thread to syntax.

The leading \ or not in a use statement seems to be the only outstanding question. Symfony doesn't use it. PHP core, when it generates a namespace, apparently doesn't either. Should we not use it then, for predictability?

casey’s picture

According to http://php.net/manual/en/language.namespaces.importing.php:

Note that for namespaced names [..], the leading backslash is unnecessary and not recommended, as import names must be fully qualified, and are not processed relative to the current namespace.

So yes, seems obvious to me.

Sorry for my previous post. Could you give me directions to that thread please?

neclimdul’s picture

Dangit, that's pretty clear. I guess no on the leading slash which is against my preference. :(

Crell’s picture

Bah. Yeah, I guess it's no leading \ then. Blargh. I'll update the summary.

Any other comments? I can't RTBC this myself. :-)

Crell’s picture

Project: Drupal core » Documentation
Issue summary: View changes

Add rules for aliasing.

webchick’s picture

Project: Documentation » Drupal core
Status: Needs review » Reviewed & tested by the community

Sure, I'm comfortable with the current proposal. Thanks casey for finding a definitive resource on the leading slash question. Sorry, neclimdul!

catch’s picture

Title: Establish standards for namespace usage » Establish standards for namespace usage [no patch]

Just so I don't open this from the commit queue again ;)

pounard’s picture

Yay, this issue is a quick win!
Let's write OO!

catch’s picture

Project: Drupal core » Documentation
Version: 8.x-dev »
Component: documentation » Other documentation issues

Let's do this actually.

Crell’s picture

Assigned: Unassigned » Crell

Assigning to myself to integrate into the standards handbook. Mostly copy and paste work, methinks.

Crell’s picture

Status: Reviewed & tested by the community » Fixed

Namespaces are now documented here: http://drupal.org/node/1353118

Marking this to fixed. Open new issues for any further tweaks to that page, I guess.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

webchick’s picture

Priority: Major » Normal
Status: Closed (fixed) » Active

Since the bulk of these standards are already established, calling this "normal" now.

But reopening based on discussions in #1321540: Convert DBTNG to namespaces; separate Drupal bits. There's a DX trade-off between the "use" keyword and absolute references to the class.

In Drupal 7, if you want to implement hook_query_alter(), as with every other hook, you go to its api.d.o page, copy the example, paste it into your module, and start hacking.

In Drupal 8, if DBTNG is moved to PSR-0 and we keep the "use" recommendation, this would change to, go to its api.d.o page, copy/paste the example into your module, then figure out where in the bowels of includes/Drupal the AlterableInterface class lies in, then scroll to the top and add a 'use' clause for that, then scroll back down to your pasted code and start hacking.

If we instead used absolute references like Drupal\Database\Query\AlterableInterface in the function signature, we'd retain the same DX as D7.

Additionally, David Rothstein notes (http://drupal.org/node/1321540#comment-5413124):

I really don't understand the benefit of use. I'd prefer the code to be more explicit inline, since it gives me a lot more context. For example, if I'm reading through code and see Drupal\Database\QueryAlterableInterface then I know immediately that it's part of Drupal's database API, whereas if I just saw QueryAlterableInterface I'd have to guess what it's for.

Thoughts?

pounard’s picture

I agree with reopening this discussion. I would tend to think that in pure OOP/PSR-0 code following a strict standard seems good (always use the "use" statement) because files will always be small enough to see the use not far; But in procedural code where some module files can be multiple thousands lines, we could use the fully qualified names in there, and use the "use" statement in those files only when we need to use the same class name more than once.

Crell’s picture

I'd be more inclined to use namespacing as another argument to not have multi-thousand-line files, personally. Those are a DX problem all their own.

At the very least for OO code, we should be picky about using use. For procedural code I would rather be picky there as well for consistency, but I can see the argument to be more forgiving. As catch noted in the DBTNGTNG issue, though, a "sometimes do X, sometimes do Y" standard can be really annoying to self-police.

jbrown’s picture

I think code examples that are designed to be pasted into modules should work without having to modify namespace imports at the top of the page. For this to work all classes / interfaces they refer to must be qualified, e.g. Drupal\Database\QueryAlterableInterface

However, if a file is referring to the same class multiple times, it makes sense to import the class to "optimize" the developer experience of the file. It's really just a shortcut to things that are used frequently.

So I think both should be permitted. It's okay to give developers a bit of flexibility.

On another note, there is a mistake in the standards:

Note that due to PHP's string handling the namespace separator must be escaped: 'Drupal\\Context\\ContextInterface'

This is not true - it is perfectly fine to have unescaped backslashes in single quotes - I do it all the time and it looks much better. The only exception is if the backslash is to be the last character in the string. In this case it must be a double backslash, otherwise it would be a literal single quote. This situation doesn't arise unless you are composing a qualified name of a namespaced resource via concatenation.

webchick’s picture

Yeah, I would be fine amending the coding standards to just say that things like hook implementations and theme functions should use the fully-namespaced name, else fall back to 'use' (particularly when something's used more than once in a file). That would get rid of most of my DX concerns, I think.

David_Rothstein’s picture

If the standard is "only for OO code" or "only for things that aren't hook implementations and theme functions" I think that would be a little confusing. Looking at the patch in #1321540: Convert DBTNG to namespaces; separate Drupal bits, that means places like node.module would not use "use" statements, but various simpletest files would.

How about instead, only use it for code that is already namespaced? In other words, if you have a namespace XYZ; statement at the top of your .php file, you should go ahead and use "use" statements also, since you're already living in a world where different rules apply. Because once you're in a namespace, you already have to put things like use Exception; at the top of your file (unless you want to type "\Exception" rather than "Exception" everywhere else, which is weird).

So in core, that would basically boil down to using this syntax in OO libraries within the includes/ directory, but using the full class names everywhere else.

jbrown’s picture

Works for me!

Crell’s picture

I have to say I'm very much against "not in procedural code" as a standard. That makes it very inconsistent between different files. That forces devs to remember "OK, here, I call this class X, but over here XXY, and over here X, no, wait, what's this class here? I don't know if it's shortened or not, um..." Consistency is important.

Also, when you factor in namespaces class names are going to get *very long*. That's going to make readability much much worse.

The only argument I can see for using a full name (which otherwise completely defeats the purpose of namespaces in the first place) is easy copy/paste of hook implementation signatures. Even there, though, the problems above still apply. It's introducing confusion because you have to remember to sometimes give a full name, sometimes, not, and oh wait what if you do use a class name more than once in a file, now you're typing crazy-long names a lot, which again defeats the whole purpose of namespaces.

-1 from me to not "use" classes anywhere except hook signature type hinting. The easy copy/paste ability there is the only argument I've heard that carries any weight. And even then, we should allow people to be "proper" about it and still put in use if it would make the code shorter/easier to follow.

pounard’s picture

While I agree with Crell, I also have a lot of experience in Java and a bit in C# development: by convention, people almost always uses "import" (for Java) or "using" (for C#) statement (as is "use" for us) but put intentionally the fully qualified names sometime, when they just use the class name once and/or it creates a name conflict (even if in PHP we have the "as" statement for this, sometime just for one usage, what the hell); It's like a commonly agreed convention infringement.

I would keep the "use" as standard, but accept to bypass it in minor cases when it doesn't cause any readability problems.

In the case of the node module query alter hook signature, for instance, I'd definitely let the fully qualified name because it appears only once and we don't really need the use statement whether for readability or DX, standard or not. A rule without exception is not a rule, and I know what I'm talking about I'm french and my native language is all about exceptions ;)

My feeling is that it's OK to break the rules sometime if we feel the readability is better this way: the only pre-condition is we have to agree at review time on a per-case basis.

Crell’s picture

French? Dude, English has you SO beat when it comes to exceptions to the rules. :-)

My concern with an exception for "when that seems more readable" is that is very gray, and we're introducing a great place to stall an issue on bikeshedding. We need to have at least some objective guidelines for when it's OK to break the convention or every issue is going to come down to me saying "no, always" and David Rothstien saying "yes, never", and no way to resolve it. :-)

Since copy/paste is the best use case I've heard so far, what about "if a class name is used in a function or method signature only once in a file, it *may* be given in full form at the developer's discretion."

Remember also that classes may get reorganized. If so, you only want to have to update the use statements, which are easy to grep for. You don't want to have to go hunting for the class name elsewhere.

webchick’s picture

"if a class name is used in a function or method signature only once in a file, it *may* be given in full form at the developer's discretion."

I think I could live with that. I'd like it even better if we appended ", for example if a class is used only once in a file." to it.

Crell’s picture

That would be redundant, since the "once in a file" is already there. I am specifically calling out signatures in particular because that's where copy/paste matters. In fact it may matter only for hooks, now that I think about it, because that's all you'd be copy/pasting. For a class name in the body of a function/method, you should "use" it properly.

If you are implementing hook_node_insert, hook_node_update, hook_node_delete, and hook_node_form, then you really really should go ahead and "use" the class name. (Assuming that the current efforts to classify Entities succeed for Nodes and eventually get namespaced, which I believe are safe assumptions to make.)

webchick’s picture

OMG. READING. I should try it sometime.

pounard’s picture

I mostly agree with the last 4 messages.

catch’s picture

Works for me too.

webchick’s picture

Status: Active » Reviewed & tested by the community

Ship it! :)

Probably append a bullet to the end of the '"use"-ing classes' heading?

Crell’s picture

Bullet added. Please confirm that it is acceptable all around and then mark this back to fixed if so.

(Note that since this is treated as optional, I will probably leave the short-names in place for the DBTNGTNG patch as I already did the work. :-) )

neclimdul’s picture

It probably goes without saying since I voiced this concern earlier but I totally support being more flexible for one off uses of fully qualified namespaces as well. Glad we found a use case and addressed it so quickly before namespaces where heavily adopted!

David_Rothstein’s picture

Status: Reviewed & tested by the community » Needs review

As written, this means that when adding certain new hook implementations to a module, I have to go back and audit some of the other hooks I already have (and possibly change their coding style in response to the mere existence of the new hook). I don't see what benefit that brings in terms of developer experience or code readability, and as coding standards go it doesn't seem like it's either simple or consistent.

I'd like to see more comments on #35.

catch’s picture

From the point of view of a coder rule, I was thinking something like this:

"Fully qualified class names are allowed in function signatures, but not anywhere else."

When we get to the point where entities are all classed, and field API is implementing entity hooks, then it is going to be a lot of entity hook implementations in that file and it seems reasonable to allow a use statement there - even if entity.api.php is using the fully qualified class names, so I'm not sure about making it a strict requirement that you can never put a use statement outside of a namespaced file (although we might possibly want to do that for consistency in core).

Crell’s picture

David: To be honest, I don't even know how to respond to #35. You're essentially proposing that we just use _ everywhere instead of \, and end up with ridiculously long class names that are hard to read. Many projects used to do that, including PEAR and Zend. They all abandoned that in favor of proper namespaces as soon as they possibly could because of how utterly painful it was. There's a reason why most of the OO frameworks were pushing hard for language-level namespaces for classes. They all knew from experience just how much life sucked without them.

To not learn from their experience and have to suffer the pain and agony that they went through doesn't strike me as a wise idea.

catch: One thing I've experienced doing the DBTNGTNG reorganization and the WSCCI-Symfony prototype is that classes may well get moved around from one namespace to another. When that happens, anywhere that a full name is used it has to be changed. If those are scattered throughout the file, it's much harder than if I just have to update a few use statements. Strictly speaking you could even alias the class if it's base name is changing, to avoid changing anything else, but I would discourage that as I can see it getting confusing very fast. The fewer places you use a full name, the easier it is to refactor code. That's true regardless of whether the file in question is namespaced or not.

David_Rothstein’s picture

That doesn't sound like what I proposed in #35... The proposal would require using the shortened class names + "use" in large parts of the codebase (in practice, probably most of the places that actually refer to such classes).

That said, I'm curious how much pain and agony there really could have been. Saving people from typing a few extra characters doesn't seem like a big deal to me when weighed against other considerations, and in general, our coding standards don't prioritize that - if they did we'd name all our variables like $a, $b, $c :) If the only benefit from namespaces were that less typing is required, I don't think it would be worth adopting; but fortunately there are lots of other benefits you described in #1240138: Adopt PSR-0 namespace convention for core framework classes (easy autoloading, compatibility with other libraries, etc), all of which are compelling regardless of how many characters we ask people to type.

pounard’s picture

My guess is we discussing all this as it was a really important detail, but I think it's only a matter of getting the right things close together in one place on the screen (quote from Joel on Software).

While having the strict "use" usage as convention is a good idea, we have, on per-case basis, to cool off about the convention when it makes the code harder to read. When I'm gonna use a class everywhere in the PHP file, I have to do a proper use of the "use" statement because I know that it will allow me more flexibility in term of readability and refactor; Nevertheless if I use my class name only once, I won't disagree breaking the convention if it keeps the right things close together in one place on the screen, because I don't want the next developper to have to scroll the whole file to find out where does it comes from.

Yes, I said it: break the convention, or doing something illegal, we probably should keep those exceptions illegal per the convention but agreed on a review basis and just not writing it into the convention, or just add a small asterisk in the convention saying but it's OK to use a fully qualified name if doesn't make the refactor harder but it clearly keeps the right things close together in one place of the screen.

effulgentsia’s picture

Just to throw another idea into the mix, what do you all think about "using" only up until the subsystem / package name, and having code be explicit in resolving finer resolution than that?

For example, instead of:

use Drupal\Core\Database\Query\Condition;
use Symfony\Component\HttpFoundation\Request;
...
function (Request $request, Condition $condition) {
}

we instead standardize on:

use Drupal\Core\Database;
use Symfony\Component\HttpFoundation;
...
function (HttpFoundation\Request $request, Database\Query\Condition $condition) {
}

Is that the best of both worlds (reduce unnecessary clutter, but keep things clear) or the worst of both worlds (code not blindly copy/pasteable, but still containing ugly slashes)?

Crell’s picture

Symfony does that in some places, I believe. I don't know what its standard is for it off hand. Personally I see that as the worst of both worlds unless you're really comfortable with namespaces, which most Drupal people are not at this point.

pounard’s picture

This seems wrong to use relative class name, it's even more confusing.

andremolnar’s picture

re: #53
What if at some point someone wants to replace Symfony\Component\HttpFoundation\Request with an API compatible Foo\Bar\Baz\Request?

yched’s picture

I guess the standards should mention a special case on *.api.php files:
- classes/interfaces appearing in hook signatures type hinting
- classes/interfaces appearing in the sample functions bodies

Those should probably have their namespaces fully inlined - we can't rely on a bunch of "use" statements at the top of the file ?
(especially since the code in the functions bodies might come from several completely unrelated modules - or completely made up)
Will make copy/paste from existing code less straightforward, though.

pounard’s picture

I agree with yched about .api.php files.

Crell’s picture

The coding standards already agree already, at least implicitly: http://drupal.org/node/1353118

jhodgdon’s picture

So...

I'm looking at http://drupal.org/node/1353118 and there are no examples in there of how to do API docs for these namespaced classes. It's kind of mentioned at the top, but some examples would really help. And we should possibly get some examples onto the Doxygen reference at http://drupal.org/node/1354 ?

Also, I'm very concerned about how the API module should handle them -- how to display these namespaced classes on api.drupal.org, etc. There's an issue for that:
#1507476: Support namespaces in API module
I am really clueless as to what we would want the API module to do, much less how to do it, so if anyone has suggestions on what we want to happen, please clue me in. :)

hansfn’s picture

Just a quick question: When using "instanceof" you have to use the class' full name with leading backslash (when you are inside a namespaced file). Should this be mentioned in the namespace documentation or is it too obvious?

hansfn’s picture

Issue summary: View changes

Clean up comment regarding leading \.

Crell’s picture

hansfn: Not true. instanceof takes a class name directly, in which case it's subject to the same namespacing rules as any other class. In a string, yes, a class name must be fully qualified and include a leading \, which I think is already in the coding standards, no?

hansfn’s picture

Thx for the quick reply, Crell. I'm not knowledgeable on this topic - I'm just posting here based on recent experiments.

instanceof takes a class name directly, in which case it's subject to the same namespacing rules as any other class.

By this you mean that if the class name contains backslashes, it doesn't need a leading backslash? My testing indicates, the opposite. Example:

In core/modules/action/lib/Drupal/action/Plugin/views/field/BulkForm.php (which is a namespaced file), you'll find

$this->view->style_plugin instanceof \Drupal\views\Plugin\views\style\Table

Removing the leading baskslash here breaks the test. However, in other non-namespaced files, the leading backslash doesn't matter.

In a string, yes, a class name must be fully qualified and include a leading \, which I think is already in the coding standards, no?

The docs I pointed to says When specifying a class name in a string, use its full name including namespace, without leading \. (This isn't relevant for my example above, anyway, is it?)

tim.plunkett’s picture

This works:

use Drupal\views\Plugin\views\style\Table;
$this->view->style_plugin instanceof Table;
Crell’s picture

hansfn: What you're running into isn't coding standards, it's just the way the PHP engine handles namespace resolution. #64 is the Drupal-preferred way of handling namespaces.

jhodgdon: Is there a reason this thread is still open nearly a year later? There's only about 14 namespace coding standards issues floating around. Do we still need this one? :-)

jhodgdon’s picture

Crell: I have no idea, and I don't have time today to read through the comments here to see if there is a reason this thread is still open (something still missing from the namespace standards?). Sorry... my schedule should be better next week but I've been really busy all December and into this week.

hansfn’s picture

What you're running into isn't coding standards, it's just the way the PHP engine handles namespace resolution. #64 is the Drupal-preferred way of handling namespaces.

Thx, Crell. So the answer to my question was, yes, it's too obvious and not worth mentioning. Sorry about the noise ;-)

jhodgdon’s picture

OK, I skimmed through this issue. It was closed/fixed sometime before comment #29. Then webchick reopened it in #30, and a proposal was made in #35 for a standards change, which people have not agreed to or completely rejected... As far as I can tell, that is apparently what it is still open for.

David_Rothstein’s picture

I think the reason for this being open can be summarized by looking at the top of node.module right now in Drupal 8:

use Symfony\Component\HttpFoundation\Response;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Database\Query\SelectExtender;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Template\Attribute;
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\file\Plugin\Core\Entity\File;
use Drupal\Core\Entity\EntityInterface;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;

Many of these only have a tangential relationship to what the node module actually is doing; they are referred to once in the entire file in some random part of the module's code thousands of lines down from the top. The concern people have raised about this is that this hurts readability and maintainability of the code in the rest of the file, without any real benefit.

I think the specific proposal in #35 will no longer work since namespaced classes are now being used in many more "higher-level" parts of the codebase than they were at the time I wrote that. Reading other comments above, there seem to be two possible solutions that remain:

  1. Be more lenient about when "use" statements are required, and only use them when there's a real benefit. This would add some inherent ambiguity to the coding standards, but maybe not as much as we think. It could be something like: "If a class is of fundamental importance to the overall purpose of the file, 'use' it at the top." In the case of node.module, I think that means use Drupal\node\Plugin\Core\Entity\Node would remain and the others would go away.
  2. Split up all files in Drupal core so that each file is relatively short and serves one main, focused purpose. (This mostly impacts procedural code, but there are some very long classes too that would need to be broken up.) This would mean extensive use of hook_hook_info() to put hooks inside many separate [module].[hook].inc files. The [module].module file itself would be left for API functions that the module provides (or that could be broken up further if it's still too big, like Field module does). This is likely a good direction overall, but would be a pain to actually implement.

I'm not sure either of these is a great solution on its own, and both have their problems. In an ideal world, we might do both; I think if node.module were a few hundred lines long instead of a few thousand, and had a single use Drupal\node\Plugin\Core\Entity\Node at the top, this would be both usable and sensible.

Crell’s picture

I think if node.module were a few hundred lines long instead of a few thousand, and had a single use Drupal\node\Plugin\Core\Entity\Node at the top, this would be both usable and sensible.

This.

For OO code, I don't think it's an issue. A thousand-line class has a > 50% chance of being a bad design in the first place, regardless of any "use" DX issues, and should be refactored anyway. Eliminating multi-thousand-line procedural files is a noble goal in and of itself. As I'm sure you're tired of hearing from me :-), IMO the preferred way is to convert more of that code to OOP. Not possible for everything yet, of course, but for many things.

Another option is to allow procedural files only to use namespace "use" statements, not class use. Vis, the node.module example above changes to:

use Symfony\Component\HttpFoundation\Response;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Query;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Template\Attribute;
use Drupal\node\Plugin\Core\Entity\Node;
use Drupal\file\Plugin\Core\Entity\File;
use Drupal\Core\Entity\EntityInterface;
use Drupal\entity\Plugin\Core\Entity\EntityDisplay;

// ...

function foo(Query\AlterableInterface $query) {
  $blah = new Query\SelectIextender();
}

That also has the impact of "you have to think harder about such things", but at least reduces the number of "use" statements and inlines some context. I know we previously rejected that when we said the base class name needs to be entirely self-descriptive, and this could result in redundancy, but... Eh. There's no silver bullet here.

(Symfony does that sort of thing all over the place, more than I care for frankly, but at least it's not unprecedented.)

sun’s picture

I can't remember why and when and for what reasons we rejected or objected to it, but importing namespaces instead of individual classes, as @Crell described in #70, has always been the best proposal from my perspective.

I'd even be tempted to potentially allow developers to scale it down even further by encouraging imports of "top-level"/"component" namespaces; i.e., preferring the primary namespace instead of a deeper one in almost all cases:

use Symfony\Component\HttpFoundation;

use Drupal\Core\Cache;
use Drupal\Core\Database;
use Drupal\Core\Datetime;
use Drupal\Core\Entity;
use Drupal\Core\Template;
use Drupal\node;
use Drupal\file;
use Drupal\entity;

function foo(Database\Query\AlterableInterface $query) {
  $blah = new Database\Query\SelectExtender();
}

// Assuming some entity plugin/namespace sanity, as discussed elsewhere:

function mymodule_node_insert(node\Entity\Type\Node $node) {
  foreach ($node->mymodule_files as $file) {
    if ($file instanceof file\Entity\Type\File) {
      $file->delete();
    )
  }
}

Importing individual classes works well in smaller files with a well-defined scope. For larger, de-facto scope-unlimited files, importing entire namespaces might work better (but not necessarily).

In any case, the maximum I'd recommend to do here is to provide a recommendation ("MAY" or possibly "SHOULD" in spec talk), but definitely not a standard (not "MUST"). That is, because I think decision should be based on human, logical sanity - not on pedantic standards. I.e., if it makes more sense to import a namespace, do it. If it's clear that you'll only ever need a single class from another namespace, just import that and be done with it - no reason to only import the namespace.

As a result, I'd recommend the following guideline:

Importing namespaced code

Namespaced code is imported via use statements at the top of a PHP file.

  • use statements MUST be located after the initial @file phpDoc block, separated by a newline.
  • use statements SHOULD be ordered alphabetically, and Drupal core namespaces should be imported before Drupal extension namespaces, e.g.:
    use Drupal\Component\Uuid;
    use Drupal\Core\Cache;
    use Drupal\file;
    use Drupal\node;
    use Symfony\Component\HttpFoundation;
    
  • If it is clear and foreseeable that a particular file will only need a particular class of another namespace, you SHOULD import class directly; e.g.:
    use Drupal\Core\Cache\CacheBackendInterface;
    
  • In case multiple resources are needed from another namespace, or the situation isn't clear yet, you MAY import the primary namespace; e.g.:
    use Drupal\Core\Cache;
    

    Note: For consistency and class name sanity, you MUST NOT import sub-namespaces of another namespace, since those can too easily lead to ambiguous/confusing but also conflicting class name references; e.g.:

    // Don't do this:
    use Symfony\Component\HttpKernel\Exception;
    
    // This would be weird:
    throw new Exception\AccessDeniedHttpException();
    
    // And this would conflict:
    use Drupal\Component\Plugin\Exception;
    
    throw new Exception\PluginException();
    

How's that?

Crell’s picture

The original reason I pushed for never doing partial namespace imports was simplicity, when we had a community of people who I expected to be scared off by \ characters all over the code. That was over a year ago now, though, so I don't know if we're comfortable loosening up yet.

In OOP files, I'd much rather still default to importing individual classes. As above, if that becomes an obscene list in a class file then it probably means your class is wrong anyway and should be refactored.

Re #71, my main concern is the idea of "sub-namespaces", since there's nothing inherent in the language that says that Drupal\Core\Database is the "right" subnamespace to do an import but Drupal\Core\Database\Query is not. We'd have to define an arbitrary number of layers of namespace to import, which would probably start an even bigger bikeshed. :-)

neclimdul’s picture

Best part about the last couple comments? I think we've identified what we're looking for which is in my opinion "Discuss namespace importing in procedural code" which is not the original or summarized version of this issue. Standards have been setup but we can iterate on them in a new issue with the current state of the community.

Crell’s picture

Is this still an active discussion? I think this conversation has meandered through other issues by now...

Crell’s picture

Issue summary: View changes

remove * with \

jhodgdon’s picture

Status: Needs review » Fixed

I do not think this is an active discussion, so marking as "fixed".

If it is an active discussion, it should be moved into the Core queue again.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.