We currently only have the following coding standards for namespaces:

  • If you use a namespace on a class anywhere in documentation, always make sure it is a fully-qualified namespace (beginning with a backslash).
  • Immediately after an @tag (@param, @return, @ver, etc.), class and interface names must always include the fully-qualified namespace.
  • Other namespace-related standards for Drupal are under discussion and have not yet been adopted permanently.

The second item is repeated under Indicating data types in documentation:

Always prefix types with the fully-qualified namespace for classes and interfaces (beginning with a backslash). If the class/interface is in the global namespace, prefix by a backslash.

However, this leaves some situations unclear, and the third item actually appears to be a lie – at least I couldn't find any existing issue discussing this topic further (please correct me if otherwise). I therefore want to start this discussion, with a current example:
In #2334405-1: Clean up documentation on Render Element classes in drupal core, @jhodgdon said that classes always need to be fully qualified in comments. While I believed that to be the case, too (and just wanted to get away with ignoring it because it felt so stupid in this instance), the standards cited above actually don't really say this, as far as I can see. Only if a namespace is used, it needs to be fully qualified. Otherwise, it seems Select::processSelect() would have been OK, too. And maybe even if referencing a different class in the same namespace (according to our current docs).

Note that there is also some discussion of this question on #2937707: Allow to use non fully-qualified name in doc blocks, which was closed as a duplicate of this issue.

Proposed resolution

So, I would like to propose the following new standards, replacing those cited above.

  • All references to classes in comments or the documentation (including as a part of a reference to a method, class constant, or similar), except to classes in the current namespace, MUST use a fully qualified name.
  • References to classes in the current namespace MAY omit the namespace. (E.g., for the constructor of \Drupal\example\Class: "Constructs a Class object.")
  • References to methods, properties, class constants, etc., of the current class MAY omit the class name as well, just starting with the double colon. (E.g.: "Used in ::doSomething() as a helper method.")

The first would eliminate any uncertainty over when it is OK to use an unqualified name, and make this uniform and predictable.
The second one we're already using anyways (at least in most places – some really seem to have the FQN in the constructor description), and I think the third one makes sense, too, especially since we have the same convention for form callbacks already.
I'd be happy without the third one as well, though – I just want to avoid having to use the FQN when referencing the current class, that really seems a lot more confusing than clarifying. An alternative suggestion for this one would be to allow using self in that context, too – e.g.: "Used in self::doSomething() as a helper method."

What are your opinions on this? Can you think of other situations where the current standards (or my proposed new ones) are confusing or too cumbersome?

CommentFileSizeAuthor
#21 Screenshot 2019-11-05 at 10.59.47.png36.32 KBKwadz
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

drunken monkey’s picture

Issue summary: View changes

Amended my reasoning for the first new standard a bit.

amateescu’s picture

Status: Active » Needs review

I think the three proposed paragraphs make sense, although I have to say it would be nice to keep the "ability" of not being mandatory to use the FQCN for classes in the same namespace.. :/

jhodgdon’s picture

I disagree with the third bullet point:

References to methods, class constants, etc., of the current class MAY omit the class name as well, just starting with the double colon. (E.g.: "Used in ::doSomething() as a helper method.")

I am against omitting the class name entirely. The API module does not currently handle this and I'd prefer to see the class name in there. It's not the same as PHP syntax, and ... do IDEs support this type of syntax? It just looks weird to me.

I would be fine with amateescu's idea of omitting the namespace if it's the same as the current file/class namespace. The API module can handle that just fine.

drunken monkey’s picture

Issue summary: View changes

I am against omitting the class name entirely. The API module does not currently handle this and I'd prefer to see the class name in there. It's not the same as PHP syntax, and ... do IDEs support this type of syntax? It just looks weird to me.

It's the syntax we use for callbacks in the Form API, that's why I thought it might be acceptable. And I think it does a good job of conveying that it's a) a method, not just a global function, and b) on the same object, making it (in my opinion) even clearer than repeating the current class's name. But maybe that's just my Java background talking and it would be confusing for most PHP developers – as said, I'd be quite happy without this rule, too.
The API module not supporting it is of course another reason against it, though I suspect this shouldn't be too hard to change if we'd be all for this addition. And, in general, I think we should have standards that make sense for the developers first, and then have the API module work with those.

Using the unqualified name for classes in the same namespace might make sense in most cases, too, you're right. I would personally have found it clearer with only the same class as an exception to the FQN rule, but probably it would be quite clear enough, too, with this change.

So, new proposal:

  • All references to classes in comments or the documentation (including as a part of a reference to a method, class constant, or similar), except to classes in the current namespace, MUST use a fully qualified name.
  • References to classes in the current namespace MAY omit the namespace. (E.g., for the constructor of \Drupal\example\Class: "Constructs a Class object.")
  • References to methods, class constants, etc., of the current class MAY omit the class name as well, just starting with the double colon. (E.g.: "Used in ::doSomething() as a helper method.")

With the inclusion of the third being the most up for discussion, but comments on others of course also still welcome.

(For the phrasing of the second: is "omit the namespace" or "use the unqualified name" clearer?)

And, as in #2027221-18: [policy] Revisit class naming standards: what is now needed to decide on this change?

drunken monkey’s picture

Issue summary: View changes

I marked #2536670: Relax class/interface reference documentation standards as a duplicate, which makes the interesting suggestion of just using self or static for referencing to the current class in this cases, too. So that could maybe be used instead of the third item in my above proposal.

tizzo’s picture

Moving this issue to the Coding Standards queue per the new workflow defined in #2428153: Create and document a process for updating coding standards.

jhodgdon’s picture

@tizzo - it didn't actually get moved. ;)

tizzo’s picture

Project: Drupal Technical Working Group » Coding Standards

Oops! Good catch, thanks @jodgdon!

slootjes’s picture

+1 to stop using the FQCN in doc blocks, comments, references. It only makes code less readable and any modern IDE should be able to handle this anyway.

jhodgdon’s picture

Adding link to a related issue where this was discussed before. That was closed as a duplicate but I have no idea what it was a duplicate of. Someone could search the Core and Coding Standards issue queues and try to find other issues...

Kwadz’s picture

Agree with @amateescu and @slootjes, FQCN are not relevant anymore nowadays, that shouldn't be mandatory.
See #2937707: Allow to use non fully-qualified name in doc blocks.

jhodgdon’s picture

Issue summary: View changes

I just closed the issue #2937707: Allow to use non fully-qualified name in doc blocks as a duplicate of this one. There was some discussion there...

slootjes’s picture

Maybe Drupal 9 can be a good fresh start when it comes to changing this requirement? Please read the linked issue for arguments.

cleverhoods’s picture

+1 to stop using the FQCN in doc blocks, comments, references. There is no real value behind using it anymore as you can get the necessary information from the "use". Doing this would greatly reduce unnecessary documentation needs.

Chi’s picture

+1 to stop using the FQCN in doc blocks, comments, references. It only makes code less readable and any modern IDE should be able to handle this anyway.

It will not be able to handle if multiple implementation exist. Using import statements just for doc comments seems wrong to me as it'll cause PHP interpreter parse instructions that are not really used. And besides, I think code sniffers will complain on unused imports.

Chi’s picture

As of referencing methods and properties in the same class. It has been discovered in #3092199: [META] Fix broken code references in phpdoc tags that we are currently. using 6(!) different ways for this.

  1. \Drupal\example\Example::foo()
  2. Example::foo()
  3. self::foo()
  4. static::foo()
  5. ::foo()
  6. foo()

I've found that PhpStorm only supports 1, 2 and 6. However, I think code navigation within the same class is not a critical feature. So maybe in addition to FQN we can also allow self::foo() or static::foo() notations.

Chi’s picture

One thing that is not covered yet in this standard is whether or not a code reference must end with a full stop.

slootjes’s picture

It will not be able to handle if multiple implementation exist. Using import statements just for doc comments seems wrong to me as it'll cause PHP interpreter parse instructions that are not really used.

There should be zero performance impact on this as the unused (in code at least) use statements are stripped during compilation.

And besides, I think code sniffers will complain on unused imports.

Code sniffer can be configured to handle this; that should also not be an issue.

eelkeblok’s picture

I am all in favour of leaving out the namespace when it is the same as that of the current class (and actually in favour of the proposal as it stands now), but for other cases, I'm not so sure. For me, it helps putting things into context. Sure, it might be a little bit redundant for the umpteenth time you add EntityTypeManager or ContainerInjectionInterface, but for most other cases, I actually like seeing the entire namespace. Also, I've seen the argument "the IDE can figure it out". That also applies to adding those FQNs. I can't remember the last time I've actually typed an entire FQN, or more than a dozen characters or so to add one; the IDE "figures it out" (i.e.: gives me an autocomplete). Lastly, don't forget your IDE is not the only place you read code. Consider things like Bitbucket, Gitlab, api.drupal.org etc. too.

Chi’s picture

Code sniffer can be configured to handle this; that should also not be an issue.

You mean completely remove that rule? I think it would be step back. At least I don't know how to tell PHP_CodeSniffer not to complain about unused imports if they are referenced in comments.

Kwadz’s picture

FQN in docblocks is a mess, like it is in method signatures. It just adds more noise. That's why PHPStorm offers the possibility to remove unnecessary qualifiers:

Screenshot

I think class names in comments should be named the same way as in code.

Using import statements just for doc comments seems wrong to me as it'll cause PHP interpreter parse instructions that are not really used

A use statement doesn't actually result in any extra code being imported, it's purely an alias for other code contained in the same file. So, having unused use statements in PHP doesn't impact performance. At least not in any noticeable measure.

I don't know how to tell PHP_CodeSniffer not to complain about unused imports if they are referenced in comments

If PHP_CodeSniffer is not able to handle that case, we should add the feature.
That being said, this problem won't exist using type declaration and, since PHP 7.4, typed class properties.

slootjes’s picture

You mean completely remove that rule? I think it would be step back. At least I don't know how to tell PHP_CodeSniffer not to complain about unused imports if they are referenced in comments.

There is not an out of the box rule for it now but the current one can be adjusted to detect these namespaces in comments and other references as described here: https://github.com/squizlabs/PHP_CodeSniffer/pull/1106

Chi’s picture

FQN in docblocks is a mess, like it is in method signatures. It just adds more noise.

Without FQN we will have this noise in the use sections.

Also agree with #19. Without FQN it would be harder to read the code without IDE, i.e. in web based git interfaces like GitHub, GitLab, BitBucket.

Kwadz’s picture

Without FQN we will have this noise in the use sections.

We only need a use statement one time while we need a FQN each time in the code. So it's like a code factorisation which is a best practice. In addition modern IDEs are able to hide this section. We're not supposed to read it most of the time.

Without FQN it would be harder to read the code without IDE, i.e. in web based git interfaces like GitHub, GitLab, BitBucket.

I think we can use a web based interface just to read quickly few files. Otherwise, to read seriously and easily navigate between files, it's better to clone the project and use a proper tool to read it.

Chi’s picture

In addition modern IDEs are able to hide this section.

Let's put it clear. There is only one "modern IDE" for PHP, and that is PhpStorm which is ubiquitous nowadays. All other IDEs a way behind it.
However, PhpStorm is still a paid proprietary software which does not work on computers with relatively low performance. Many developers especially in front-end prefer other IDEs/editors when working with Drupal.

Kwadz’s picture

Agree about PhpStorm. Yet, in any case we'll still have less noise using use statements (code factorisation).

slootjes’s picture

I think we can use a web based interface just to read quickly few files. Otherwise, to read seriously and easily navigate between files, it's better to clone the project and use a proper tool to read it.

Agree! These web interfaces also would not highlight potential issues when the docs are out of sync with their actual use statements as an IDE would.

eelkeblok’s picture

Especially when "quickly reading a file" it is important that code is readable. The point was that an IDE (or PHPStorm) is not the only place code is read. Obviously, the IDE is the most important one. I'm not saying this is the most important argument, but is an argument that should not be completely disregarded.

I'm not sure how obvious PHPStorm makes the FQN for a reference that does not include the entire namespace. That would be an important consideration. I've done a quick experiment and it may be down to configuration; PHPStorm does take me to the right PHP file, but there is nothing like a mouseover or something telling me where this class is. If that were there, it would actually be more helpful to have the FQN be resolved based on the use statements, because that could even surface bugs (such as completely forgetting the use statement, claiming a variable is one type, but PHP will actually be looking in the current namespace, for example).

Chi’s picture

It is worth noting that referencing namespaces is not mandatory. At least Drupal code sniffer does not complain on it. In PHP 7 support of type hints has improved notably which makes having PHPDoc notation less essential.
There are RFCs for mixed and union types. I hope some day will stop using PHPDoc notation for documenting types.

slootjes’s picture

I'm not sure how obvious PHPStorm makes the FQN for a reference that does not include the entire namespace. That would be an important consideration. I've done a quick experiment and it may be down to configuration; PHPStorm does take me to the right PHP file, but there is nothing like a mouseover or something telling me where this class is.

Not sure what you mean with this. If you ctrl-click the class it takes you to the right class right away (and you know it's location). If the class does not exist because of a typo or wrong use statement it will tell you right away that the class does not exist.

If that were there, it would actually be more helpful to have the FQN be resolved based on the use statements, because that could even surface bugs (such as completely forgetting the use statement, claiming a variable is one type, but PHP will actually be looking in the current namespace, for example).

Exactly, letting the IDE resolve namespaces makes it less error prone, especially when refactoring where there is a risk the namespace in the doc block go out of sync with the actual namespace in code.

eelkeblok’s picture

The ctrl-click is what I was describing. It is a lot more "work" than seeing the FQN right there in your code. So, if PHPStorm can fill in that gap, i.e. making the FQN obvious without having to leave your code, that would remove that particular (maybe only) advantage of having inline FQNs. A question might be is how often having the FQN actually prevents confusion, as opposed to how much damage it does to the readability. I guess that is down to personal preference (and probably also in actually experiencing it).

slootjes’s picture

Ok, I understand and good point. Personally I don't think I've ever made mistakes due to a wrong import however that might be different for others. In the end the entire discussion comes down to personal preference anyway of course :-)

Kwadz’s picture

A question we should ask ourselves:

If FQN is better, why don't we use it everywhere in the code?
Same answers should apply for comment blocks.

Kwadz’s picture

Sorry to come again with that, but I think it's not about a matter of taste or personal preference.

Does someone disagree with the following statement?

If FQN is better, why don't we use it everywhere in the code?
Same answers should apply for comment blocks.

If nobody disagrees with valid reasons, I suggest allowing the use of non fully-qualified name in doc blocks.
What do you think?

slootjes’s picture

Sorry to come again with that, but I think it's not about a matter of taste or personal preference.

If you read above comments, apparently it is. As you could also read I am 100% advocating to drop the full class names in doc blocks as in my eyes it's just a waste of screen space in a world where nearly every developer can have access to a proper IDE resolving everything correctly.

If FQN is better, why don't we use it everywhere in the code?
Same answers should apply for comment blocks.

Couldn't agree more.

eelkeblok’s picture

I think the valid reasons have already been given. I really can't wrap my head around that argument, "just use FQNs everywhere if they are so good". Nobody said "FQNs are better", full stop. The argument is much more nuanced than that, and taking the argument to this extreme seems to just be detrimental to the discussion. What has been said is that FQNs in the places where they are currently mandatory, in most cases removes ambiguity. The "most cases" part is actually mostly the subject of this proposal.

I just tested, and PHPStorm will not tell me the FQN for a class I removed it from in a docblock without actually clicking through to that class. Even then, IDEs are not the complete picture; code is read in many more places than just IDEs. Places where there is not a fancy parsing engine that understands PHP code and can resolve un-namespaced classes.

I think the current status quo is mostly a good compromise between removing that ambiguity (argument and return types, are documented as FQNs) and not littering code with FQNs. The actual suggestion of this issue I can get behind, because in those situations, the guideline seems to miss its target. That is:

  • All references to classes in comments or the documentation (including as a part of a reference to a method, class constant, or similar), except to classes in the current namespace, MUST use a fully qualified name.
  • References to classes in the current namespace MAY omit the namespace. (E.g., for the constructor of \Drupal\example\Class: "Constructs a Class object.")
  • References to methods, properties, class constants, etc., of the current class MAY omit the class name as well, just starting with the double colon. (E.g.: "Used in ::doSomething() as a helper method.")

The first bullet point could use some more tweaking, for my POV, but that does not seem where this discussion is at at all, so I'll leave that for now. I think this has been discussed at quite some length and I think trying to get the proposal changed to "don't use FQNs anywhere" has proved quite futile.

dww’s picture

Not having found this issue when searching for '@see', I opened a closely related (possibly duplicate) issue: #3112830: [policy, no patch] Allow static::methodName() and/or self::methodName() in @see comments when referring to the same class, which @drunken monkey was kind enough to comment on, pointing me here.

Turns out that the api.module (which powers api.drupal.org) already handles @see static::fooBar() and @see self::fooBar() just fine, but I don't believe it knows what to do with @see ::foBar() (yet).

I don't use or have access to any IDEs, so I don't know about their support, but I'm a bit surprised by #16 that PHPStorm can't handle self::fooBar(). /shrug

How existing tools support all these options should factor into the decision, although it's not the only factor. If we need to patch api.module to handle ::fooBar(), so be it. If we need to open bug reports for PHPStorm for them to support an obvious thing, we could...

Not sure how the #OutOfScope police function in this issue queue. If it's better for everyone to merge these two issues, we can. If it's easier to deal with the small piece about @see comments pointing to methods in the same class as a separate issue, please join the discussion over there.

Thanks,
-Derek

jhodgdon’s picture

You are correct about the API module. It works fine with static/self as the class name, but doesn't handle a missing class name. It would not be all that hard to make it do that, but currently it doesn't.

Personally I'm not excited about the ::methodName() syntax, and would prefer self:: or static::.