Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
other
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
4 Jun 2010 at 13:33 UTC
Updated:
3 Jan 2014 at 01:42 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
dawehnerI would vote for the first suggestion because
Comment #2
jbrown commentedI like the first one because it's consistent with when a constructor is getting arguments.
Comment #3
jhodgdonBoth of those sound like reasonable arguments to me. +1 for suggestion #1.
Comment #4
Crell commentedI am going to "me too" dereine's points in #1. A function if called with no parameters requires (), a method if called with no params still requires (), I don't see why calling the constructor of a new object (which is what happens when you create an object) shouldn't require one.
Comment #5
berdirAgree with #1 and #4. A quick grep gave me 17 instances (vs 63 with ()) without ():
I guess it would be easier if we wait for #780154: There is no listing API for field API to get commited before we work on a patch for this as it started this issue and misses some () too.
Comment #6
jhodgdonLet's also give it 24 hours to see if anyone objects, before adding it as a standard to the coding standards page. And I guess then someone should alert Coder module?
Comment #7
jhodgdonAnd who are the current coding standards gurus?
Comment #8
stella commented+1 for using the () Though I'm pretty sure the coding standards used to say to do "new stdClass;" without the (), but can't find it there now.
Comment #9
morbus iffI vote for ().
Comment #10
morbus iffFor two reasons:
Comment #11
chx commentedI vote very very strongly against () because
new $foo()is one of the biggest undocumented WTFs in PHP, observeit's bad enough to figure out what's going in if the constructor gets arguments, let's not throw that WTF around for every variable-class new.
Comment #12
chx commentedAlso it's not a function, why would it get parentheses which means call-a-function? Just
new classis fine.Comment #13
morbus iff$request = new HTTP_Request2($url, HTTP_Request2::METHOD_GET);i argue that"new HTTP_Request2" is more confusing than a paramless construction: "new HTTP_Request2()"
Comment #14
morbus iffchx's code isn't confusing to me at all, really. $foo is a placeholder for "a". if you use "a" in different ways - by throwing 'new' in front of it - then, yeah, it'll do different things. the inclusion, or exclusion, of "new" "casts" the result to an expectation. chx's argument is not too different from:
Comment #15
chx commentedBut the problem is not with
$foostandalone bu that$foo()behaves totally differently in two contexts. Asnew $fooandnew $foo()are the same and sonew $foois way clearer in what it does because you do not need to guess whether the relevant information$foo()or just$foo. That's widely different from an explicit cast.The confusion arises from the fact that
()itself changes meaning betweenprint $foo();andnew $foo();because in the first it is a function-call-operator the second is nothing. Don't tell me that's not confusing.Comment #16
Crell commentedchx: Valid point, but that remains an issue regardless of whether it's an empty constructor or not. To wit:
And we certainly can't omit the () on the second one, naturally. It's only a serious WTF if we have a function and class with the same name, which should never happen anyway and if it does then someone needs to change their code because that's its own wtf. :-) If you don't share names, you'll get a fatal error if you get it wrong which is quite easy to spot and fix.
That said, if we wanted to go with something like "always include the () unless it's a variable-named class", I'd be OK with that.
Comment #17
chx commentedThat said, if we wanted to go with something like "always include the () unless it's a variable-named class", I'd be OK with that.
Me too.
Comment #18
dave reidSo we'd have a different standard for variable functions with empty parameters as variable classes with empty constructor. I'd much rather prefer the same thing.
Comment #19
jhodgdonOK.
I finally get it.
If you call
$a = new $foo();
This is somewhat ambigous to read. You don't know if it is going to evaluate $foo as a class name, and then call
new WhateverTheClassName();
OR it could be that it will call $foo() first and evaluate that (make the function call), and then call
new ThisOtherClassName;
So I agree with the proposal in #16/#17.
Comment #20
jhodgdonProposed wording for coding standards:
When calling class constructors with no arguments, always include parentheses:
$foo = new MyClassName();
This is to maintain consistency with constructors that have arguments:
$foo = new MyClassName($arg1, $arg2);
The only exception to this is in the rare case that you need to use a variable for the class name. In that case, to avoid ambiguity over whether "new $classname()" means "evaluate variable $classname and then call that class's no-arg constructor", or "evaluate function $classname() and then call that class's no-arg constructor", we leave the parentheses out:
$foo = new $classname;
Comment #21
Island Usurper commentedI suppose it's an even rarer case that we would have
That's the only syntax that works here, so if people look at this and don't know what it does, they need to be told that "new" makes $classname evaluate to a class name and not a function. Semantic variable names go a long way towards that, I think.
Comment #22
Crell commentedIsland: The DB layer does that quite a bit, actually, and it was never a problem.
Comment #23
Island Usurper commentedCrell, that's actually my point. I guess it's not as rare as I thought.
I don't see how leaving off the parentheses for the one case of variable class name with no constructor arguments really helps the confusion. Class names can still look like function names except for our casing convention, which PHP doesn't care about.
I knew when I first saw this issue it would turn into a bikeshed. :)
Comment #24
jhodgdonOK....
So it sounds like whether you do new $foo(), new $foo($a, $b), or new $foo [no parens], you get the same behavior: $foo evaluates as a variable to the class name, then the constructor for that class is called. Correct?
In which case, and if we're using the new $foo($a, $b) syntax all over the code, then I think I agree with Island Usurper that saying not to do new $foo() is not any worse confusion.
Comment #25
morbus iffI knew that someone would run around trotting out lame coding tropes within 30 comments.
Comment #26
neclimdulI'm with the should have () crowd. I'm really of the opinion we should expect our developers to understand their language. And if we expect people to understand what happening when they call
new $foo($bar, $baz);then why can't we expect then to understand what's happening innew $foo();. Its just overall more consistent.Comment #27
merlinofchaos commentedI agree that the use of () would be more consistent than dropping it. I like having the ().
Comment #28
jhodgdonNew proposed standard:
When calling class constructors with no arguments, always include parentheses:
$foo = new MyClassName();
This is to maintain consistency with constructors that have arguments:
$foo = new MyClassName($arg1, $arg2);
Note that if the class name is a variable, the variable will be evaluated first to get the class name, and then the constructor will be called. Use the same syntax:
$bar = 'MyClassName';
$foo = new $bar();
$foo = new $bar($arg1, $arg2);
Can we adopt this?
Comment #29
Crell commentedI'm cool with #28.
Comment #30
morbus iffSame.
Comment #31
jbrown commented#28++
Comment #32
chx commentedSure. We can do #28
Comment #33
jhodgdonOK. I think everyone is agreed then. I can't find any comments above that disagree with #28, aside from arguments from the people above who explicitly said #28 is OK.
I'm going to add this to the coding standards page, in that case. Next step: A core patch to bring it into compliance with this standard. And then also to add this to Coder?
Comment #34
stella commented#28++
Comment #35
berdirThese should be all. I also changed 3 instances from "StdClass" to "stdClass".
Comment #36
jhodgdonThat patch is fine. Thanks!
Comment #37
dries commentedAlright, committed to CVS HEAD. Thanks!
Comment #38
jhodgdonWe need to (a) confirm that all new className() and new $classnamevar() have parens after this patch, and (b) file a Coder issue to get it checking for this, correct?
Comment #39
berdirI'm quite sure that I found all of them:
This simply looks for lines with "= new " and then removes those which have a "(". Not perfect since it will not find those that aren't assigned to a variable but I don't get any results for this now.
Comment #40
jhodgdonThat's reasonable. After expanding the grep to also look for lines like throw new FooException; and looking in the profiles and themes directories as well, I agree you probably got them all.
So is there a Coder issue, or should we file one?