BuBOL Coding Standards

This coding standard was originally insipred by the phpBB coding standard. A full copy of their standard can be found in their source download http://www.phpbb.com/ but we won't be following it exactly, I'd just like to point out my inspiration for this one :-)

The purpose of this standard is to keep the BuBOL code clean, consistent, readable, and hopefully more maintainable. Please note, I didn't write this for my own health. Follow it or watch your code get handed back to you for clean-up and reformatting ;-) I'll admit, I had to bend a lot of my own personal coding style to match what I thought was a better way of writing code after much research and trial & error.

Also, while I'd like to have this standard written in stone, forever unchanging and always right, that's obviously impossible :-) So consider this a living document that can change at anytime. Changes to this standard will be communicated as best as they can to all active/registered developers.

Have any questions, suggestions or comments? Just let russ know.

Editor Settings

Recommended Editors: Eclipse 2.1 or higher (http://www.eclipse.org) with the Xored WebStudio plugin (http://www.xored.com) makes for a very powerful and flexible editor and IDE. See the Development FAQ for more details.

Tabs vs. Spaces: Please use spaces only, 4 spaces per tab/indent. This makes the viewing consistent. Use an editor that can replace a tab with spaces.

Linefeeds: For now, let's just stick with Win32 editors (e.g. Notepad) that use a CR/LF combo. Down the road maybe we'll switch to Unix format, but right now, it's not that important. Either way, it'd be really super swell if you used an editor or tool that could switch between the two if and when we do switch (something like Metapad: http://liquidninja.com/metapad/) or dos2unix.

Whitespace: As mentioned earlier, tabs should be spaces. Basically any white space should always be a space (except in the case of "tabs" above). There should also not be any white space at the end of a line. Similarly, lines that consist of nothing but new lines should not have any spaces either, e.g. if a line is blank, it should be just that... blank!

 

Naming Conventions

Naming style: Use camelCase for all variable and function names, but NOT Hungarian notation, an example of this is: good: $memberName bad: $strMemberName. The first letter of each "word" should be upper case, except for the first word. The exception to this is class names (e.g. class ThreadPost).

Variable Names: camelCase, see above. Make them descriptive, but short and sweet. (no $c = $a + $b crapola, but no $currentMemberOfThisScriptFunction either). Try to use your best judgement.

Loop Indices: This is the only time when you can use a one-character variable name, unless there's another variable already in use with a useful name. Start outer loops with $i, then just go down the alphabet ($j, $k, $l, etc)

Function Names: Same as variable names, but try to put a verb in them somewhere.

Function Arguments: Same as variable names. You should be able to tell how to use a function just by looking at the declaration.

Example URLs: All example, sample, and/or default URLs should be "example.com". See RFC 2606 for more information.

Class Namespacing: Since the PHP language doesn't provide any formal way of separating classes into different namespaces/packages, this will be enforced by class naming. All BuBOL classes should begin their class name and declaration with BuBOL_, e.g.:

class BuBOL_Forum

Where it makes sense to further organize a class into a 'sub-package', on the filesystem level the class must exist in a directory structure matching its package structure, and the package levels must be in the class name/declaration. For example:

class BuBOL_PLI_DBI_Mysql

Would exist in the directory: <BUBOL_ROOT>/PLI/DBI

Class filenames: Similarly to the class namespacing conventions mentioned above, the file names should be in all lowercase, start with class_, and be followed with the package/namespace structure, in all lower case, with sub-packages separated by dots. All class files must also end in .php. Using the BuBOL_PLI_DB_Mysql class from above as an example, the file name for this class would be: class_bubol.pli.db.mysql.php

 

Comments

All comments for classes follow the standard Javadoc rules used for Java comments. A good reference to take a look at is: http://java.sun.com/j2se/javadoc/writingdoccomments/

Comments: Aside from standard file, class, property, and method headers, you should only need to put comments around areas of code that are particularly ugly, or particularly clever. You don't need to comment every line of code, but try to use your best judgement, and remember it's better to comment sooner rather then later, after you've forgotten where something is or what it does.

Types of comment blocks: Personally I prefer the Javadoc style:

/**
 * Some comment
 */

but C style comments /* */ and standard C++ comments // are both fine as well. The Perl style comments # is strongly discouraged.

Standard file header: As of this writing, here's our standard header which should appear at the top of every single .php or .inc file. The website listed for the powered by information is just temporary until we get xbb.org/.net/.com setup =].

Be sure to update the began date to the date you started working on the file. Also, remove the spaces at the beginning and end of RCSfile and Id. These are RCS keyword substitution tags that will show the file name and some info about its version in the repository. They had to be space padded here so they wouldn't get substituted in this example ;-)

/**
 *
 * file      : $ RCSfile $
 *
 * began     : October 25, 2002
 * copyright : (c) 2002, 2003, 2004, 2005 Russ Collier
 * support   : bubol@grayshirt.com
 *
 * $ Id $
 *
 */

/**
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Or visit http://www.gnu.org/copyleft/gpl.html
 *
 */

Standard class header: All classes should start with this header, again be sure to remove the space padding around Revision. If you are working on a class that already has this header, be sure to add a new @author tag with your name on a new line directly below the last existing @author tag. The @see tag is optional if the class is related to another existing class that you feel the documentation should refer to, if not needed, then leave the entire @see line out.

/**
 * @brief A short 1 or 2 sentence description of the class and what it does.
 *
 * @author  Your name
 * @version $ Revision $
 * @see     SomeClass
 */

Standard property header: All class properties (data members) should have this comment header on the line directly above them:

/**
 * Type - Very brief description
 */

Standard method header: All class methods (functions) should have this comment header on the line directly above them. Remove unnecessary tags completely (@param, @return, @see, @static), and add more as necessary. Add extra @author tags to methods if you have added or modified them.:

/**
 * Brief 1 or 2 sentence description of the method and what it does.
 * Brief description of restrictions on input parameters.
 * Mention if and how Exceptions are set.
 *
 * @static
 * @param  $parameter_name ParameterType - Description of parameter
 * @return ReturnType - brief description of possible return values and their meanings.
 * @author Your name
 * @see    similarMethod()
 * @throws SomeException - On some condition
 */

Code Layout

Number of columns: The 80 column limit isn't a huge deal these days, but don't abuse the line length in your source code. Personally I feel 120 is a very lenient maximum length. The 80 column limit won't be strictly enforced, but try to use it as a guideline. If you have a line of over 120 characters long, maybe you should think about what you're trying to do and see if there's a more readable way to code it. Cleverness in coding is appreciated, but readability and maintainability are higher priorities.

Always include the braces: Helps with code readability. Examples:

bad:
if($something)
    do_this();

good:
if ( $something )
{

    do_this();

}


good:
switch ( $someCondition )
{

    case 0:

        do_this();
        break;

    default:

        do_that();

}

Where to put braces: Make sure the open brace is on it's own line. And make sure the closing brace is in the same column as the corresponding opening brace, again on its own line. Make sure a blank new line separates the brace and whatever is above or below the brace - except for opening braces, then it's only a blank new line below. This increases file length but really helps with readability.

Use spaces between tokens: Helps with code readability. Put spaces between variables and operators, after commas, between element indices and square brackets in arrays, and after an opening bracket or before a closing bracket. No spaces before a comma or semicolon though. Unless it's a function call, there should be a space between the keyword/statement and the opening bracket.

Operator precedence: Never assume, always make it obvious by using brackets to force the precedence of an equation so you know the order by looking at it.
Bad: $x + $y - $z / $w * $v
Good: $x + ( ( $y - $z ) / ( $w * $v ) )

SQL code layout: Break statements onto their own lines. Follow this example for the capitalization, use of brackets, etc.:

SELECT field_1 AS whatever, field_2, field_3
FROM table_a, table_b
WHERE (work = play) AND (russ = bored)

SQL insert statement: Always explicitly list the columns for the insert. When you assume you make an ass of you and me.

One PHP class per file! Should be self-explanatory :-)

 

General

PHP Predefined Globals: Always use the superglobals: $_SERVER, $_POST, $_GET, $_COOKIE, $_SESSION, etc.

PHP tags: To ensure some degree of backwards compatibility, XML support, and consistency, all php script tags should be in the form of <?php ...  ?>, and preferably on their own lines with 1 empty newline immediately after <?php and 1 empty newline immediately before ?> unless it's a concise 1 liner in the midst of HTML (e.g. <?php print $currentTime; ?>)

Quoting strings: If you have variables in your string or escape sequences (e.g. \n, \"), use double quotes. If not, then use single quotes. This saves unnecessary interpolation parsing (although apparently, concatenation is faster than interpolation in the first place :-)).

Associative array keys: Use single quotes around the key to help with readability, with a single space between the quoted key and the square brackets. Bad: $bluh = $my_array[narf]; Good: $bluh = $my_array[ 'narf' ]; And always concatenate arrays in strings, never embed an array element in a string.

Bad:

$foo = "Here is a string with an array element: $someArray[ 'bar' ]\n";

Good:

$foo = "Here is a string with an array element: " . $someArray[ 'bar' ] . "\n";

Besides, I think the first example with throw a syntax error anyway (at least in PHP 4.x)

Magic numbers: Just don't use them. When in doubt, make it a constant. Probably the only time it's okay to use a literal number instead of a constant is when checking if an array has 0 elements. Preferably make things static class constants

Class constants: Use the const class property keyword, named in all upper case, that's set to the default (constant!) value you need. Example:

class Foo
{

    const DEFAULT_MEMBER_ID = 1;

}

// ....

print "Default member id is: " . Foo::DEFAULT_MEMBER_ID;

Increment/Decrement operators: The only time they shouldn't be on their own line is in a loop statement. Otherwise always put them on their own line to help keep code readable/easily understoond. Example:

bad:
$array[ $i++ ] = $bluh;

good:
$i++;
$array[ $i ] = $bluh;

Don't use uninitialized variables: if you're not sure, use the built-in isset() function to test if the variable has been set yet. If you're writing a function and can make valid assumptions, try to use default parameters.

Built-in values: For boolean operations use the words true and false instead of 1 and 0. As usual this helps keep the code concise and readable. Also, use the word null for uninitialized objects. All of these should be lower case, always.

Built-in functions: Whenever you call a built-in PHP function and/or statement, always make sure it is in lower-case, even if PHP allows otherwise.

User input: to quote someone's Slashdot comment I read once, treat all user input as if it was from Satan himself. Validate existence, validate type, validate range, and validate content. Do not trust the user!

Code with error_reporting( E_ALL ): There should never be any warnings or notices when the code runs, if there is, it could indicate some variables aren't being properly sanitized.


Hosting provided by: SourceForge.net Logo
$Id: codingstandards.html,v 1.3 2005/01/03 05:22:07 russ Exp $