I've been wondering whether this shorthand, if we may call it that, is an accepted practice of coding among pro PHP devs:
foo() && bar();
instead of
if( foo() ) {
bar();
}
While IMO the single line code is much neater, I've not seen it being used anywhere.
That is a common practice among developers of a number of languages. There is technically nothing wrong with it, but judging by the number of times it shows up on StackOverflow, I'll go ahead and say that it is a "use only when it is the only thing which makes sense." Most people don't expect it.
That said, this is perfectly valid:
foo()?bar()?bat():zonk():baz();
As is
foo() && bar() && baz();
Just remember:
function foo(){return true;}
function bar(){echo "bar";}
function baz(){echo "baz"; return 2;}
echo foo()||foo()?baz():baz(); // baz2
Personally, I see nothing wrong with it. It's fairly widespread, so most PHP programmers will understand it just as well as they would understand the extended version, making it perfectly acceptable.
The most important part is that you write code that is easy to read. Using function names like foo() and bar() for example are totally useless, so it's hard to say which one of the two you want to compare are better.
Next to that, the if example has some considerable flaws as well:
if is a language construct, but you use it like a function.
you add vertical space into the if condition. This can make things hard to read as spaces are influencing the visual focus.
An alternative suggestion would be:
if (foo()) {
But you wanted to compare the two: Code is always in it's context. And readable code uses it's context. Both of your suggestions can be valid, the key point is that you can read the meaning from the code already:
conditionMet() && gotForIt();
if (conditionMet()) goForIt();
Decide for yourself. Just don't mix from one line to the other, so keep one style through your whole code.
foo() && bar(); is a boolean expression, so it's wrong if you don't put it inside a boolean context (a condition like if, while, etc).
The code has to tell "the story" of the problem being solved, using this shortcut is not telling the story. It's an ugly hack, it's not elegant.
If you think about it as "neat", then you haven't yet reached the point where code means ideas, not code.
Related
In PHP, one can write
$a="$b$c";
This concatenates the assumed strings in $b and $c into $a elegantly (that is, using minimal yet clear syntax).
Now I want to move this statement into a function. The problem is that $b and $c are naturally interpreted as being local to this function, not its caller (which can be the global code or a function). Even if the caller defines $b and $c, this new function cannot see those definitions.
I want to do something clever that requires the statement to work the same (except for the location of $a) even though it has been moved into a function.
Furthermore, I want this to be efficient. No use of extract() or debug_backtrace(). Just want to use the caller's local scope. I don't mind if I use Zend to get the caller's symbol table, or any other hack, so long as it's efficient.
Don't worry, I'm not going to use this as general programming practice (ugh), just for one specific and wonderful purpose.
I know you don't want extract, but could this help?
<?php
function foo()
{
$b = 'Butter';
$c = 'Cup';
$v = get_defined_vars();
echo bar($v);
}
function bar($v)
{
extract($v);
return $b . $c;
}
foo();
Output:
ButterCup
There is no native PHP functionality for violating function scope in this way, other than backtraces included in debugging functions and exceptions.
I'd suggest looking at the C code for debug_backtrace() and seeing if you can write an extension that implements the bit of it you need (walking up the stack one step to find the parent symbol table) but which performs better than the existing function (I've no idea if that's possible, I don't know where the overhead comes from).
However, I would also recommend thinking really really hard about what problem you're actually trying to solve, and why it's led you to want to break function isolation in such an unusual way. Maybe there's a completely different solution.
For instance, if what you want is a kind of macro, rather than a function, you could write a pre-processor (or find one that's already been written) so that the code is literally pasted into place, and you don't need to hack the symbol table.
I was refactoring some old code when I stumbled upon a construct similar to this:
// function bar() returns a value
// if the value is an instance of customException class, terminate with error code
// else process the regular data
$foo = bar();
checkForException($foo) && exit($foo->errorCode());
process($foo);
Now strange as it might seem, this is a lot shorter then
$foo=bar();
if(checkForException($foo)) {
exit($foo->errorCode();
}
else {
process($foo);
}
And somewhat more readable (at least after the initial surprise) then
$foo=bar();
(checkForException($foo)) ? exit($foo->errorCode()) : process($foo);
While shorter code doesn't necessarily mean more readable code, I find this to be somewhere in the middle of the two "standard" ways above.
In other words, instead of
if($foo) {
bar();
}
else {
// there is no real reason for this to exist, since
// I have nothing to write here, but I want to conform
// to the general coding practices and my coding OCD
}
One could simply write
$foo && bar();
So what is the reasoning behind this not seeing much use? Can it be as simple as "Don't reinvent the wheel, write the more readable if/else, and if you really want to shorten it, that's what ternary operator is for"?
EDIT: Please keep in mind that the above code was quickly derived from the original code and was mean to be just an example of the use of "short circuit" code. If you can, please restrain from suggesting code improvements, since that was not the desired outcome of the question.
Example No.2
userCheckedTheBox($user) && displayAppropriateInfo();
While $foo && bar(); is fewer lines of code it's much less readable. Making your code easy to understand is usually more important than reducing the total LoC. Even if it's you're not working in an environment with multiple programmers, you will have to come back and read your code at some point in the future, and you probably won't be able to remember what the rationale was behind every line of code (Eagleson's Law).
Generally, you should limit the use of these kinds of statements to only those cases where the programmer's intent is absolutely clear. In my opinion, it's very bad practice to have code which tests a condition and code which actively modifies the current state of the program on the same statement.
Here's one acceptable use for this kind of code:
$isValidUser = $userName && usernameIsValid();
Here, both sides of the && operator are testing a condition, the fact that the right side is calling a function to do that does not harm the readability of the code.
There's an old technique which I believe was popular in hacked-together perl scripts to show errors. pseudo-code:
myFunction( ) || exitWithError( "Uh-oh" )
When coding-to-a-deadline, and when the user interface doesn't need to be stellar, it's a quick way to avoid errors.
The style is also popular in javascript for default parameters:
function myfunction(foo) {
foo = foo || 0;
// note that a non-zero default won't work so well,
// because the user could call the function with 0
}
and for null-checks:
var bar = foo && foo.property;
I find that once you're used to it, it's very readable and often more intuitive than if/else or ?:. But you should only use it when it makes sense. Using it everywhere is going to get very confusing. For example, in your example, you should not use it. Personally I use it for simple error checking and some default values. In big projects, you almost always want to do a lot more when an error occurs, so in those cases you shouldn't use this.
Also you should be careful; this only works in languages which have short-circuit evaluation (http://en.wikipedia.org/wiki/Short-circuit_evaluation). And sometimes and and or are short-circuit, while && and || are not.
myfunction() or die("I'm melting!"); is also quite satisfying to write.
Finally, empty else blocks as a rule is something I've never seen before, or heard anyone recommend. It seems very pointless to me. The most readable option for your example is, quite simply:
if( $foo ) {
bar( );
}
For errors you should use real exceptions:
try {
$foo = bar();
} catch(FooException $e) {
exit($e->errorCode);
}
process($foo);
See the documentation for errorhandling.
What ever that code is doing, returning an instance of CustomException just doesn't add up. Why not change the function definition a little:
function bar()
{
$stuff = true;
if ($stuff === true)
{
return 'Value on success';
}
//something went wrong:
throw new CustomException('You messed up');
}
try
{//here's the outlandish try-catch block
$foo = bar();
}
catch (CustomException $e)
{
exit($e->message());//fugly exit call, work on this, too
}
//carry on here, no exception was thrown
Also, calling that second function (checkForException($foo)) is just absurd. Function calls are cheap, but not free. You want to know if the function returned an instance of CustomException? Don't turn that into a function, but use instanceof. Using short-circuit to keep the number of chars (ad thus parse-time) down, while at the same time wasting resources on on all other levels is about as silly as turning up in a V8 mustang on a hyper-miling course.
Another possible Solution for your problem:
$foo = bar();
!checkForException($foo) or exit($foo->errorCode);
process($foo);
But better change !checkForException for isNoException or something along those lines.
In PHP, a static member or function can be accessed so long as the class name is a valid object or a string. This is mostly true. When the class name string is a property of an object, it can't be used directly. It must be copied to a simple variable before it can be used to access a static member. Here's an example:
class Foo {
protected $otherclass='Bar'; //string!
function out(){
$class=$this->otherclass;
echo $class::ALIAS; //Where everyone knows your name.
}
function noout_err(){
echo $this->otherclass::ALIAS; //syntax error, unexpected '::'
}
}
class Bar {
const ALIAS='Where everyone knows your name.'
}
This quirk has bothered me for a while now. So I've been wondering:
Is this a common limitation among OOP languages?
Can someone familiar with the internals of PHP explain why $this->classname::somefunction() is not desirable syntax?
This isn't meant to provoke a storm of 'because php sux' comments. I'm well aware of the language's peculiarities. I'd just like to know if there is a reason for this one other than 'it just grew that way'.
It is a limitation indeed and there's a reason for it:
The :: scope operator has an higher precedence over -> which means that:
$this->otherclass::ALIAS;
will be read as:
($this->(otherclass::ALIAS));
therefore triggering the error.
This is actually a feature that PHP inherited probably by C++.
Yeah, you can't do this, and there's no explicit reason for it. There's simply no syntax, messing up the grammar, to provide for this extreme edge case for which you've already demonstrated that there's a trivial workaround.
I'd hardly go so far as to call it a "limitation", and it's certainly no "quirk". PHP can't bake bread, either.
Really, if you see the code $this->classname::somefunction(), does it immediately make intuitive sense to you? Nah. It's good that you can't do this.
Ok, first of all, i suspect this is going to be closed.
Right, i have a question relating to using function calls inside statements as opposed to assigning to a variable first.
For example:
(code is in php, but question applies generally. Also, code is overly simplified)
if (myAmazingFunction() === true) {
// do something amazing
}
instead of
$amazingresult = myAmazingFuncton();
if ($amazingResult === true) {
// do something amazing
}
The question is:
Is there any performance, or other underlying pros or cons to each approach
Stylistically, is any of the approaches considered better than the other
In most languages, there will be no performance difference. In the first case, the compiler will allocate storage for the result of the function call before checking whether it is true. In the second case you're simply making this explicit.
If you are debugging, sometimes the second form is easier, as you can set a breakpoint on the second line and check the value returned by the function before the comparison is made - but then you see the result of the function by the path the executing code takes anyway in the example you've given. You can also re-use the value without rerunning the function, as Zac says in his comment.
Stylistically, this is going to be largely subjective. The only thing I'd say here is that if your variable name makes the purpose of the function output clear, then you might be adding something to the ability for others to understand your code easily.
#DavidM's answer is correct. However, I'd just like to add that stylistically, I think it depends on the name of the function and its context.
Example:
if ($food->tastesGood()) {
echo 'Mmmm!';
}
// vs.
$foodTastesGood = $food->tastesGood();
if ($foodTastesGood) {
echo 'Mmmm!';
}
In this case, it's very clear that the return value of the method tastesGood() is going to be a boolean from both the name of the method and its context. Using a temporary variable adds nothing to your code except making it redundant and less-readable at a glance. In addition, if the variable is not defined right before its used, then you have to go find the definition to understand the condition. In these cases, I would say use of a variable is worse.
Another example:
if ($dishes->wash() !== FALSE) {
echo 'Sparkly!';
}
// vs.
$dishesAreClean = $dishes->wash() !== FALSE;
if ($dishesAreClean) {
echo 'Sparkly!';
}
In this case, we can't really infer the return type of the wash() method from its name, and indeed, it would seem that it returns nothing on success and FALSE on errors. Checking if the dishes are clean then requires us to make sure that there were no errors, but the first case doesn't make for particularly readable or self-documenting code. The second case, however, adds very explicit information about what's going on by way of the temporary variable. In these cases, I would say use of a variable is better.
Is there any performance, or other underlying pros or cons to each approach
Performance-wise, assigning an extra variable that you will use only in your if condition will use extra memory, and one useless line of code. So it will use more memory. Will it be noticeable? Probably not.
Stylistically, is any of the approaches considered bad
Using the method in your if statement is perfectly valid, and I think it's a better approach, since you can read the code and see exactly what value is being tested in the if condition. No need to look for the variable and search where it was affected.
I'm creating a simple application using the Kohana PHP framework, just FYI. This is my first time with the framework.
While developing classes or functions I'm commenting my code using DocBlock. How should I comment my code while using the framework? I meant to code some parts of the code, not whole controllers.
Basically, I'm using following methods:
// Check if variable_name is greater than zero
if($this->var > 0) {
// do something
} else {
// do something
}
if( $result ) {
// display confirmation message
} else {
// display errors
}
Am I doing it right way? Is there a standard for inserting comments in the code?
I'm not using comments like "check if variable is greater than zero". I'm just wondering if is it good practice to put comments into the code.
Not related to visual style of the comments, but a comment like "Check if variable_name is greater than zero" is a bad comment in and by itself. All it does is duplicate the information on the line below. The code should contain names on variables, functions and other things that can be read to know what's going on.
Other than that, I see nothing wrong with the double-slash-comment types.
// Check if variable_name is greater than zero
Such comments are worthless. I only know little PHP, and even if I didn't knew anything about it, I could immediately tell (or at least, very confidently guess) that after looking at the line.
As a general (language-agnostic) rule of thumb, write code that is mostly self-documenting (by using descriptive names, avoiding non-obvious shortcuts, etc.) and only comment why you do something which looks wrong/strange.
Personally, I document inline sparingly (I do religiously put doc-blocks in for methods, classes and member variables though). I believe that code itself should be as self documenting as possible.
There will be times where you need to do something non-obvious or possibly even counter-intuitive. That's the time for inline comments. Try to explain not what the block of code does, but why it does it that way.
There's a great example in Phing's CodeCoverageReportTask class:
// Strange PHP5 reflection bug,
// classes without parent class or implemented interfaces
// seem to start one line off
if ($reflection->getParentClass() == NULL
&& count($reflection->getInterfaces()) == 0)
{
unset($coverageInformation[$classStartLine + 1]);
}
else
{
unset($coverageInformation[$classStartLine]);
}
And another good one just a few lines down from that:
// PHP5 reflection considers methods of a parent class to be part
// of a subclass, we don't
if ($method->getDeclaringClass()->getName() != $reflection->getName())
{
continue;
}
I completely agree that comments should never explain what the code does, only why. But, it is definitely good practice to put necessary comments into the code. When I go back and look over some of my code (PHP or other), I wish I had commented more clearly.
But, the only standard with comments is consistency! Be consistent and you don't have to worry so much about confusing comments (only about when to use them).
Some (if not most) PHP programmers use the double-slash method (//) for commenting their code. There really is no standard, and I've seen people who comment using the pound symbol (#) at the beginning of a line, and others who comment out blocks with /* and */.
Comments are liars!
The problem with comments is that you have to update them as you update your code. If you don't, you end up with code looking like this:
// sum $a and $b
$x = $a * $a - $b;
So the best way to document your code is to make it really clear! I would write your code like this:
if ( isPositive(3) ) {
doA();
} else {
doB();
}
if( $result ) {
displayConfirmationMsg();
} else {
displayErrors();
}
This code doesn't need comments at all, because it's very simple to understand it!
Well, anyway, when I do have to write comments (almost never), I go with the // notation, but I think it doesn't really matter.
By the way, check out this awesome video of Uncle Bob.