Wiki source for CodingGuidelinesHowto
[[WikkaHowto | Wikka "Howto" Pages]]
----
=====Wikka Coding Guidelines=====
>>==See also:==
~-[[DocumentingCodeHowto | Code Documentation Tutorial]]
>>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,
~- a red caption **{{color c="red" text="not recommended"}}** indicates code violating the present guidelines;
~- a green caption **{{color c="green" text="recommended"}}** indicates code complying with the present guidelines.
<<==Table of contents==""<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Code_structure">Code structure</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_include_and_require"><tt>include</tt> and <tt>require</tt></a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Conditions_and_loops">Conditions and loops</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Naming_conventions">Naming conventions</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Class_and_object_names">Class and object names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Method_and_function_names">Method and function names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Variable_names">Variable names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Constant_names">Constant names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Loop_indices">Loop indices</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Code_layout">Code layout</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Braces">Braces</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Single_vs._double_quotes">Single vs. double quotes</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Whitespace">Whitespace</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Type_casting">Type casting</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Wikka-specific_guidelines">Wikka-specific guidelines</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Code_structure_1">Code structure</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Using_core_methods">Using core methods</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Actions_vs._handlers">Actions vs. handlers</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Action_parameters">Action parameters</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_File_naming_conventions">File naming conventions</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Variables_and_parameters">Variables and parameters</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Third-party_code">Third-party code</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Editor_settings">Editor settings</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Tabs_vs._spaces">Tabs vs. spaces</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Trailing_whitespace_2">Trailing whitespace</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Line_endings">Line endings</a></li>
</ul>
</ul>""<<::c::
====Code structure====
(stub)
===##include## and ##require##===
~-**How to choose the correct one** ---
~As we can read in the PHP docs about [[PHP:include | 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. ---
~-**Format** ---
~##include## and ##require## are **//statements//**, not functions. The parentheses (as in the little quote above) are optional in PHP. (According to the [[PHP:include | 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. ---
~-**Conditional includes** ---
~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. ---
~-**Including once or more?** ---
~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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if (($fh = fopen($rssFile,'w')) === FALSE)
{
die('Failed to open file for writing!');
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
$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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ($page["tag"] != $tag) return false;
else return true;
%%
**{{color c="green" text="recommended:"}}**
%%(php)
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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ( 8 == $i || 10 == $i && 12 == $j )
{
...
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
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
%%(php)
if (FALSE === ($fh = fopen($rssFile,'w')))
{
...
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
$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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ($inputNubmer == 12)
{
...
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
if (12 == $inputNumber)
{
...
}
%%
== Use switch structures rather than nested if-then-else ==
Switch structures enhances readability in your code.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ($i == 0)
{
echo "i equals 0";
} elseif ($i == 1) {
echo "i equals 1";
} elseif ($i == 2) {
echo "i equals 2";
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
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:
~-class and object names start with a **capital**
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:
~-method and function names start with a **lowercase character**
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:
~-method and function names should be descriptive, and use camelCaseWords to separate words
~-methods/functions returning a boolean (TRUE or FALSE) should have a name that naturally suggests this, such as isRegistered or existsPage
// 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.
**{{color c="red" text="not recommended:"}}** (mixed case is not recommended for variables)
%%(php)$CurrentUser = $this->getUserName();%%
**{{color c="red" text="not recommended:"}}** (words without separators make variable names hardly readable)
%%(php)$currentuser = $this->getUserName();%%
**{{color c="green" text="recommended:"}}** (lowercase variables using underscore as word separators are readable and distinctive)
%%(php)$current_user = $this->getUserName();%%
~& A_lot_of_under_scores_are_hard_to_read - we should also allow camelCased variable names as long as the name begins with a lower-case letter
~& RubenOlsen
===Constant names===
Constants should follow the same conventions as variables, except use all UPPERCASE to distinguish them from variables.
**{{color c="red" text="not recommended:"}}** (lowercase is for variables)
%%(php)
define('default_width', 500);
$window_width = default_width;
%%
**{{color c="red" text="not recommended:"}}** (words without separators make constant names hardly readable)
%%(php)
define('DEFAULTWIDTH', 500);
$window_width = DEFAULTWIDTH;
%%
**{{color c="green" text="recommended:"}}** (uppercase constants using underscore as separators are readable and distinctive)
%%(php)
define('DEFAULT_WIDTH', 500);
$window_width = DEFAULT_WIDTH;
%%
~& While these general guidelines for naming constants are (mostly) fine, in working on the language file (to enable localization of Wikka) I found the ones presented are actually far too vague for specific usage. Constants have many uses, and different uses actually warrant their own guidelines. Naming constants to be used for regular expression building is quite a different proposition from naming constants for defining default values for parameters, or for text strings for a language file to be used by translators for localizing Wikka. So, I'm going to start a few subpages for developing guidelines for naming different **groups** of constants. I'm putting this comment here, on purpose, because what follows about names for text constants will (ultimately) be largely replaced by one or more specific subpages. So, for now, I think we'll need these (and possibly more) pages:
~~-CodingGuidelinesTextConstants - for (to be localized) text appearing in in the Wikka userinterface
~~-""CodingGuidelinesRegexConstants"" - for a collection of Regular Expressions and RE "building blocks"
~~-""CodingGuidelinesDefaultConstants"" - for defining default values for action, handler, or form default values
~&-- JavaWoman
== Names for text constants ==
Constants containing text - strings should be named accordingly to the function the text has:
**{{color c="green" text="recommended:"}}** (ERROR_ for error-messages, i.e. when wikka does not behave like the user expects)
%%(php)
define('ERROR_CIRCULAR_REFERENCE_DETECTED', 'Circular reference detected');
// here goes some code...
} else print '<span class="error">'.ERROR_CIRCULAR_REFERENCE_DETECTED.'</span>';
%%
**{{color c="green" text="recommended:"}}** (BUTTON_ for buttons - //or better BUTTON_LABEL?//)
%%(php)
define('BUTTON_CHANGE', "Change");
// here goes some code...
<td><input type="submit" value="<?php echo BUTTON_CHANGE ?>" size="40" /></td>
%%
**{{color c="green" text="recommended:"}}** (IMG_ALT_ for the alternative text provided with images)
%%(php)
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.'" />';
%%
**{{color c="green" text="recommended:"}}** (used variable substitutes should be explained in a comment afterwards)
%%(php)
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
%%
~& The following is missing:
~~& what prefix for link texts ("title" and <a>the text between</a>)
~~& where to put the constants and how to name the section
===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'.
**{{color c="red" text="not recommended:"}}** (long names for loop indices are less readable and are easily confused with real variables)
%%(php)for ($squares = 0; $squares < $shapes; $squares++)
{
for ($triangles = 0; $triangles < $shapes; $triangles++)
{
foo($squares, $triangles);
}
}%%
**{{color c="green" text="recommended:"}}** (one-character loop indices are distinctive and readable)
%%(php)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.
**{{color c="red" text="not recommended:"}}** (Code more difficult to maintain, bugs hard to track down)
%%(php)
if (condition) foo();
if (condition)
foo();
while (condition)
foo();
for ($i = 0; $i < 10; $i++)
foo($i);
%%
**{{color c="green" text="recommended:"}}** (Easier to maintain, reduced risk of bugs)
%%(php)
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.
**{{color c="red" text="not recommended:"}}** (reduced readability)
%%(php)
if (condition) {
while (condition2) {
//...
}
} else {
//...
}
%%
**{{color c="green" text="recommended:"}}** (improved readability)
%%(php)
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.
**{{color c="red" text="not recommended:"}}** (A lot of escaping makes the code hardly readable)
%%(php)$w3_logo = "<img alt=\"The World Wide Web Consortium (W3C)\" height=\"48\" width=\"315\" src=\"/Icons/w3c_main\" />";%%
~& We should have a better example as single quotes are allowed i HTML, thue reducing the need for escaping anything.
~& RubenOlsen
**{{color c="green" text="recommended:"}}** (Code is much more readable)
%%(php)$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.
**{{color c="red" text="not recommended:"}}** (Slower parsing)
%%(php)$str = "Avoid this - it just makes more work for the parser.";%%
**{{color c="green" text="recommended:"}}** (Faster parsing)
%%(php)$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:
**{{color c="red" text="not recommended:"}}** (What happens if 'example' is defined as a constant elsewhere?)
%%(php)$str= $my_array[example];%%
**{{color c="red" text="not recommended:"}}** (Slower parsing)
%%(php)$str= $my_array["example"];%%
**{{color c="green" text="recommended:"}}** (No ambiguity as to the name of the key and processing is faster than using double quotes )
%%(php)$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:
**{{color c="red" text="not recommended:"}}** (Slower parsing)
%%(php)theFunction("$var");
$str = $my_array["$example"];%%
**{{color c="green" text="recommended:"}}** (Faster parsing)
%%(php)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
**{{color c="red" text="not recommended:"}}** (The parser will not interpolate the variable embedded in the string)
%%(php)$str = 'My name is $user';%%
**{{color c="red" text="not recommended:"}}** (The "\n" will be literally displayed as such)
%%(php)echo 'This is a sentence followed by a newline\n';%%
**{{color c="green" text="recommended:"}}** (The parser will correctly replace the variable embedded in the string)
%%(php)$str = "My name is $user";%%
**{{color c="green" text="recommended:"}}** (The textual string will be displayed followed by a newline)
%%(php)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:
**{{color c="red" text="not recommended:"}}** (Correct use of double quotes with interpolation, but slower parsing!)
%%(php)$str = "My name is $user";%%
**{{color c="green" text="recommended:"}}** (Correct use of single strings with concatenation, faster)
%%(php)$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
**{{color c="red" text="not recommended:"}}** (single spaces clutter the code and make layout incoherences easier)
%%(php)
if ($x > 0)
{
echo $x;
}%%
**{{color c="green" text="recommended:"}}** (tabs are a consistent and economical solution for indenting code)
%%(php)
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.
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
$i=0;
$str='a'.'b'.'c';
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal space between tokens increases readability)
%%(php)
$i = 0;
$str = 'a'.'b'.'c';
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
if($i<7)
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal space between tokens increases readability)
%%(php)
if ($i < 7)
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
if ( ($i < 7)&&($j > 8) )
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal space between tokens increases readability)
%%(php)
if ($i < 7 && $j > 8)
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
myFunction( $i, $str, $b );
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal whitespace between tokens increases readability)
%%(php)
myFunction($i, $str, $b);
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
for($i=0; $i<$size; $i++)
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal whitespace between tokens increases readability)
%%(php)
for ($i = 0; $i < $size; $i++)
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
$i=($j < $size)?0:1;
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal whitespace between tokens increases readability)
%%(php)
$i = ($j < $size) ? 0 : 1;
%%
==Vertical whitespace==
(stub)
~-use blank lines to separate "blocks" of code that together "form a thought"
==Trailing whitespace==
(stub)
~-remove whitespace from the ends of lines (most editors can do this automatically - see below)
===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##.
~-use any of the following type casting forms:
~~-(int), (integer) - cast to integer; preferred form (int)
~~-(bool), (boolean) - cast to boolean; preferred form (bool)
~~-(float), (double), (real) - cast to float; preferred form (float)
~~-(string) - cast to string
~~-(array) - cast to array
~~-(object) - cast to object
~-do not use any white space within the typecast operator, and do separate it with a single space before the variable or expression being cast
**{{color c="red" text="not recommended:"}}** (incorrect use of type casting decreases readability)
%%(php)
if (3 > intval($this->GetConfigValue('some_setting')))
{
$setting = (bool)$settingpar;
$param = array($param);
}
%%
**{{color c="green" text="recommended:"}}** (correct use of type casting increases readability)
%%(php)
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.
**{{color c="green" text="recommended:"}}**
%%(php)
/* ****************************************************
*
* 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";
%%
**{{color c="red" text="not recommended:"}}**
%%(php)
/* 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:
~-if you're building a complete SQL query, use $sql or $query
~-if you're building (content for) a particular SQL //clause//, don't name that $sql, but name it after the clause it's intended for: $where, $values or $valuelist, $sort
~-to refer to an array that contains a complete page record, use $page; to refer to the name only, do **not** use $page, but instead $tag or $pagename
~-similarly, to refer to an array that contains a complete user record, use $user; to refer to the name only, use $username (or a variant like $reg_username or $anon_username that clearly indicates it's a //name//, not a whole record).
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:
~-Clearly document what you changed, and why
~-Follow the coding conventions of the package itself, //even if they do not correspond to Wikka coding guidelines//: you don't want to re-code the whole thing, and code with a mix of conventions used is hard to read.
====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 your editor to use a tab width of 4 spaces - this is for readability.
~-Most editors provide a function to convert leading spaces to tabs; make sure you have //first// set your editor tab width
~-Most editors can be configured to use tabs (vs. spaces) for indenting; many will have an "auto-indent" feature which is useful but since these often "echo" whatever whitespace is at the start of the preceding line, it's helpful to start with converting leading spaces (if any) in the code you are working on.
~& Suggested settings for vim:
%%
:set ai (Auto indent)
:set noet (Don't change tabs into spaces "on the fly")
:set ts=4 (4 spaces per tab)
%%
~& Use the following global search/replace sequence to replace groups of four spaces with tabs (to get the ^I character, do a CTRL-V followed by a Tab):
%%
:%s/ /^I/g
%%
===Trailing whitespace===
~-Most editors have a setting to remove whitespace from the ends of lines automatically when saving a file; if not, they generally provide a function to do this for a whole file (use this before saving).
===Line endings===
(stub)
----
CategoryHowto
CategoryDevelopment
----
=====Wikka Coding Guidelines=====
>>==See also:==
~-[[DocumentingCodeHowto | Code Documentation Tutorial]]
>>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,
~- a red caption **{{color c="red" text="not recommended"}}** indicates code violating the present guidelines;
~- a green caption **{{color c="green" text="recommended"}}** indicates code complying with the present guidelines.
<<==Table of contents==""<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Code_structure">Code structure</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_include_and_require"><tt>include</tt> and <tt>require</tt></a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Conditions_and_loops">Conditions and loops</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Naming_conventions">Naming conventions</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Class_and_object_names">Class and object names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Method_and_function_names">Method and function names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Variable_names">Variable names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Constant_names">Constant names</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Loop_indices">Loop indices</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Code_layout">Code layout</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Braces">Braces</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Single_vs._double_quotes">Single vs. double quotes</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Whitespace">Whitespace</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Type_casting">Type casting</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Wikka-specific_guidelines">Wikka-specific guidelines</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Code_structure_1">Code structure</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Using_core_methods">Using core methods</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Actions_vs._handlers">Actions vs. handlers</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Action_parameters">Action parameters</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_File_naming_conventions">File naming conventions</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Variables_and_parameters">Variables and parameters</a></li>
</ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Third-party_code">Third-party code</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Editor_settings">Editor settings</a></li>
<ul>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Tabs_vs._spaces">Tabs vs. spaces</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Trailing_whitespace_2">Trailing whitespace</a></li>
<li><a href="http://wikkawiki.org/CodingGuidelinesHowto#hn_Line_endings">Line endings</a></li>
</ul>
</ul>""<<::c::
====Code structure====
(stub)
===##include## and ##require##===
~-**How to choose the correct one** ---
~As we can read in the PHP docs about [[PHP:include | 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. ---
~-**Format** ---
~##include## and ##require## are **//statements//**, not functions. The parentheses (as in the little quote above) are optional in PHP. (According to the [[PHP:include | 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. ---
~-**Conditional includes** ---
~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. ---
~-**Including once or more?** ---
~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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if (($fh = fopen($rssFile,'w')) === FALSE)
{
die('Failed to open file for writing!');
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
$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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ($page["tag"] != $tag) return false;
else return true;
%%
**{{color c="green" text="recommended:"}}**
%%(php)
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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ( 8 == $i || 10 == $i && 12 == $j )
{
...
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
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
%%(php)
if (FALSE === ($fh = fopen($rssFile,'w')))
{
...
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
$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.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ($inputNubmer == 12)
{
...
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
if (12 == $inputNumber)
{
...
}
%%
== Use switch structures rather than nested if-then-else ==
Switch structures enhances readability in your code.
**{{color c="red" text="not recommended:"}}**
%%(php)
if ($i == 0)
{
echo "i equals 0";
} elseif ($i == 1) {
echo "i equals 1";
} elseif ($i == 2) {
echo "i equals 2";
}
%%
**{{color c="green" text="recommended:"}}**
%%(php)
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:
~-class and object names start with a **capital**
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:
~-method and function names start with a **lowercase character**
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:
~-method and function names should be descriptive, and use camelCaseWords to separate words
~-methods/functions returning a boolean (TRUE or FALSE) should have a name that naturally suggests this, such as isRegistered or existsPage
// 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.
**{{color c="red" text="not recommended:"}}** (mixed case is not recommended for variables)
%%(php)$CurrentUser = $this->getUserName();%%
**{{color c="red" text="not recommended:"}}** (words without separators make variable names hardly readable)
%%(php)$currentuser = $this->getUserName();%%
**{{color c="green" text="recommended:"}}** (lowercase variables using underscore as word separators are readable and distinctive)
%%(php)$current_user = $this->getUserName();%%
~& A_lot_of_under_scores_are_hard_to_read - we should also allow camelCased variable names as long as the name begins with a lower-case letter
~& RubenOlsen
===Constant names===
Constants should follow the same conventions as variables, except use all UPPERCASE to distinguish them from variables.
**{{color c="red" text="not recommended:"}}** (lowercase is for variables)
%%(php)
define('default_width', 500);
$window_width = default_width;
%%
**{{color c="red" text="not recommended:"}}** (words without separators make constant names hardly readable)
%%(php)
define('DEFAULTWIDTH', 500);
$window_width = DEFAULTWIDTH;
%%
**{{color c="green" text="recommended:"}}** (uppercase constants using underscore as separators are readable and distinctive)
%%(php)
define('DEFAULT_WIDTH', 500);
$window_width = DEFAULT_WIDTH;
%%
~& While these general guidelines for naming constants are (mostly) fine, in working on the language file (to enable localization of Wikka) I found the ones presented are actually far too vague for specific usage. Constants have many uses, and different uses actually warrant their own guidelines. Naming constants to be used for regular expression building is quite a different proposition from naming constants for defining default values for parameters, or for text strings for a language file to be used by translators for localizing Wikka. So, I'm going to start a few subpages for developing guidelines for naming different **groups** of constants. I'm putting this comment here, on purpose, because what follows about names for text constants will (ultimately) be largely replaced by one or more specific subpages. So, for now, I think we'll need these (and possibly more) pages:
~~-CodingGuidelinesTextConstants - for (to be localized) text appearing in in the Wikka userinterface
~~-""CodingGuidelinesRegexConstants"" - for a collection of Regular Expressions and RE "building blocks"
~~-""CodingGuidelinesDefaultConstants"" - for defining default values for action, handler, or form default values
~&-- JavaWoman
== Names for text constants ==
Constants containing text - strings should be named accordingly to the function the text has:
**{{color c="green" text="recommended:"}}** (ERROR_ for error-messages, i.e. when wikka does not behave like the user expects)
%%(php)
define('ERROR_CIRCULAR_REFERENCE_DETECTED', 'Circular reference detected');
// here goes some code...
} else print '<span class="error">'.ERROR_CIRCULAR_REFERENCE_DETECTED.'</span>';
%%
**{{color c="green" text="recommended:"}}** (BUTTON_ for buttons - //or better BUTTON_LABEL?//)
%%(php)
define('BUTTON_CHANGE', "Change");
// here goes some code...
<td><input type="submit" value="<?php echo BUTTON_CHANGE ?>" size="40" /></td>
%%
**{{color c="green" text="recommended:"}}** (IMG_ALT_ for the alternative text provided with images)
%%(php)
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.'" />';
%%
**{{color c="green" text="recommended:"}}** (used variable substitutes should be explained in a comment afterwards)
%%(php)
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
%%
~& The following is missing:
~~& what prefix for link texts ("title" and <a>the text between</a>)
~~& where to put the constants and how to name the section
===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'.
**{{color c="red" text="not recommended:"}}** (long names for loop indices are less readable and are easily confused with real variables)
%%(php)for ($squares = 0; $squares < $shapes; $squares++)
{
for ($triangles = 0; $triangles < $shapes; $triangles++)
{
foo($squares, $triangles);
}
}%%
**{{color c="green" text="recommended:"}}** (one-character loop indices are distinctive and readable)
%%(php)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.
**{{color c="red" text="not recommended:"}}** (Code more difficult to maintain, bugs hard to track down)
%%(php)
if (condition) foo();
if (condition)
foo();
while (condition)
foo();
for ($i = 0; $i < 10; $i++)
foo($i);
%%
**{{color c="green" text="recommended:"}}** (Easier to maintain, reduced risk of bugs)
%%(php)
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.
**{{color c="red" text="not recommended:"}}** (reduced readability)
%%(php)
if (condition) {
while (condition2) {
//...
}
} else {
//...
}
%%
**{{color c="green" text="recommended:"}}** (improved readability)
%%(php)
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.
**{{color c="red" text="not recommended:"}}** (A lot of escaping makes the code hardly readable)
%%(php)$w3_logo = "<img alt=\"The World Wide Web Consortium (W3C)\" height=\"48\" width=\"315\" src=\"/Icons/w3c_main\" />";%%
~& We should have a better example as single quotes are allowed i HTML, thue reducing the need for escaping anything.
~& RubenOlsen
**{{color c="green" text="recommended:"}}** (Code is much more readable)
%%(php)$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.
**{{color c="red" text="not recommended:"}}** (Slower parsing)
%%(php)$str = "Avoid this - it just makes more work for the parser.";%%
**{{color c="green" text="recommended:"}}** (Faster parsing)
%%(php)$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:
**{{color c="red" text="not recommended:"}}** (What happens if 'example' is defined as a constant elsewhere?)
%%(php)$str= $my_array[example];%%
**{{color c="red" text="not recommended:"}}** (Slower parsing)
%%(php)$str= $my_array["example"];%%
**{{color c="green" text="recommended:"}}** (No ambiguity as to the name of the key and processing is faster than using double quotes )
%%(php)$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:
**{{color c="red" text="not recommended:"}}** (Slower parsing)
%%(php)theFunction("$var");
$str = $my_array["$example"];%%
**{{color c="green" text="recommended:"}}** (Faster parsing)
%%(php)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
**{{color c="red" text="not recommended:"}}** (The parser will not interpolate the variable embedded in the string)
%%(php)$str = 'My name is $user';%%
**{{color c="red" text="not recommended:"}}** (The "\n" will be literally displayed as such)
%%(php)echo 'This is a sentence followed by a newline\n';%%
**{{color c="green" text="recommended:"}}** (The parser will correctly replace the variable embedded in the string)
%%(php)$str = "My name is $user";%%
**{{color c="green" text="recommended:"}}** (The textual string will be displayed followed by a newline)
%%(php)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:
**{{color c="red" text="not recommended:"}}** (Correct use of double quotes with interpolation, but slower parsing!)
%%(php)$str = "My name is $user";%%
**{{color c="green" text="recommended:"}}** (Correct use of single strings with concatenation, faster)
%%(php)$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
**{{color c="red" text="not recommended:"}}** (single spaces clutter the code and make layout incoherences easier)
%%(php)
if ($x > 0)
{
echo $x;
}%%
**{{color c="green" text="recommended:"}}** (tabs are a consistent and economical solution for indenting code)
%%(php)
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.
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
$i=0;
$str='a'.'b'.'c';
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal space between tokens increases readability)
%%(php)
$i = 0;
$str = 'a'.'b'.'c';
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
if($i<7)
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal space between tokens increases readability)
%%(php)
if ($i < 7)
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
if ( ($i < 7)&&($j > 8) )
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal space between tokens increases readability)
%%(php)
if ($i < 7 && $j > 8)
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
myFunction( $i, $str, $b );
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal whitespace between tokens increases readability)
%%(php)
myFunction($i, $str, $b);
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
for($i=0; $i<$size; $i++)
{
}
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal whitespace between tokens increases readability)
%%(php)
for ($i = 0; $i < $size; $i++)
{
}
%%
**{{color c="red" text="not recommended:"}}** (incorrect use of horizontal whitespace between tokens decreases readability)
%%(php)
$i=($j < $size)?0:1;
%%
**{{color c="green" text="recommended:"}}** (correct use of horizontal whitespace between tokens increases readability)
%%(php)
$i = ($j < $size) ? 0 : 1;
%%
==Vertical whitespace==
(stub)
~-use blank lines to separate "blocks" of code that together "form a thought"
==Trailing whitespace==
(stub)
~-remove whitespace from the ends of lines (most editors can do this automatically - see below)
===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##.
~-use any of the following type casting forms:
~~-(int), (integer) - cast to integer; preferred form (int)
~~-(bool), (boolean) - cast to boolean; preferred form (bool)
~~-(float), (double), (real) - cast to float; preferred form (float)
~~-(string) - cast to string
~~-(array) - cast to array
~~-(object) - cast to object
~-do not use any white space within the typecast operator, and do separate it with a single space before the variable or expression being cast
**{{color c="red" text="not recommended:"}}** (incorrect use of type casting decreases readability)
%%(php)
if (3 > intval($this->GetConfigValue('some_setting')))
{
$setting = (bool)$settingpar;
$param = array($param);
}
%%
**{{color c="green" text="recommended:"}}** (correct use of type casting increases readability)
%%(php)
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.
**{{color c="green" text="recommended:"}}**
%%(php)
/* ****************************************************
*
* 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";
%%
**{{color c="red" text="not recommended:"}}**
%%(php)
/* 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:
~-if you're building a complete SQL query, use $sql or $query
~-if you're building (content for) a particular SQL //clause//, don't name that $sql, but name it after the clause it's intended for: $where, $values or $valuelist, $sort
~-to refer to an array that contains a complete page record, use $page; to refer to the name only, do **not** use $page, but instead $tag or $pagename
~-similarly, to refer to an array that contains a complete user record, use $user; to refer to the name only, use $username (or a variant like $reg_username or $anon_username that clearly indicates it's a //name//, not a whole record).
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:
~-Clearly document what you changed, and why
~-Follow the coding conventions of the package itself, //even if they do not correspond to Wikka coding guidelines//: you don't want to re-code the whole thing, and code with a mix of conventions used is hard to read.
====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 your editor to use a tab width of 4 spaces - this is for readability.
~-Most editors provide a function to convert leading spaces to tabs; make sure you have //first// set your editor tab width
~-Most editors can be configured to use tabs (vs. spaces) for indenting; many will have an "auto-indent" feature which is useful but since these often "echo" whatever whitespace is at the start of the preceding line, it's helpful to start with converting leading spaces (if any) in the code you are working on.
~& Suggested settings for vim:
%%
:set ai (Auto indent)
:set noet (Don't change tabs into spaces "on the fly")
:set ts=4 (4 spaces per tab)
%%
~& Use the following global search/replace sequence to replace groups of four spaces with tabs (to get the ^I character, do a CTRL-V followed by a Tab):
%%
:%s/ /^I/g
%%
===Trailing whitespace===
~-Most editors have a setting to remove whitespace from the ends of lines automatically when saving a file; if not, they generally provide a function to do this for a whole file (use this before saving).
===Line endings===
(stub)
----
CategoryHowto
CategoryDevelopment