Replacing IF with a logical expression in PHP - php

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.

Related

Best practice for returning in PHP function/method

I am refactoring an extensive codebase overtime. In the long run we are going to develop the whole system in classes but in the mean time I am using the opportunity to refine my PHP skills and improve some of the legacy code we use across several hundred websites.
I have read conflicting articles over time about how best to return data from a custom function, generally the debate falls into two categories, those concerned about best technical practice and those concerned about ease of reading and presentation.
I am interesting in opinions (with elaboration) on what you consider best practice when returning from a custom PHP function.
I am undecided as to which of the following as a better standard to follow using this basic theoretical function for example;
Approach a.
Populating a return variable and returning it at the end of the function:
<?php
function theoreticalFunction( $var )
{
$return = '';
if( $something > $somethingelse ){
$return = true;
}else{
$return = false;
}
return $return;
}
?>
Approach b.
Returning at each endpoint:
<?php
function theoreticalFunction( $var )
{
if( $something > $somethingelse ){
return true;
}else{
return false;
}
}
?>
A possible duplicate could have been What is the PHP best practice for using functions that return true or false? however this is not limited to simply true or false despite my basic example above.
I have looked through the PSR guidelines but didn't see anything (but I may have missed it so please feel free to point me to PSR with reference :) ).
Extending the original question:
Is the method used to return different depending on the expected/desired output type?
Does this method change depending on the use of procedural or object oriented programming methods? As this question shows, object orientation brings in its own eccentricities to further extend the possible formatting/presentation options Best practices for returns methods in PHP
Please try to be clear in your explanations, I am interested in WHY you choose your preferred method and what, if anything, made you choose it over another method.
I tend towards early returns - leave the function as soon as you know what is going on. One type of this use if called a 'Guard Clause'
Other things I will often do include dropping final else for a default:
if ($something > $somethingelse) {
return true;
}
return false;
and in fact, conditions of the form if (boolean) return true; else return false, can be shortened even further (if it is clearer to you) to just return ($something > $somethingelse);. Extracting a complex if clause from code like this to a usefully named function can help clear up the meaning of code a lot.
There are people arguing for single exit points in functions (only one return at the end), and others that argue for fail/return early. It's simply a matter of opinion and readability/comprehensibility on a case-by-case basis. There is hardly any objective technical answer.
The reality is that it's simply not something that can be prescribed dogmatically. Some algorithms are better expressed as A and others work better as B.
In your specific case neither is "best"; your code should be written as:
return $something > $somethingelse;
That would hopefully serve as example that there's simply no such thing as a generally applicable rule.
I know this question is old but the it is interesting and according to me
there are many things to say about it.
The first thing to say is that there is no real standard about returning in functions or methods.
It's usually ruled by the rules your team has decided to follow, but if you are the only one on this refactoring you can do what you think better.
In the case of returning a value the important thing I guess is
readability. Sometimes it's better to loose a little bit
of performance for a code that is more readable and maintainable.
I will try to show some examples with pros and cons.
Approach A
<?php
function getTariableType($var = null)
{
if (null === $var) {
return 0;
} elseif (is_string($var)) {
return 1;
} else {
return -1;
}
}
Pros:
Explicitness. Each case explains itself, even without any comments.
Structure. There is a branch for each case, every case is delimited clearly
and it's easy to add a statement for a new case.
Cons:
Readability. All these if..else with brackets make the code hard to read and
we really have to pay attention to every part to understand.
Not required code. The last else statement is not required and the code would be
easier to read if the return -1 was only the last statement of the function,
outside of any else.
Approach B
<?php
function isTheVariableNull($var)
{
return (null === $var);
}
Pros:
Readability. The code is easy to read and understand, at the first look we
know that the function is checking whether the variable is null.
Conciseness. There is only one statement and in this case it's fine and clear.
Cons:
Limit. This notation is limited to really little funtions. Using this notation
or even ternary operator becomes harder to understand in more complicated
functions.
Approach C.1
<?php
function doingSomethingIfNotNullAndPositive($var)
{
if (null !== $var) {
if (0 < $var) {
//Doing something
} else {
return 0;
}
} else {
return -1;
}
}
Pros:
Explicitness. Each case is explicit we can reconstruct the logic of the
function when reading it.
Cons:
Readability. When adding many if..else statements the code is really less
readable. The code is then indented many times looks dirty. Imagine the code
with six nested if.
Difficulty to add code. Because the logic seems complex (even if it is not),
it's difficult to add code or logic into the function.
Plenty of logic. If you have many if..else nested it is perhaps because you
should create a second function. NetBeans IDE for example suggests you to create
an other function that handles the logic of all your nested blocks. A function
should be atomic, it should do only one thing. If it does too much work, has
too much logic, it's hard to maintain and understand. Creating an other function
may be a good option.
Approach C.2
This approch aims to present an alternative to the C.1 notation.
<?php
function doingSomethingIfNotNullAndPositive($var)
{
if (null === $var) {
return -1;
} elseif (0 >= $var) {
return 0;
}
//Doing something
}
Pros:
Readability. This notation is very readable. It's
easy to understand what result we will get according to a given value.
Explicitness. As C.1, this approach is explicit in every branch of the
condition.
Cons:
Difficulty to add logic. If the function becomes a bit more complicated,
adding logic would be difficult because we may need to move all the branches of the
condition.
Approach D
<?php
function kindOfStrlen($var)
{
$return = -1;
if (is_string($var)) {
$return = strlen($var);
}
return $return;
}
Pros:
Default value. In this structure we can see that the default value is handled
from the beginning. We have logic in our function, but if we enter in no
branch we have a value anyway.
Ease to add logic. If we need to add a branch if it's easy and it does not
change the structure of the function.
Const:
Not required variable. In this case the $return variable is not required, we
would write the same function without using it. The solution would be to
return -1 at the end, and return strlen($var) in the if, and it would not
be less readable.
Conclusion
I have not listed all the possible notation here, only some of them. What we can
think about them is there is no perfect one, but in some cases an approach seems
better that an other. For example an is_null function would be fine with the
approach B.
Using an approach or an other is really up to you, the important thing is to
choose a logic and to keep it during all your project.
Using the approach b is more fine with me because in approach a you have written very few lines of code, but if there are many lines of code and many return statements, then are chances that i will somewhere use the wrong return type, where $return was assigned a some other place and i did not notice that.
I prever variant b. Not only is it more readable ( you know exactly that you do not need to consider any of the remaining code after a return statement), but it is also more failsafe.
If you either have a bug in the remaining code, or you encounter a set of conditions you did not take into account when designing the system, it would be possible that your result is changed. This cannot happen when you exit the function with return [$someVariable];
<?php
function theoreticalFunction( $var )
{
if( $something > $somethingelse ){
return true;
}
return false;
}
?>
This approach can also be used as on RETURN Statement, the program cursor is returned back and the next statement will not be executed.

"If" with assignment is a good practice?

consider this case:
large code:
if($site->getUser($id)){
$user = $site->getUser($id);
//more code here
}
short code:
if($user = $site->getUser($id)){
//already have the user
//more code here
}
in the first case, I do 2 access to bbdd for get the user, but in the second only one...
the second case, is a good practice?
I prefer this.
$user = $site->getUser($id);
if($user){
//more code here
}
Generally, assignments in conditions should be avoided. Many programming languages don't even allow it anymore. Too easy to make a mistake.
It's also better in terms of readability.
Repeatedly calling a function which is potentially expensive and/or has side effects is certainly not a good thing to do in any case, so your first sample should generally be avoided. Exceptions may be if the method is purely a passive getter method which does not execute any logic code; but since this implementation may change, you should still avoid it.
if ($foo = bar()) ...
Against the above can be argued that typos confusing = and == are not uncommon, so this may lead to bugs and/or be needlessly confusing to future developers reading the code. The least controversial method should be:
$foo = bar();
if ($foo) ...
However, some prefer to shorten this to an assignment-in-if; it's a stylistic choice.
Yes,in my opinion.
But, i am accustomed to code like this.
if($user = ($site->getUser($id) ) ){
//already have the user
//more code here
}
Warning this
if($flag = $usrType == $type) ){
//already have the user
//more code here
}

Common practice?

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.

Commenting code in PHP while using a framework

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.

for each ... break

I feel dirty every time I "break" out of a for-each construct (PHP/Javascript)
So something like this:
// Javascript example
for (object in objectList)
{
if (object.test == true)
{
//do some process on object
break;
}
}
For large objectLists I would go through the hassle building a more elegant solution. But for small lists there is no noticeable performance issue and hence "why not?" It's quick and more importantly easy to understand and follow.
But it just "feels wrong". Kind of like a goto statement.
How do you handle this kind of situation?
I use a break. It's a perfectly cromulent solution.
It's quick and more importantly easy to understand and follow.
Don't feel bad about break. Goto is frowned upon because it's quick and more importantly not easy to understand and follow.
See, the break doesn't bug me at all. Programming is built on goto, and for-break - like all control structures - is merely a special-purpose form of goto meant to improve the readability of your code. Don't ever feel bad about writing readable code!
Now, I do feel dirty about direct comparisons to true, especially when using the type-converting equality operator... Oh yeah. What you've written - if (object.test == true) - is equivalent to writing if (object.test), but requires more thought. If you really want that comparison to only succeed if object.test is both a boolean value and true, then you'd use the strict equality operator (===)... Otherwise, skip it.
For small lists, there's no issue with doing this.
As you mention, you may want to think about a more 'elegant' solution for large lists (especially lists with unknown sizes).
Sometimes it feels wrong, but it's all right. You'll learn to love break in time.
Like you said ""why not?" It's quick and more importantly easy to understand and follow."
Why feel dirty, I see nothing wrong with this.
I think is is easier to read and hence easier to maintain.
It is meant to be like it. Break is designed to jump out of a loop. If you have found what you need in a loop why keep the loop going?
Breaks and continues are not gotos. They are there for a reason. As soon as you're done with a loop structure, get out of the loop.
Now, what I would avoid is very, very deep nesting (a.k.a. the arrowhead design anti-pattern).
if (someCondition)
{
for (thing in collection)
{
if (someOtherCondition)
{
break;
}
}
}
If you are going to do a break, then make sure that you've structure your code so that it's only ever one level deep. Use function calls to keep the iteration as shallow as possible.
if (someCondition)
{
loopThroughCollection(collection);
}
function loopThroughCollection(collection)
{
for (thing in collection)
{
if (someOtherCondition)
{
doSomethingToObject(thing);
break;
}
}
}
function doSomethingToObject(thing)
{
// etc.
}
I really don't see anythign wrong with breaking out of a for loop. Unless you have some sort of hash table, dictionary where you have some sort of key to obtain a value there really is no other way.
I'd use a break statement.
In general there is nothing wrong with the break statement. However your code can become a problem if blocks like these appear in different places of your code base. In this case the break statements are code small for duplicated code.
You can easily extract the search into a reusable function:
function findFirst(objectList, test)
{
for (var key in objectList) {
var value = objectList[key];
if (test(value)) return value;
}
return null;
}
var first = findFirst(objectList, function(object) {
return object.test == true;
}
if (first) {
//do some process on object
}
If you always process the found element in some way you can simplify your code further:
function processFirstMatch(objectList, test, processor) {
var first = findFirst(objectList, test);
if (first) processor(first);
}
processFirst(
objectList,
function(object) {
return object.test == true;
},
function(object) {
//do some process on object
}
}
So you can use the power of the functional features in JavaScript to make your original code much more expressive. As a side effect this will push the break statement out of your regular code base into a helper function.
Perhaps I'm misunderstanding your use-case, but why break at all? I'm assuming you're expecting the test to be true for at most one element in the list?
If there's no performance issue and you want to clean up the code you could always skip the test and the break.
for (object in objectList)
{
//do some process on object
}
That way if you do need to do the process on more than one element your code won't break (pun intended).
Use a
Object object;
int index = 0;
do
{
object = objectList[index];
index++;
}
while (object.test == false)
if breaking from a for loop makes you feel uneasy.
My preference is to simply use a break. It's quick and typically doesn't complicate things.
If you use a for, while, or do while loop, you can use a variable to determine whether or not to continue:
for ($i = 0, $c = true; ($i < 10) && $c; $i++) {
// do stuff
if ($condition) {
$c= false;
}
}
The only way to break from a foreach loop is to break or return.

Categories