Developer Coding Guidelines


@author andrej arn <andrej at blueshoes>
@author sam blume <sam at blueshoes>
@version 4.6 updated 2005-11-24

we'd like to have a clean and professional, bug-free code. 
Most people have different coding styles. And most think that 
"the other style" is ugly. We don't want to force you changing 
your style. Here is how we do it and like it:

o) We use capital letters for constants. e.g. define('CONSTANT', 1). 
   We also use the capital form of  TRUE, FALSE and NULL. 
   This is true for PHP, note that javascript needs lowercase.
o) If a function is described to return bool, expect to get a real bool 
   (TRUE/FALSE) and not an int (0/1). So please code your functions and 
   methods that way. 
o) Don't trust the return values from php methods. If they are stated 
   to return bool, they often return an int (0/1). So don't directly 
   return that from your functions, convert to (bool) if necessary.

o) Never ever use echo, print and die and the like inside your methods. 
   Use return.
o) this applies also for white spaces. if you start your file with anything 
   (an empty line) before the <?php tag, it will be sent to the client and 
   considered as output. This makes header() calls impossible (cookie, 
   session). The same applies for white spaces after the ?> tag. take care! 
   Even a newline is too much. This is a typical php newbie mistake.
o) Everything should be as os independant as possible. Including windows.

o) Make your code work with PHP version 4.3.0+ and 5.0.5+.
   Don't support php3.

o) Make the php exam. Repeat it from time to time.

o) Code object oriented. (PHP4)

o) Avoid setting vars in the global scope. If you need one, prefix it. 
   Example: $GLOBALS['_Bs_MyClass_MyVar'] = 'foo';

o) Avoid using things from global scope inside methods. Instead 'include' 
   them in the constructor. 

o) Prefix classes with Bs_. This is a poor man's namespace.

o) Name your files like the classes: a class named 'Bs_Something' will 
   have the file name 'Bs_Something.class.php'.
o) One class per file.

o) References:
   Don't return temporaries by reference. 
   function &foo() {
     return new StdClass(); //this is wrong
     return $ret = new StdClass(); //this is wrong too
     //this is wrong too. (it works at least in php 4.4.1, 
     //but who knows, it's inconsistent, so please don't use it.)
     return $ret =& new StdClass(); 
     $ret =& new StdClass(); return $ret; //this is right
     return FALSE; //this is wrong
     return $ret = FALSE; //this is wrong
     $ret = FALSE; return $ret; //this is right
     $classOne =& new StdClass();
     $classTwo =& new StdClass();
     return (true) ? $classOne : $classTwo; //this is wrong
   $object =& foo();
   Don't pass temporaries by reference:
   function foo(&$param) {}
   foo(TRUE); //this is wrong
   $param = TRUE; foo($param); //this is wrong
   //this is wrong. (it works, but who knows, it's inconsistent, 
   //so please don't use it.)
   foo(new StdClass);
   $param =& new StdClass(); foo($param); //this is right
   Also take care when encapsulating functions:
   function foo() { return new StdClass(); }
   function bar(&$param) {}
   bar(foo()); //this is wrong
   $object = foo(); bar($object); //this is right
   When you create a new instance of a class, *always* do it by reference:
   $object =& new SomeClass();
            ^---->this one
   This is *important*, *important*, *important*!!. Trust me. if you don't, 
   you will after having strange bugs in your code and not finding them 
   for hours.
   Also read http://www.zend.com/manual/language.oop.newref.php please.
o) Please use the same coding style as it is already used, if you can. 
   I know that changing your coding style is not easy if you're used to 
   old: - a tab is 2 spaces
   new: - a tab is a tab, we set it to the width of 2, but feel free to 
          configure your editor to show it as 3, 4, 8, whatever.
   - A function is written like:
     function something(param, param) {
       //some code
   - An if statement is written like:
     if ($this == $that) {
     } elseif ($this > $that) {
     } else {
   - Use spaces to separate: 
     $x .= $y . 'hello';   instead of   $x.=$y.'hello';
     exceptions are (for readability):
     - $array = array('key'=>'value', 'key2'=>'value2');
     - for ($i=1; $i<=10; $i++) {
     - function myFunction($a='default', $b='foobar') {
o) Naming conventions:
   - PHP itself is *very* inconsistent about the naming: 
     isset() but is_string() => underscore or not, 
     strtolower but bin2hex => to or 2, 
     create_function but str_shuffle => verb object, object verb, 
     strpos(haystack, needle) but in_array(needle, haystack) => order of param
     so let's do it better.
   - Use studly caps (first letter of each word capitalized (but not the 
      first one), otherwise lower case, no underscores) for vars, functions 
     (methods), lists, anything that needs a unique name.
     class names go like 'Bs_SomeClass'.
     vars/functions/objects/db-names are started lowercase, class 
     names/db-table names are started uppercase:
     $someVarName         instead of   $some_var_name
     someFunctionName()   instead of   some_function_name()
     SomeObject           instead of   some_object
     this especially also applies for short forms:
     $someDbTable         instead of   $someDBTable
     $someHtmlString      instead of   $someHTMLString
     It is easier to read, and you can be sure how it was written. We think 
     it's better from experience. (An exception is the table field name/term 
     ID because of a naming convention.)
     Often it is hard to decide if a word is made up of multiple words. 
     These words are considered being one word, not two, and thus have 
     no capital:
     - username  (not userName)
     - password  (not passWord)
     - blueshoes (not blueShoes)
     These words are considered being two words and thus have a capital:
     - fileName (not filename)
     - passPhraze (not passphraze)
     - dateTime  (not datetime)
     A few other writings:
     - email    (not eMail or so, because someEmail will work while 
                 someeMail or someEmail or someEMail would break the rules.)
     Please avoid something like '$conn1' ('$conn2', '$conn3' ...) because 
     you cannot see if it was $conn1 or $connl. See what i mean? (one or 
     a small L, depending on the font)
   - Don't use the fancy way pdf2html. It's kinda breaking the studly 
      caps rule. it would be pdf2Html and then it's not that readable 
     anymore because both '2' and 'H' are "upper case". So always use 

   - Use verb object, not object verb. So makeObject(), not objectMake().
   - If in doubt, use java syntax/style.
o) Learn the difference between == and === and != and !==. Read the manual 
   and check http://www.blueshoes.org/en/developer/php_cheat_sheet/

o) Passing by reference: Our code needs to be compatible with PHP 4 and 5. 
   PHP5 passes all objects by reference while PHP4 passes them by copy. 
   To make both versions behave the same way, do the following:
   To pass by reference (99% of all cases):
     function foo(&$theObject, $theInteger) {
     foo($someObject, 5);
   To pass by value (1% of all cases):
     function foo($theObject, $theInteger) {
     $copyOfObject = bs_clone($someObject);
     foo($copyOfObject, 5);

o) Private vars and methods start with an underscore. 
   _foo is a private var, foo is a public var, _foo() is a private method 
   and foo() a public one.

o) In your classes, define all your public and private class vars using
   var $something; or var $_something;
   even if you don't set a default value. It will help maintaining the code.
o) Document while you code. Please document (phpdoc, like javadoc) your 
   functions, classes, methods, even class vars. I know that coders are 
   always in a hurry. But it will save a lot of time in the end! 
   It looks like this:
   * What the function does in one line.
   * Here goes some more detailed description on 0-n lines, if needed.
   * @access  [public|static|pseudostatic]
   * @param   [string|int|double|bool|array|object|mixed] $paramName desc
   * @return  datatype  description
   * @throws  [bs_exception|bool FALSE|NULL...]
   * @see     someFunction(), var someVar
   * @todo    description
   * @since   bs4.1, php4.3             (comma separated list)
   * @status  stable|experimental       (if not set then considered stable)
   * @pattern singleton|factory|mvc|observer|facade|...
   function something() {
   For variables the @var keyword is used instead of @param:
   * Some internally used var.
   * @access private
   * @var    bool $someStatus
   * @see    setSomeStatus()
   var $_someStatus = FALSE;
   The description may include HTML, but please avoid it on the first line.
   #@pattern singleton means that the constructor returns a reference 
   #to an already existing instance, if there is one.
o) Write ecg classes for your code. They will serve other coders 
   as examples and make the code more safe. Especially when it is 
   installed on other os'es, when new php/apache/mysql/... versions come 
   out etc. See naming for a definition of ecg.
   The classes are in subfolders named 'ecg', for an example have a look 
   at core/util/ecg/Bs_String_PhpUnit.class.php
o) Don't eat junk food and never drink Red Bull at night. Pizza is ok. :)

o) Don't use underscores _ in databases (table names, field names). 
   They are reserved for relations (foreign key by naming convention).
   Don't use the numbers 2, 3 and 4 inside of db table names. They are 
   reserved for the same reason.

o) Associative arrays are called 'hash', zero-based arrays are called 
   'vector'. Please use these terms. Undefined arrays are called 'array'.

o) Use the term 'function' for 'structured' procedural code. Use the term 
   'method' for functions inside classes. Don't use the terms 'procedures', 
   'subs', 'routines' etc. 
   sam: "methods are verbs, classes are substantives." :-)

o) When you return inside a switch or something, write the break too. 
   switch ($x) {
     case 'hello':
       return TRUE;
   This way it will be harder for someone to 'implement' bugs into your code.

o) Avoid buggy code. For example if you're not 100% sure that a var is 
   an array, do is_array(), sizeOf($array) and such.
o) To be PHP4 compatible instead of using try-catch use the do-while(FALSE) 
   try-catch code, something like:
     do { // try block
       $isOk = someFunction();
       if (!$isOk) break;
       $isOk = otherFunction();
       if (!$isOk) break;
       $isOk = TRUE; //everything worked
     } while (FALSE);
     if ($isOk) echo 'yeah';

o) Form your var declaration blocks etc in a nice way: (note the extra 
   $a        = 'hello';
   $bbbb     = 'world';
   $cccccccc = 'foobar';
o) Mostly use foreach instead of while-list to loop arrays. See sam's 
   php-bench: http://www.blueshoes.org/en/developer/php_bench/
   Note: there are also, and i like them (andrej)
   while (list($k,) = each($a)) {
   while (list(,$v) = each($a)) {

o) Magic_quotes_gpc was a good idea to prevent sql injection. 
   Unfortunately this feature can be turned on or off, was on in 
   previous PHP releases and is turned off by default now. This makes 
   the situation for libraries and released software a lot harder 
   which has to work with different configurations.
   Check your php.ini, look for "magic_quotes_gpc". It 
   should be set to Off, not On. (magic_quotes_gpc = Off)
   BlueShoes fixes this by checking magic_quotes_gpc, and if it is on, 
   it goes and undo'es the changes in _REQUEST, _GET, _POST and _COOKIE 
   see bs_undoMagicQuotes(). 
   Note that there is other software around that does the opposite.

o) Make sure your code runs error free even if warnings and notices are 

o) Use the new superglobals (_GET, _POST etc), make sure your code works 
   if register_globals turned off. And we highly recommend to set 
   register_globals to off.

o) JavaScript classes are named like in php, for example 
   "Bs_FormFieldSelect.class.js". If it's a lib then it goes like 
   Bs_FormFieldSelect.lib.js. A lib is simply a collection of functions 
   for a special task, so not oo-code.

o) If you change something in code someone else maintains (and/or you're 
   not in the @author of the class or the function) then add your comments 
   along with the date and your name, example:
   someCode(); //i did this because of that. 2002/10/16 --yourname

o) Don't add email addresses in plain text. Even the phpdoc comments in 
   the code get indexed, and thus could be spidered by email crawlers. 
   Please use "<user at domain dot com>" which makes it a bit harder to parse.

o) Naming (Glossary)

   ecg          ElectroCardioGram
                In the code base you'll find many subdirectories with that 
                name. There are php code files that test our code. we 
                thought calling them just 'test' would not give them the 
                honor they deserve, and prolly someone would just delete 
                them. The ecg tests show a sysadmin very fast what's not 
                working (anymore) on his system, for example after the 
                installation or after a php upgrade or whatever. 
   whtml        wysiwyg html. It's a mime type in blueshoes. It means that 
                the block [part] may be edited using wysiwyg. So it's not 
                xml compliant. A synonym would be "crappy html".
   URL: (see Bs_Url.class.php and its methods)
   example: url https://bill:gates@order.blue-shoes.com:81/forms/
     scheme     = https
     host       = order.blue-shoes.com
     port       = 81
     user       = bill
     pass       = gates
     path       = /forms/form.php
     query      = lang=fr&sid=456456
     fragment   = address
     domain     = blue-shoes.com
     directory  = /forms/
     file       = form.php
   xpv stands for xPointer vector. Match always returns an array, so xp 
   is always an array, maybe an empty one.
   UID          Unified ID.

Treeview control with built-in checkbox system, drag&drop suppert etc. more ...

Let us know

Have you done something interesting with BlueShoes or one of its components?