Revision [14743]

This is an old revision of CodingGuidelinesHowto made by DarTar on 2006-06-30 11:49:42.

 

WikkaHowto Wikka "Howto" Pages

Wikka Coding Guidelines

Last edited by DarTar:
Cloned from WikkaCodingGuidelinesHowto
Fri, 30 Jun 2006 11:49 UTC [diff]

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 documentation

Documentation is essential! Even well-written code is not necessarily self-documenting; there is always some decision-making involved, for instance, in why you coded something the way you did, why a particular algorithm is chosen, etc. Such "why" decisions should be documented. Also, pieces of code that need to be used by others, such as classes and functions (and in Wikka this includes actions and handlers) need to have their interface documented so others can make use of the functionality without needing to read all the code first.

In fact, when starting to write something new, it's a good idea to start with the documentation - and then work that out into code.

It's important that such documentation "travels with" the code, instead of having it externally. That's where comments come in, and specific guidelines for how to write comments for multiple purposes. A tool like phpDocumentor can help to make a user-friendly and cross-referenced documentation for others to use by parsing the code looking for structures like classes and functions and for structured comments, and outputting fully-crossreferenced HTML documentation.

phpDoc docblocks

This section uses materials adapted from the phpDoc manual
Self-documenting code can be created by adding phpDoc docblocks. Every file, class, function and - where needed - constant or variable should be introduced by a docblock.

A docblock is an extended C++-style PHP comment that begins with /** and has an * at the beginning of every line. Docblocks always precede the element they are documenting.

/**
 * The most basic Wikka function.
 */

function foo()
{
}

A docblock contains three basic segments in this order:
The Short Description starts on the first line, and can be terminated with a blank line or a period. A period inside a word is ignored. If the Short Description becomes more than three lines long, only the first line is taken. The Long Description continues for as many lines as desired and may contain html markup for display formatting. Here is a sample docblock with a Short and a Long Description:

/**
 * Display information about the system Wikka is running on.
 *
 * Depending on the 'show' parameter, this action displays different types of system information.
 * By default it only displays this information to Wikka Admins, this option can be changed by
 * setting 'public_sysinfo' to '1' in the Wikka configuration file.
 *
 *  Syntax:
 *  {{system [show="OS|machine|host"]}}
 *
 */

You can optionally use a limited set of HTML elements in the Long Description if needed. Long Descriptions can also contain lists like in the following example:

/**
 * Simple DocBlock with simple lists
 * Here's a simple list:
 * - item 1
 * - item 2, this one
 *   is multi-line
 * - item 3
 * end of list.  Next list is ordered
 * 1 ordered item 1
 * 2 ordered item 2
 * end of list. This is also ordered:
 * 1. ordered item 1
 * 2. ordered item 2
 */


The last (and most important) part of a docblock contains tags that add information on the documented item. Tags are single words prefixed by a @ symbol.

Wikka uses a subset of all the possible tags supported by phpDoc (for the complete list of phpDoc tags check this page)

/**
 * A short description
 *
 * As many lines of extendend description as you want {@link element}
 * links to an element {@link http://www.example.com Example} links to
 * a website.
 *
 * @access       public or private
 * @author       Author Name <author@email>
   or
 * @author       {@link http://wikkawiki.org/UserPage author name} (further notes)  
 * @copyright    name date
 * @deprecated   description
 * @example      /path/to/example (include an external example file with syntax highlighting)
 * @global       type $globalvarname
   or
 * @global       type description of global variable usage in a function
 * @ignore
 * @internal     private information for advanced developers only
 * @link         URL
 * @name         Name of the handler/action/formatter, e.g. recentchanges
 * @package        package name, e.g. Handlers
 * @param        type [$varname] description
 * @return       type description
 * @see          name of another element that can be documented (displays an internal link to the documentation for that element)
 * @since        Wikka version number
 * @subpackage    sub package name, e.g. Page (for page handlers)
 * @todo         item for a todo lisy
 * @var        type    a data type for a class variable
 * @version    version (will use SVN $Id$)
 */

function foo()
{
// ...
}


(stub - file/class/function/constant/variable - refer to page with templates)

Single-line comments vs. comment blocks

(stub)

End-of-line comments

(stub)

Special markers

(stub - conventions for things like "todo" and "fixme" remarks)


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 brackets (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 brackets (use those 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 efficient not to 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 will make the code more efficient by not needlessly including code that may not be 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...)


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

(stub)

Method and function names

(stub)

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 substitues 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();
}

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. Include the key 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)

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)

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 ony 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 settnig to automatically do this when saving a file).

Tabs vs. spaces


Trailing whitespace


Line endings

(stub)



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