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.
Related
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.
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'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.
when I use some nested if / else statements, sometimes I get confused if my code logic corresponds to my original idea. I use some simple procedural code, so how can I train my understanding?
Try to split your code up into functions. If you have deeply nested if/else statements then you can probably create well-named functions for both the "if" tests and the resulting logic. For example, change:
if ($something == "a" && $somethingElse == "b") {
// code
}
else if ($whatever > 4) {
// more code
}
else {
// yet more code
}
to
if (condition1True()) {
handleCondition1();
}
else if (condition2True()) {
handleCondition2();
}
else {
handleDefaultCondition();
}
Making your code read more like English means you can more easily understand how it works. You can also split your functionality so that each function only needs to do something simple then compose those functions into higher-level behaviour.
EDIT: Regarding comments, I tend to go for well-named functions and variables rather than copious commenting. If you can read the code without comments then that's ideal, but obviously you will still need comments sometimes. Definitely worth writing Javadoc-style comments for each function detailing the meanings of the arguments and return value, but inline comments in the code are sometimes more hindrance than help.
Comments! Write your original ideas in comments above each if/else block, and then make sure the conditionals for each block match the pseudo code you outlined in the comment. If they do, go back after you're done an re-read the comments - if the logic in them still seems valid, then there's a good chance your code will be good to go. I find it much easier to read comments outlining what a conditional does than to decipher each conditional on the fly. Of course, that means keeping comments up to date as well.
One of the best programmers I've ever met stubbed out functions with comments detailing how the function was supposed to work. He could read it back in plain English to make sure it made sense, and then implementation was, as he said, a simple matter of translation. This may not be for everyone, but it may help you keep focused.
Simplify complex conditionals and inner logic with appropriate function calls. Refactor you code to make it more clear, into small chunks. Use switch statements if appropriate, polymorphism if dealing with similar objects, etc.
Seeing some sample code would help give a more appropriate example, but consider the following contrived example:
if($a.isAnimal && $a.animalIsAlive){
if($a.isDog){
if(!$a.hasHadWalk && date('h') > 6 && date('h') < 20){
getLeash();
attachLeashToCollar();
putOnShoes();
...
}else{
//doNotWalk
}
}else{
//some other stuff here
}
}
could be refactored into
if(canBreathe($a)){
if($a.isDog){
if(shouldWeWalk($a)){
walkDog();
}
}else{
//some other stuff here
}
}
function canBreathe($a){
return $a.isAlive && $a.isAnimal;
}
function walkDog(){
getLeash();
attachLeashToCollar();
putOnShoes();
...
}
function shouldWeWalk($a){
return (!$a.hasHadWalk && date('h') > 6 && date('h') < 20);
}
First make a copy of the PHP file ;-)
Then try to refactor some of the deeply nested conditionals code blocks into their own functions and choose the name of these functions carefully.
That will force you to think about the code.
I think
if (condition1True()) {
handleCondition1();
}
else if (condition2True()) {
handleCondition2();
}
else {
handleDefaultCondition();
}
this variant is more preferable, because of better understanding what program doing.
I am a C++ programmer starting with PHP. I find that I lose most of the debugging time (and my selfesteem!) due to undefined variables. From what I know, the only way to deal with them is to watch the output at execution time.
Are other strategies to notice these faults earlier (something like with C++ that a single compile gives you all the clues you need)?
This is a common complaint with PHP. Here are some ideas:
Use a code analysis tool. Many IDEs such as NetBeans will help also.
Just run the code. PHP doesn't have an expensive compilation step like C++ does.
Use unit testing. Common side effects include: better code.
Set error_reporting(-1), or the equivalent in your ini file.
Get xdebug. It's not preventative, but stack traces help with squishing bugs.
isset(), === null (identity operator), and guard clauses are your friends.
Loose and dynamic typing are a feature of the language. Just because PHP isn't strict about typing doesn't mean you can't be. If it really bugs you and you have a choice, you could try Python instead—it's a bit stricter with typing.
Log your E_NOTICE messages to a text file. You can then process logs with automated scripts to indicate files and lines where these are raised.
No. In PHP, you can only know a variable doesn't exist when you try to access it.
Consider:
if ($data = file('my_file.txt')) {
if (count($data) >= 0)
$line = reset($data);
}
var_dump($line);
You have to restructure your code so that all the code paths leads to the variable defined, e.g.:
$line = "default value";
if ($data = file('my_file.txt')) {
if (count($data) >= 0)
$line = reset($data);
}
var_dump($line);
If there isn't any default value that makes sense, this is still better than isset because you'll warned if you have a typo in the variable name in the final if:
$line = null;
if ($data = file('my_file.txt')) {
if (count($data) >= 0)
$line = reset($data);
}
if ($line !== null) { /* ... */ }
Of course, you can use isset1 to check, at a given point, if a variable exists. However, if your code relies on that, it's probably poorly structured. My point is that, contrary to e.g. C/Java, you cannot, at compile time, determine if an access to a variable is valid. This is made worse by the nonexistence of block scope in PHP.
1 Strictly speaking, isset won't tell you whether a variable is set, it tell if it's set and is not null. Otherwise, you'll need get_defined_vars.
From what I know the only way to deal with them is to watch the output at execution time.
Not really: To prevent these notices from popping up, you just need to make sure you initialize variables before accessing them the first time. We (sadly IMO) don't have variable declaration in PHP, but initializing them in the beginning of your code block is just as well:
$my_var = value;
Using phpDocumentor syntax, you can also kind of declare them to be of a certain a type, at least in a way that many IDEs are able to do code lookup with:
/** #desc optional description of what the variable does
#var int */
$my_var = 0;
Also, you can (and sometimes need to) use isset() / empty() / array_key_exists() conditions before trying to access a variable.
I agree this sucks big time sometimes, but it's necessary. There should be no notices in finished production code - they eat up performance even if displaying them is turned off, plus they are very useful to find out typos one may have made when using a variable. (But you already know that.)
Just watch not to do operations that requires the variable value when using it the first time, like the concatenate operator, .=.
If you are a C++ programmer you must be used to declare all variables. Do something similar to this in PHP by zeroing variables or creating empty array if you want to use them.
Pay attention to user input, and be sure you have registered globals off and check inputs from $_GET and $_POST by isset().
You can also try to code classes against structural code, and have every variable created at the beginning of a class declaration with the correct privacy policy.
You can also separate the application logic from the view, by preparing all variables that have to be outputted first, and when it goes to display it, you will be know which variables you prepared.
During development stages use
error_reporting(E_ALL);
which will show every error that has caused, all NOTICE errors, etc.
Keep an eye on your error_log as well. That will show you errors.
Use an error reporting system, example:
http://php.net/manual/en/function.set-error-handler.php
class ErrorReporter
{
public function catch($errno, $errstr, $errfile, $errline)
{
if($errno == E_USER_NOTICE && !defined('DEBUG'))
{
// Catch all output buffer and clear states, redirect or include error page.
}
}
}
set_error_handler(array(new ErrorReporter,'catch'));
A few other tips is always use isset for variables that you may / may not have set because of a if statement let’s say.
Always use if(isset($_POST['key'])) or even better just use if(!empty($_POST['key'])) as this checks if the key exists and if the value is not empty.
Make sure you know your comparison operators as well. Languages like C# use == to check a Boolean state whereas in PHP to check data-types you have to use === and use == to check value states, and single = to assign a value!
Unless I'm missing something, then why is no one suggesting to structure your page properly? I've never really had an ongoing problem with undefined variable errors.
An idea on structuring your page
Define all your variables at the top, assign default values if necessary, and then use those variables from there. That's how I write web pages and I never run into undefined variable problems.
Don't get in the habit of defining variables only when you need them. This quickly creates spaghetti code and can be very difficult to manage.
No one likes spaghetti code
If you show us some of your code we might be able to offer suggestions on how you can better structure it to resolve these sorts of errors. You might be getting confused coming from a C background; the flow may work differently to web pages.
Good practice is to define all variable before use, i.e., set a default value:
$variable = default_value;
This will solve most problems. As suggested before, use Xdebug or built-in debugging tools in editors like NetBeans.
If you want to hide the error of an undefined variable, then use #. Example: #$var
I believe that various of the Code Coverage tools that are available for PHP will highlight this.
Personally, I try and set variables, even if it's with an empty string, array, Boolean, etc. Then I use a function such as isset() before using them. For example:
$page_found = false;
if ($page_found==false) {
// Do page not found stuff here
}
if (isset($_POST['field'])) {
$value = $_POST['field'];
$sql = "UPDATE table SET field = '$value'";
}
And so on. And before some smart-ass says it: I know that query's unsafe. It was just an example of using isset().
I really didn't find a direct answer already here. The actual solution I found to this problem is to use PHP Code Sniffer along with this awesome extension called PHP Code Sniffer Variable Analysis.
Also the regular PHP linter (php -l) is available inside PHP Code Sniffer, so I'm thinking about customizing my configuration for regular PHP linting, detecting unused/uninitialized variables and validating my own code style, all in one step.
My very minimal PHPCS configuration:
<?xml version="1.0"?>
<ruleset name="MyConfig">
<description>Minimal PHP Syntax check</description>
<rule ref="Generic.PHP.Syntax" />
<rule ref="VariableAnalysis" />
</ruleset>