wiki:ProgrammingGuideline

UPDATE WARNING

This page needs a review. Some guidelines are not supported by the current developers (i.e. planetcruiser) any longer or have never been followed by many people. If in doubt, ask the currently active developers. ;)

Programming Guideline

See also

The programming guideline describes what the BeWelcome code should look like and how to document it. Any deviations from this guideline should be corrected. If there is a real need for not following some part(s) of this guideline, talk first with the SW development team coordinators to see if the guideline needs update.

Following coding standards for naming, indentation etc means you show respect to fellow developers who want to read or modify your code. A lot of time is spent on reading code, so please take this serious!

Quick and Short

PEAR programming guideline
The PEAR PHP programming guideline is the bible of PHP programming. check its coding standards and learn it by heart!
Use English language!
The language for names and comments and all that is English. Do not ever write any names of files, variables and functions or comments in any other language. The dictionary is your friend! (there are enough online dictionaries out there). If that doesn't help, others can correct your mistakes. See below, "Identifier Names".
Separate of layout and code!
A clear separation between layout and code should be maintained in all circumstances. Ideally we only have explicit HTML inside template files, sometimes in classes in the 'MVC view layer'. Never ever in controllers or models! See ArchitectureGuideline.
Use the translation engine
Never hard code any texts which users might see in PHP files. Use our translation functions instead. Announce newly added strings in this group thread, so translators can translate them to their language: http://www.bewelcome.org/groups/60/forum/s2330-Translation_Anouncements

HTML

We want to comply with XHTML 1.0

JavaScript

When implementing new scripts or refactoring exiting ones, please use the Google JavaScript Style Guide.

PHP (I): Keep it simple!

  1. Avoid ternary operators ($a = $b ? $c : $d)
    • They might look very 133t, but are hard to read sometimes
    • Adding debug statements or extending is not possible
    • Use properly formatted if clauses instead

PHP (II): Keep it safe and robust!

TODO: check if all these tips are correct! Especially for the escaping I'm not sure.

Be careful when checking if variables are undefined, empty, or whatever. Better think about what exactly you want to check! Useful functions:

  • is_empty() is useful with arrays, strings and objects.
  • is_array(), is_string(), is_object(), is_numeric()
  • isset() - check if a variable, object attribute, or array key is defined
  • class_exists(), method_exists(), is_class(), is_method()

escaping strings:

  • mysql_real_escape_string() for text used in SQL statements, to avoid SQL injection.
  • ? for text used in html
  • ? for text used in html tag attributes

filesystem paths

  • is_file(), is_dir() - check if an absolute filesystem paths points to an existing file/directory.
  • you don't need to think any more about slash vs backslash in Linux vs Windows. A slash will always work nowadays.

linebreaks (?)

  • As some of us use Linux, others use other operating systems, it doesn't matter if you use Apple, DOS or Linux line breaks.

finding bugs:

  • When possible, use tools to find the obvious bugs in the code. For example, Eclipse shows a lot of clear mistakes. Take benefit of such things.

PHP (III): Syntax Formatting - Keep it Readable!

These are mostly taken from the PEAR coding standards. Some of them can be seen as rules, others just as suggestions how you can make your code more readable.

Indentation: 4 spaces, no tabs.

  • Code should be indented with +4 spaces each block level. Don't use the explicit tab symbol! Usually you can change the "tab policy" in your editor of choice.

Linebreaks: avoid horizontal scrolling

  • If possible, all the code should be readable without horizontal scrolling. To make this possible,
  • break SQL statements, HTML and other strings to multiple lines (see below).
  • Break comments to multiple lines.
  • Break PHP code (array definitions, etc) to multiple lines, with the appropriate indentation.
  • Inline comments which would make the line too long go in a separate line.

Misc.

  • ";" should be always written without preceding space.
  • echo and return don't need braces.
  • spaces before "(" symbol: Write control flow statements like "if (" and "switch (" and "foreach (" with a space, but function calls like "foo(", "$this->bar(" (without a space).
  • Do not mark the end of block with a comment if not needed. Functions are separated by their appropriate PHPDoc comment blocks.
  • If some part of code is not completely ready for some reason. Mark it with a comment: <tt> TODO: need to blah blah blah, 20070730</tt>
  • Don't use control structures (if, while, for) without curly brackets "{}", because it makes it more difficult to read and extend code
  • The dot connecting strings is an operator and should therefore have spaces before and after it. Correct: $message = "You have " . $number . " friends";
  • Don't use short tags (<? ... ?> and <?= ?>). We use <?php ... ?> almost everywhere and we should keep things consistent.
  • In templates use this to print out variables:
    <?php echo $username; ?>
    

Multi-line Arrays

If an array definition grows to big, it is better to break it to multiple lines. A multi-line array can look like this:

$my_array = array(
    'something',
    'something else',
);

$my_associative_array = array(
    'key1'       => 'value1',
    'key2'       => array('2a', '2b'),
    'anotherkey' => 'anothervalue',
);

Things to consider.

  • if every line (especially the last one) ends with a comma, it is easier to rearrange them, or add a new one.
  • If the "=" are all aligned, it becomes easier to read (well.. that's not a rule)

Multi-line Strings: Inline HTML

Long SQL statements or inline html strings often exceed the right end of the editor window, forcing the reader to do horizontal scrolling. Fortunately, it is possible in PHP to have a string span multiple lines. And both HTML and SQL don't care about additional linebreaks or whitespace - a bunch of linebreaks plus whitespaces has the same effect as a single whitespace.

HTML in template files can be written like this,

?>
<div>
    <h3><?=$headline ?></h3>
    Some text
</div>
<?php

Inside class methods this would look rather ugly, so: If you feel you need to have inline html in class methods, this could be the way to do it:

function foo()
{
    echo '
    <div>
    <h3>'.$headline.'</h3>
    Some text
    </div>
    ';
    if (...) {
        echo 'yes';
    } else {
        echo 'no';
    }
}

Things to consider:

  • Don't use a new echo or $str.="..." for every new line. This would make it a pain to modify the string.
  • For longer html, put the quotation marks and echo or <?php and ?> statements in a separate line, where there is no html text. This way, it becomes easier to move the html lines up and down.
  • A long connected string is better than a lot of cluttered small strings. Again, this makes it easier to modify parts of the string.
  • Indentation for XML/HTML should not overshadow the indentation for your PHP blocks. (In the above example all the indentation follows PHP blocks, not XML blocks).

Multi-line Strings: SQL Statements

SQL statements are vital for the understanding of the code. Therefore it is important to make them easily readable. The following syntax is an example how SQL statements can be made both easy to read and easy to modify.

        $message = $this->singleLookup(
            "
SELECT
    messages.*,
    receivers.Username AS receiverUsername,
    senders.Username   AS senderUsername  
FROM
    messages
    LEFT JOIN members AS receivers  ON  messages.IdReceiver = receivers.id
    LEFT JOIN members AS senders    ON  messages.IdSender   = senders.id 
WHERE
    messages.id = $message_id
            "
        );

Things to consider:

  • indentation helps a lot for clarity.
  • Make the SQL statements stand out by breaking the PHP indentation and letting each SQL statement begin at indentation level zero. This makes it possible to quickly scan the code for SQL statements.
  • Vertical space between PHP and SQL (here with a quotation symbol) help to separate the two.
  • SQL keywords should be ALL UPPERCASE.
  • A nice trick is to have the " symbol in a separate line, where there is no SQL code. This allows to move the SQL lines up and down, without having to fight with the " symbol.

MySQL queries in PHP code

In SQL SQL expresssions are in UPPER CASE.

 SELECT SQL_CACHE * FROM address WHERE id_member=1 AND rank=0 LIMIT 1

and not

 select SQL_CACHE * from address where id_member=1 and rank=0 limit 1

It helps readability

  1. if you can see the full query without horizontal scrolling.
  2. if the SQL code is clearly separated from the surrounding PHP code.

It's a good idea to break it to multiple lines, like this:

        $message = $this->singleLookup(
            "
SELECT
    messages.*,
    receivers.Username AS receiverUsername,
    senders.Username   AS senderUsername  
FROM
    messages
    LEFT JOIN members AS receivers  ON  messages.IdReceiver = receivers.id
    LEFT JOIN members AS senders    ON  messages.IdSender   = senders.id 
WHERE
    messages.id = $message_id
            "
        );

or like this, for simpler queries:

        return $this->singleLookup(
            "
SELECT *
FROM members
WHERE Username = '$username'
            "
        );

Identifier Names

PHP Identifiers

PEAR naming standards
Follow the PEAR naming standards.
consistent naming
The name of frequently used PHP variables should always be the same. This isn't mandatory, but helpful for code browsing. So please look around, what others do. E.g. you might often find $query as the name for a string containing a complete SQL statement. It would make things easier, if you use the same name for your SQL statement.
Uppercase, CamelCase, under_score etc

  • class names in
    CamelCase: "class SearchmembersController"
  • public and protected method names in
    lowerCamelCase: "MessagesModel::getMessagesWith(..)"
  • local variables, and public or protected class attributes
    lowercase_with_underscores: "user_id"
  • private member variables and methods with
    _trailing_underscore: "$this->_createMessage()", "$this->_cached_values"
  • special: If a method or class name is composed out of two segments by some fancy mechanic, then it's ok to connect them with an underscore. This can help to understand the synthetic nature of this identifier. For instance, 'get' + 'username' becomes 'get_username'.

Choosing meaningful identifiers

not too short

  • Avoid abbreviations, unless it's really clear what they mean.
  • Don't be cheap with identifier length. Only mathematicians use variables like $a, $b, $c, $x, $y. They write with chalk, you have a keyboard!

Avoid ambiguity. Not everything has to be explicit, but at least those bits that would otherwise cause confusion. If things have different roles, give them different names.

  • A "$user" can be anything. Having "$user_id" and "$username" is a lot more helpful. The same for "$method" - much better is "$methodname", so you know it is a string.
  • Arrays should be named as a plural.
  • If there is more than one user, let the names reflect their roles - for instance, $receiver_username, $sender_username.
  • Avoid meaningless name diferences like "doLogin()" vs "login()". If you think two of your methods deserve the same name, it is time to think about your design. Do you really need them both? If yes, what's the difference in what they do, or their roles? Do they depend on each other, and how? The method names should give a clue why you need them both!

Method name prefix.
Some functions have a meaningful return value, others just print the result to the output stream.

  • The method prefix "get" (as in "getMemberWithId($id)") indicates a return value.
  • The prefix "show" (as in "showSidebar()") or "print" would indicate that something is printed.
  • The methods of a page or widget class do by default print things, so they don't need a prefix saying "show" or "print".

one var = one role[[BR]

  • Don't let a variable change its role or type! Things like "$request = exlode('/', $request);" are totally confusing! Instead, you can make a new variable, such as "$request_exploded".

PHP: Documentation (PHP Comments)

Every programmer is personally responsible of generating proper PHPDoc compatible documentation of the code they produce.

The minimum amount of tags what need to be written for each file and function are:
@author
@param
@return
function and method descriptions

Everything should be described, just listing names is not helping anyone.

See example here: PEAR standards sample

Database Design

TODO: Some of this has to be checked, if it's still valid.

Naming of Tables and Columns

Table names

  • lowercase letters with under_score
  • table names plural?
    • Someone says: Every table includes several rows. Therefore it's senseless to put the plural in their name. "address" is a much better table name than "addresses" as everybody already knows, that it includes several of them.
    • Fake51 says: This is bad design. Objects should be named after what they are: since tables store multiple rows, they should ALWAYS be named in plural. The whole point of naming is that you shouldn't be guessing or assuming anything. All table names should be plural, but all column names should be singular, since any given field should only store one value.
    • lemon-head says: Yes, and it is more intuitive to use plural.. I am sure we are not the first ones having this question - so, any good references?
    • Fake51 says: Well, we discussed it on the mailing list a while ago, look here http://bewelcome.org/pipermail/bw-dev-discussion/2008-January/001515.html - the standards Morgan Tocker's which we all agreed were nice. Other than that, Database Design for Mere Mortals has a good set of standards as well - almost the same as Morgans (difference in foreign key naming).

Column names

  • normally people would use lower_case_with_underscore.
  • In BW-Rox, we already have tons of column names in CamelCase. So, now we better stick with that.
  • Also, don't introduce redundancy in the naming. The primary key of tables should be named 'id' unless you have a good reason to name it differently (mainly because a column that does not store ids is made primary key). Hence, in a table "Addresses" don't name the id "address_id" - just name it plain "id". Also (again, in the addresses table) don't use addrZipcode or addrStreet - since the columns are in the addresses table, they HAVE to be address-related, so don't write that in the name.
  • When setting foreign keys, name like this: [singular name of foreign table][underscore][key]. It will almost certainly be like: address_id or member_id. This way you know exactly which columns of a table are foreign keys and what table they link with.

    • The exception would be if more than one column point to the same foreign table. In this case, one would create column names from the roles of the fields. For instance, a table "messages" could have two columns "sender_id" and "receiver_id", which both point to the "members" table.

Comments

When you're creating or editing a table, adding or editing columns, it's good practice to stick in comments - both for the table and for the columns. This helps a lot for the next fella who needs to figure out what the database design is like.

Structural Design

While creating tables watch out not to produce reduncancy. Learn about normalization here: http://en.wikipedia.org/wiki/Database_normalization.

Example Table

Table:
 members

Columns:
 id // primary key
 firstname
 lastname
 username
 address_id // foreign key
 ...etc

Last modified 5 years ago Last modified on Dec 7, 2012 6:09:25 AM