Wikka "Howto" Pages

Wikka Coding Guidelines


The following guidelines describe coding conventions adopted in Wikka. Please note this page is a draft - once it is completed, new and existing code should be made compliant with these guidelines.
Where examples are provided,

 

Code structure

(stub)

include and require

As we can read in the PHP docs about include: "require() and include() are identical in every way except how they handle failure. include() produces a Warning while require() results in a Fatal Error."

When a piece of code (for instance an action) depends on an external file to provide some of its functionality, for instance a library with functions, obviously require will be the one to use since proceeding without that dependency has little use. On the other hand, when an external file provides only some content to be displayed, include will normally be sufficient: if the file can't be found a warning will result, but the page won't be aborted.

include and require are statements, not functions. The parentheses (as in the little quote above) are optional in PHP. (According to the include docs: "Because include() is a special language construct, parentheses are not needed around its argument. Take care when comparing return value.")

So, in order to make them not look like a function, it's best to leave out the parentheses, reserving their use exclusively for functions, never for statements.

It is possible to include or require a file only conditionally. Obviously useful for blocks of content to be displayed, but it can also be more efficient to not require a library file unless it's really needed: for instance only after you've done input validation and concluded that it's OK to proceed. This can improve performance by not needlessly including code never executed.

When include and require are used conditionally, they must be inside a statement block, i.e., within braces.

Functions can't be re-defined in PHP. That implies that if you need to include a library file in an action, you must take care it's included just once (even if the action can be used only once on a page - a history page would show two or more versions and thus still "call" the action multiple times!). For content blocks on the other hand, it may actually be desirable to include it multiple times. So in general it's best to use require_once for code libraries and include for content blocks.

Conditions and loops

(stub - if/then/else, shortcuts, case, loops...)

Conditionals

Complex conditionals must be avoided
By introducing temporary boolean variables to expressions the code will be much easier to maintain.
not recommended:
if (($fh = fopen($rssFile,'w')) === FALSE)
{
  die('Failed to open file for writing!');
}

recommended:
$fh = fopen("file.txt","r");
if (FALSE == $fh)
{
  die('Failed to open file for writing!');
}


True before False in if/then/else
To ensure readability, keep the True part of the check in the if-segment, and the False part in the else-segment. This will ensure that the code is easy to read and that the logic is not obscured regarding the execution path.
not recommended:
if ($page["tag"] != $tag) return false;
else return true;

recommended:
if ($page["tag"] == $tag) return true;
else return false;


Do not short circuit logical tests
Short circuiting will sooner or later introduce logical error in your code. Avoid this at all costs by using the correct amount of parantheses.
not recommended:
if ( 8 == $i || 10 == $i && 12 == $j )
{
   ...
}

recommended:
if ( (8 == $i) || (10 == $i && 12 == $j) )
{
   ...
}



Do execute functions before conditionals
Executing functions inside conditionals can be quite difficult to read. This is double true for programmers new to PHP
if (FALSE === ($fh = fopen($rssFile,'w')))
{
  ...
}

recommended:
$fh = fopen("file.txt","r");
if (FALSE == $fh)
{
   ...
}


Constant must come before variable
Very often a logical bug is due to assignment inside the conditional. Assigning the value 12 to the varible $inputNumber will always yield true, but trying to assign the variable $inputNumber to the number 12 will result in a error.
not recommended:
if ($inputNubmer == 12)
{
  ...
}

recommended:
if (12 == $inputNumber)
{
   ...
}


Use switch structures rather than nested if-then-else
Switch structures enhances readability in your code.
not recommended:
if ($i == 0)
{
    echo "i equals 0";
} elseif ($i == 1) {
    echo "i equals 1";
} elseif ($i == 2) {
    echo "i equals 2";
}

recommended:
switch ($i)
{
  case 0:
      echo "i equals 0";
      break;
  case 1:
      echo "i equals 1";
      break;
  case 2:
      echo "i equals 2";
      break;
}

switch ($food)
{
  case "apple":
      echo "food is apple";
      break;
  case "bar":
      echo "food is bar";
      break;
  case "cake":
      echo "food is cake";
      break;
}


Naming conventions

Naming conventions vary widely between various coding guidelines for PHP found on the web - perhaps the biggest variation between them. But at least within a project (like Wikka) it's important to use one set of naming conventions: this greatly enhances readability of the code which is especially important when multiple developers are working on it.

Class and object names

A very widely-used rule that we'd like to see in Wikka (if only for consistency with most of the rest of the world!) is the following:
Unfortunately, the original authors of Wikka (or, more likely, Wakka) must have been unaware of any such rule so what we currently have mostly violates this. But that's not a reason to continue to do so... at least any new class, object, method or variable should follow this rule, and then at one time we can do a global search-and-replace and be done.

examples to be added

Method and function names

A very widely-used rule that we'd like to see in Wikka (if only for consistency with most of the rest of the world!) is the following:
Unfortunately, as in the case of Class and object names (above), the original authors of Wikka (or, more likely, Wakka) must have been unaware of any such rule so what we currently have mostly violates this. But that's not a reason to continue to do so... at least any new class, object, method or variable should follow this rule, and then at one time we can do a global search-and-replace and be done.

In addition to this basic rule, we add:

examples to be added

Variable names

Variable names should be in all lowercase, with words separated by an underscore. Names should be descriptive, but concise.

not recommended: (mixed case is not recommended for variables)
$CurrentUser = $this->getUserName();

not recommended: (words without separators make variable names hardly readable)
$currentuser = $this->getUserName();

recommended: (lowercase variables using underscore as word separators are readable and distinctive)
$current_user = $this->getUserName();



Constant names

Constants should follow the same conventions as variables, except use all UPPERCASE to distinguish them from variables.

not recommended: (lowercase is for variables)
define('default_width', 500);
$window_width = default_width;

not recommended: (words without separators make constant names hardly readable)
define('DEFAULTWIDTH', 500);
$window_width = DEFAULTWIDTH;

recommended: (uppercase constants using underscore as separators are readable and distinctive)
define('DEFAULT_WIDTH', 500);
$window_width = DEFAULT_WIDTH;




Names for text constants
Constants containing text - strings should be named accordingly to the function the text has:

recommended: (ERROR_ for error-messages, i.e. when wikka does not behave like the user expects)
define('ERROR_CIRCULAR_REFERENCE_DETECTED', 'Circular reference detected');
// here goes some code...
} else print '<span class="error">'.ERROR_CIRCULAR_REFERENCE_DETECTED.'</span>';


recommended: (BUTTON_ for buttons - or better BUTTON_LABEL?)
define('BUTTON_CHANGE', "Change");
// here goes some code...
<td><input type="submit" value="<?php echo BUTTON_CHANGE ?>" size="40" /></td>


recommended: (IMG_ALT_ for the alternative text provided with images)
define('IMG_ALT_XML_BUTTON', 'XML');
// here goes some code...
print '<img src="images/xml.png" width="36" height="14" alt="'.IMG_ALT_XML_BUTTON.'" />';


recommended: (used variable substitutes should be explained in a comment afterwards)
define('CATEGORY_PAGES_HEADER', 'The following %b pages belong to %s:'); // %b - number of pages, %s - name of the user
define('CATEGORY_NO_PAGES_FOUND', 'Sorry, no items found for %s.'); // %s - name of the page



Loop indices

The only situation where a one-character variable name is allowed is when it's the index for some looping construct. Unless you already have a specific counting variable, use $i as the variable for the outermost loop, then go onto $j for the next most outermost loop etc. Avoid using the variable $l (lowercase 'L') in any of your code as it looks too much like the number 'one'.

not recommended: (long names for loop indices are less readable and are easily confused with real variables)
for ($squares = 0; $squares < $shapes; $squares++)
{
    for ($triangles = 0; $triangles < $shapes; $triangles++)
    {
        foo($squares, $triangles);
    }
}

recommended: (one-character loop indices are distinctive and readable)
for ($i = 0; $i < $total; $i++)
{
    for ($j = 0; $j < $total; $j++)
    {
        foo($i, $j);
    }
}



Code layout

Some of these guidelines are just for readability but some also have a possible influence on how how efficiently code executes. If you need to make a choice though, human efficiency comes first: code needs to be read much more often than it needs to be written.

Braces

Braces should always be included when writing code using if, for, while etc. blocks. There are no exceptions to this rule, even if the braces could be omitted. Leaving out braces makes code harder to maintain in the future and can also cause bugs that are very difficult to track down.

not recommended: (Code more difficult to maintain, bugs hard to track down)
if (condition) foo();

if (condition)
    foo();

while (condition)
    foo();

for ($i = 0; $i < 10; $i++)
    foo($i);

recommended: (Easier to maintain, reduced risk of bugs)
if (condition)
{
    foo();
}

while (condition)
{
    foo();
}

do
{
    foo();
} while (condition)

for ($i = 0; $i < 10; $i++)
{
    foo($i);
}


Braces should be placed on a line on their own, indented to the same level as the control statement (BSD/Allman style). Statements within the braces should be indented to the next level. Braces should also align properly using tabs so a closing brace is always in the same column as the corresponding opening brace. The main advantages of using this indent style are that: the indented code is clearly set apart from the containing statement by lines that are almost completely whitespace, improving readability; the braces line up with the statement they conceptually belong to; and the ending brace lines up symmetrically in the same column with the beginning brace.

not recommended: (reduced readability)
if (condition) {
    while (condition2) {
        //...
    }
} else {
    //...
}

recommended: (improved readability)
if (condition)
{
    while (condition2)
    {
        //...
    }
}
else
{
    //...
}


Single vs. double quotes

Strings in PHP can either be quoted with single quotes (') or double quotes ("). As a general rule, you should use quotes only when needed, and prefer single quotes to double quotes anytime it is possible. The two main reasons to prefer single quotes are readability and performance. Single quotes make the code more readable, especially when it already contains double quotes which would then have to be escaped, as in the case of HTML strings.

not recommended: (A lot of escaping makes the code hardly readable)
$w3_logo = "<img alt=\"The World Wide Web Consortium (W3C)\" height=\"48\" width=\"315\" src=\"/Icons/w3c_main\" />";

recommended: (Code is much more readable)
$w3_logo = '<img alt="The World Wide Web Consortium (W3C)" height="48" width="315" src="/Icons/w3c_main" />';


Another, major difference between single and double quotes is that the parser will use variable-interpolation in double-quoted strings, but not with single-quoted strings. You should always use single quotes unless you specifically need variable interpolation to be done on that string. This way, you can save the parser the trouble of parsing a bunch of strings where no interpolation needs to be done.

not recommended: (Slower parsing)
$str = "Avoid this - it just makes more work for the parser.";

recommended: (Faster parsing)
$str = 'This is much better.';


Similarly, when using associative arrays, avoid using double quotes. Unless using a variable as the key (in which case there should be no quotes at all!), include the key name within single quotes to prevent any ambiguities, especially with constants:

not recommended: (What happens if 'example' is defined as a constant elsewhere?)
$str= $my_array[example];

not recommended: (Slower parsing)
$str= $my_array["example"];

recommended: (No ambiguity as to the name of the key and processing is faster than using double quotes )
$str = $my_array['example'];


In general, you should use quotes only when strictly needed. If you are passing a variable to a function, or accessing an array with a key that is stored in a variable, there is no need to use quotes:

not recommended: (Slower parsing)
theFunction("$var");
$str = $my_array["$example"];

recommended: (Faster parsing)
theFunction($var);
$str = $my_array[$example];


The use of double quotes is only recommended when you need to interpolate variables or escape sequences withing strings: since everything between single quotes is stored literally, variable interpolation requires double quotes

not recommended: (The parser will not interpolate the variable embedded in the string)
$str = 'My name is $user';

not recommended: (The "\n" will be literally displayed as such)
echo 'This is a sentence followed by a newline\n';

recommended: (The parser will correctly replace the variable embedded in the string)
$str = "My name is $user";

recommended: (The textual string will be displayed followed by a newline)
echo "This is a sentence followed by a newline\n";


As a general rule , to optimize processing always prefer string concatenation using single quotes to variable interpolation using double quotes:

not recommended: (Correct use of double quotes with interpolation, but slower parsing!)
$str = "My name is $user";

recommended: (Correct use of single strings with concatenation, faster)
$str = 'My name is'.$user;


Whitespace


Indenting
Use only tabs (and not multiple spaces) to indent your code (see below for how your editor may help with this). Indenting through an arbitrary number of spaces can result in longer and incoherent code from different contributors

not recommended: (single spaces clutter the code and make layout incoherences easier)
if ($x > 0)
{
           echo $x;
}

recommended: (tabs are a consistent and economical solution for indenting code)
if ($x > 0)
{
    echo $x;
}


Horizontal space between tokens
There should always be one space on either side of a token in expressions, statements etc. The only exceptions are the following: commas (,) - which should have one space after, but none before, semi-colons (;) - which should not have spaces on either side if they are at the end of a line, and one space after otherwise, concatenation operators (.) - which should not have space on either side.

Functions should follow the rules laid out already, i.e. no spaces between the function name and the opening bracket and no space between the brackets and the arguments, but one space between each argument.

Control statements such as if, for, while etc. should have one space on either side of the opening bracket, and one space before the closing bracket.

not recommended: (incorrect use of horizontal whitespace between tokens decreases readability)
$i=0;
$str='a'.'b'.'c';

recommended: (correct use of horizontal space between tokens increases readability)
$i = 0;
$str = 'a'.'b'.'c';

not recommended: (incorrect use of horizontal whitespace between tokens decreases readability)
if($i<7)
{
}

recommended: (correct use of horizontal space between tokens increases readability)
if ($i < 7)
{
}

not recommended: (incorrect use of horizontal whitespace between tokens decreases readability)
if ( ($i < 7)&&($j > 8) )
{
}

recommended: (correct use of horizontal space between tokens increases readability)
if ($i < 7 && $j > 8)
{
}

not recommended: (incorrect use of horizontal whitespace between tokens decreases readability)
myFunction( $i, $str, $b );
{
}

recommended: (correct use of horizontal whitespace between tokens increases readability)
myFunction($i, $str, $b);
{
}

not recommended: (incorrect use of horizontal whitespace between tokens decreases readability)
for($i=0; $i<$size; $i++)
{
}

recommended: (correct use of horizontal whitespace between tokens increases readability)
for ($i = 0; $i < $size; $i++)
{
}

not recommended: (incorrect use of horizontal whitespace between tokens decreases readability)
$i=($j < $size)?0:1;

recommended: (correct use of horizontal whitespace between tokens increases readability)
$i = ($j < $size) ? 0 : 1;


Vertical whitespace
(stub)

Trailing whitespace
(stub)

Type casting

In spite of (or because of!) PHP's dynamic variable types, it is often necessary to make sure a variable is of a specific type before working with (or accepting) it. (It is also advisable to actually use a boolean whenever an either/or choice is needed, instead of a number, let alone a string representing a number!) Although for instance intval($var) is equivalent to (int) $var the latter is much more readable especially inside expressions that already have a numerous brackets. The same applies to array($var) vs (array) $var.

not recommended: (incorrect use of type casting decreases readability)
if (3 > intval($this->GetConfigValue('some_setting')))
{
    $setting = (bool)$settingpar;
    $param = array($param);
}

recommended: (correct use of type casting increases readability)
if (3 > (int) $this->GetConfigValue('some_setting'))
{
    $setting = (bool) $settingpar;
    $param = (array) $param;
}


Comments

Re-write complex code instead of commenting
If the code is so complex that it requires lengthy explanations, then the code should be re-written. Comments should only be used to explain the logical flow of the program - and the code it self should be clear enough to be self documenting.

Comments should be readable and easy to spot
The content of the comment is important, make it readable! The content of a comment must not exceed 80 characters per line.

Use comments to group various parts of the code.

Multi line comments should have the form or a number of #-chars. The first and last line in a comment should really stand out by having a number of repeating * or # characters. Within the multi-line comment each line should start with either the * character or the # character, depending.

Single line comments must have a open line before the comment. Single line comments can either be the // notion followed by a space. It is also possible to use 3 consecutive lines with the # character where the 1 and 3rd lines does not have any content. The #-character must be followed by a space. Single line comments must follow the indentation of the surrounding code.

End of line comments should be indicated by the #-character.

recommended:
/* ****************************************************
 *
 * Copyright (C) 2002, 2003 Hendrik Mans <[email protected]>
 * Copyright (C) 2004, 2005 Jason Tourtelotte <[email protected]>
 * Copyright (C) 2006 Wikka Development Team <[email protected]>
 *
 ****************************************************** */


##################################################################################
# Copyright (C) 2002, 2003 Hendrik Mans <[email protected]>
# Copyright (C) 2004, 2005 Jason Tourtelotte <[email protected]>
# Copyright (C) 2006 Wikka Development Team <[email protected]>
##################################################################################


##################################################################################
# Initalize variables
##################################################################################

$name    = "";   # The users name
$address = "" ;  # The users address

##################################################################################
# Main routine
##################################################################################

// Grab HTTP GET
$name = $_GET['username'];
$address = $_GET['address'];

// Print out some information
print "The name is $name";

if ($name == "RubenOlsen")
{
    // Friendly greeting is in place
    print "Hello Ruben - have a nice day!";

} else {
    // Ordinary greeting
    print "Hello $name - now, get to work!";
}

#
# Print out concatenated information
#
print "Name and address $name, $address";


not recommended:
/* Copyright (C) 2002, 2003 Hendrik Mans <[email protected]>
Copyright (C) 2004, 2005 Jason Tourtelotte <[email protected]>
Copyright (C) 2006 Wikka Development Team <[email protected]> */

//Initialize variables
$name    = "";  
$address = "" ;
//Grab HTTP GET
$name = $_GET['username'];
$address = $_GET['address'];
print "The name is $name";//Print out some information
if ($name == "RubenOlsen")
{
//Friendly greeting is in place
    print "Hello Ruben - have a nice day!";
} else {
    print "Hello $name - now, get to work!";//Ordinary greeting
}
# Print out concatenated information
print "Name and address $name, $address";



Wikka specific comments
(need more info regarding the @input, @output, etc)

PHP Doc
(need more info)



Wikka-specific guidelines

While most guidelines apply in general to writing PHP code as we would like to see it in Wikka, Wikka has a specific architecture for which we need a number of specific guidelines as well.

Code structure

(stub - explains the structure of actions and handlers, i.e. their organization in different sections)

Using core methods

(stub)

Actions vs. handlers

(stub)

Action parameters

(stub)

File naming conventions

(stub)

Variables and parameters

Be consistent in naming variables and parameters. Use the same name for the same type of thing, even in an unrelated bit of code: it makes reading and understanding code much easier. For instance:

There are still quite a few cases where these rules are violated in our current code - they make the code much harder to understand, in particular when inappropriate or inconsistent names are used as formal inside methods and functions. Please correct when you come across such cases (after making sure you understand what's really meant) - and of course don't create any new ones. :)

Third-party code

Wikka includes a number of third-party packages for its basic functionality. In general, whatever coding standard a third-party package uses, should be left alone. When a class is used and Wikka needs a slightly changed (or extended) functionality, it's generally best to just write a wrapper in Wikka that extends the class. Only when this is really not possible should code changes be considered.

When making code changes to third-party software in Wikka, two important guidelines apply:


Editor settings

Many editors can help implementing some of the coding standards and not only enforce consistency this way, but save you a bunch of time as well. A good "programmer's" editor will have settings to enforce line endings (when creating a new file and/or when saving a file) and for gettng rid of spurious white space at the end of lines (as a function, or as a setting to automatically do this when saving a file).

Tabs vs. spaces


:set ai (Auto indent)
:set noet (Don't change tabs into spaces "on the fly")
:set ts=4 (4 spaces per tab)

:%s/    /^I/g


Trailing whitespace


Line endings

(stub)



CategoryHowto
CategoryDevelopment
There are 3 comments on this page. [Show comments]
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki