debuggable

 
Contact Us
 
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56

Naming Conventions

Posted on 16/3/07 by Tim Koschützki

Naming conventions are one of the easiest, but most powerful tools to make your code readable and easy-to-follow. Over the years, certain standards have developed for most programming languages, including PHP. Let's outline them here.

Naming Variables

  • Use all camel-case; start new words with a capital letter. Example: $thisIsAvariable.
  • Use descriptive names (except loop variables).
  • Loop variables can be of the usual variety: $i, $j, $k, etc.
  • Count variables should follow the format $*_count, e.g. $bug_count
  • Global variables should be prefixed with g_
  • Temporary variables should be prefixed with t_
  • $query and $result should be used for SQL query and results respectively

Some people suggest, that one should prefix variables depending on where they are coming from and whether they have been "cleaned" yet (as in slashes stripped, etc.). I liked the idea at first, but admittedly, as your scripts grow, the code becomes more and more unreadable if you deal with variables like $c_resultSet and $i_loopVar for a cleaned resultset and an integer.

If you code in a clean way, that is with many small functions, you should be good to go without prefixing.

Naming Functions

  • Use all camel-case again. Example: function thisIsMyFunction()
  • Keep functions to 5 words or less
  • Name the function after what it does. Something like functionA() doesn't help. cleanSqlQuery() is much better.

Naming Classes

  • Use all camel-case again with the first letter being capitalized. Examples: class MyDog(), class RequestParser(), class BbCodeParser()
  • Keep classes to 5 words or less
  • Name the class after what it does. Something like class SomeClass is not descriptive enough. Class SqlQuery is much better.

Naming Class Methods

  • Use the same strategy as for normal functions. Do not start with a capital letter as indicated in some guides. Justification: When using typehinting, this can get quite confusing. Example: $requestParser = RequestParser $this->CreateRequestParser();
  • Keep methods to five words or less
  • Name the method after what it does.

 

Releasing Resources

Posted on 15/3/07 by Tim Koschützki

This goes without much explanation. Whenever you are using any resources, like files, streams, etc, always make sure you release them.

Files

For files it is a best coding practice to use fclose once you are ready with your file operations. Here is a quick example:


  $handle = fopen('somefile.txt', 'r');
 
  // do something with the file

  fclose($handle);
 

The consequences of not using fclose on open file handles or stream handles are unforseeable and depend on the operating system. Maybe the file cannot be opened again. I am still researching of what could possibly happen, so stay tuned for updates to this article.

As for now, make it a habit though to always release your resources.

Using up your resources

It's of course also in PHP possible to use up all your resources. For example when you are comparing large database tables with multiple nested select statements and the like. You can alter the php.ini setting "memory_limit" and set it from the default 16MB to for example 64MB.

Always ensure that you set this setting high enough before you execute system critical code, especially on your live site, or else your webserver may go down, your mysql server may crash and the script can't execute properly and thus might corrupt data.


 

BaseUrl finding, Simple event broadcasting and element sorting in JS

Posted on 15/3/07 by Felix Geisendörfer

Hey folks,

it's been a while since my last post on JS (and in general) and I apologize for that. There is just way too much stuff for me to do right now (client work, my own web app, school finals, etc.) but most of that will be over at some point and then I'll have a thousand interesting things to blog about as well as the time for it. Meanwhile here comes some fun JS stuff I'm using in the web app I'm working on right now and I hope you'll enjoy it. When you see the '$' sign in the code then it's the jQuery library I'm absolutely in love with and not the evil prototype one ; ). All code I'll post now can be written without it, but I don't have the time to present alternative solutions right now.

Alright let's get started. First of all I advocate the usage of a namespace for the functions I'll present since that makes it less likely to run into conflicts with 3rd party scripts as well as allowing for the code base to stay more maintainable. I'm assuming you are using CakePHP so please create a file called 'common.js' in /app/webroot/js/. The other file you put in there is the latest 'jquery.js' that you downloaded from jquery.com. In your html layout you include jquery.js first and common.js second.

The first thing I got for you is a function capable of determining the base url where your application is installed. This is very useful when doing lot's of ajax requests and you want to be able to always use '/controller/action' style url references like you do in CakePHP internally. It's also nice to know image files will always be located in '/img/...'. The way I do it is inspired by the script.aculo.us lib and looks like this:

var Common =
{
    baseUrl: null
   
    , setBaseUrl: function(url)
    {
        Common.baseUrl = url || $('script[@src$=js/common.js]')
            .attr('src')
            .replace(/js\/common.js$/,'');
    }
   
    , url: function(url)
    {
        return this.baseUrl+url.replace(/^\/+/, '');
    }
}

Common.setBaseUrl();

The code should be pretty straight forward. After defining the Common object (used as a namespace) we call it's setBaseUrl function without parameters. This causes a jQuery selector to find the script element of our common.js file and use it's src attribute to determine the baseUrl. From that point on we can do calls like this in our other JS files:

$.getJSON(Common.url('/tasks/view/1.json'), function(Task)
{
    alert('It is time to "'+Task.name+'"!');
})

Alright this is useful (at least I hope so), but there is more stuff to come. One thing I found myself working a lot with was collections of objects of the same type that need to exchange messages through events with one another. For example you have a class called 'Task' and all of them are managed by another object called 'TaskList'. Now let's say the User is able to click on each Task in your TaskList which causes this particular Task to get the focus (a couple of DOM elements getting an 'active' class). When one Task get's focused, naturally all other tasks need to loose their focus. Here is some code similar to what I'm using in my application right now which will make this become very easy and fail-safe:

A new generic broadcastEvent function for our Common namespace. It basically loops through all listeners (array of JS objects) and sees if they have listeners for the particular task defined and call those up. It also set's the context of the listener function to the object that is listening and uses whatever additional parameters are passed to broadcastEvent for calling it:

var Common =
{
    broadcastEvent: function(listeners, event)
    {
        var params = arguments;
       
        $.each(listeners, function()
        {
            if (typeof this.events[event] == 'function')
            {
                this.events[event].apply(this, [].slice.call(params, 2));
            }
        });
    }
}

And here comes the TaskList that object that manages all Task's on the screen. It basically uses a table (element) as it's construct parameter, loops through all rows with a 'td' in them (those that are not part of the table header) and passes the table row elements as an initialization parameter to the Task object that is created for each one of it and added to a list of tasks. TaskList.broadcastEvent uses Common.broadcastEvent to allow the tasks inside the TaskList to communicate with one another easily which you'll see in the Task class.

var TaskList = function(element)
{
    this.construct(element);
};

TaskList.prototype =
{
    element: null
    , tasks: []

    , construct: function(element)
    {    
        this.element = $(element)[0];
       
        var self = this;
       
        $('tr[td]', this.element).each(function()
        {
            self.add(new Task(self, this));
        });
    }
   
    , add: function(TaskObject)
    {
        this.tasks.push(TaskObject);
    }
   
    , broadcastEvent: function(event)
    {
        var params = [this.tasks, event];
        params.push.apply(params, [].slice.call(arguments, 1));
       
        Common.broadcastEvent.apply(null, params);
    }
};

And here comes the Task class that triggers the event broadcasting and listens to events. It's constructor takes two arguments. The first one is a reference to the parent TaskList object and the second on is the table row (tr) element that hold the DOM representation of this Task. When the name of the task ('a.name') is clicked then it causes that Task to get the focus and all others to be blured (as they receive the focus event and react on it):

var Task = function(parent, element)
{
    this.construct(parent, element);
};

Task.prototype =
{
    id: null
    , parent: null
   
    , construct: function(parent, element)
    {
        this.parent = parent;
        this.element = element;
       
        this.bindEvents();
    }
   
    , bindEvents: function()
    {
        var self = this;
       
        $('td.task a.name', this.element).bind('click', function()
        {
            self.focus();
            return false;
        });
    }
   
    , focus: function()
    {
        $('a.name, a.time', this.element)
            .removeClass('active')
            .addClass('active');
           
        this.parent.broadcastEvent('focus', this);
    }
   
    , blur: function()
    {
        $('a.name, a.time', this.element)
            .removeClass('active');
    }
       
    , events:
    {      
        focus: function(Task)
        {
            if (Task !== this)
            {
                this.blur();
            }
        }
    }
};

Alright that's it. The code above is of course just meant for educational purposes and not the complete code I'm using in my web app which is a little more complex and would only distract from demonstrating the Common.broadcastEvent function. So if it doesn't run it's probably because I didn't test the simplified version presented here.

So let's come to my last little trick, sorting elements in JS. Javascript has a very cool function build into the Array class named sort that is very useful for doing all kinds of sorting as it allows you to define a callback for comparing the array elements yourself. It basically works like this:

The following code uses jQuery to get all list items inside of a unorder list and then sorts the array using the anchor text (for simplicity, innerHTML).

var elements = $('ul#my-list li').get();

elements.sort(sortByName);

function sortByName(a, b)
{
    if (a.innerHTML < b.innerHTML)
    {
        return -1
    }
   
    if(a.innerHTML > b.innerHTML)
    {
        return 1
    }
   
    return 0
}

But since we don't only want to sort them inside the array but also in the DOM, we need to get a little more tricky. In the simplest case this means to remove all li elements from our unordered list before sorting and them put them back into our list after we sorted them:

var elements = $($('ul#my-list li')
    .remove()
    .get()
    .sort(sortByName))
    .appendTo('#my-list');

If you don't like the train-wreck style you'd write the above like this:

var elements = $('ul#my-list li').remove().get();
elements.sort(sortByName)
$(elements).appendTo('#my-list');

So of course if you work with large lists of items you might want to actually swap elements using the Array.sort callback instead of re-populating the entire list, but for this example I wanted to keep it simple. Also here is a live demo where you can check out how the method presented here works on a small list. You basically can not tell that all elements where removed and then added again.

Alright, I hope you find some of the above stuff useful and if you have any questions feel free to ask them in the comments.

-- Felixd

 

Simple and Complex Strings

Posted on 6/3/07 by Tim Koschützki

There are a few simple rules when it comes to strings. To understand them, you have to know about variable interpolation.

Simple Strings

In PHP when you define simple strings using single quotes, no variable names will be interpolated. For example:

$var = 10;
echo 'some string here $var';
// output will be: some string here $var

This is of course a small performance issue as well as the php interpreter does not have to look for variables to be parsed. The downsite of this is, that carriage returns (\r\n) will also not be parsed as such.

Complex String

If you want to have variables to be parsed inside a string, you have to use double quotes.

$var = 10;
echo "some string here $var";
// output will be: some string here 10

This is gives a small decrease in speed, as the php interpreter looks for variables and parses them. Of course, for small application this makes almost no difference. However, think of very large applications with many user interactions and possibly many database queries that need to parse variables. This may lead to a performance issue then.

Various ways of parsing variables in complex strings

1. Method

$var = 10;
echo "some string here $var";
// output will be: some string here 10

2. Method

$var = 10;
echo "some string here ".$var;
// output will be: some string here 10

3. Method

$var = 10;
echo "some string here {$var}";
// output will be: some string here 10

This is a very handy method, which I use often, because it makes parsing arrays easy. What for example you want to parse $arr[0] and want to append the string [0] directly afterwards?

$arr = array(0=>'test');

echo "some string here $arr[0][0]";
// will generate a warning

echo "some string here {$arr[0]}[0]";
// output will be: some string here test[0]

4. Method

$var = 10;
echo "some string here ",$var;
// output will be: some string here 10

This is a very unusual form to php developers. Many don't even know, that it exists. I must admit I hadn't known it either for long. It was just until my php zend certification exam when a question exposing my knowledge about this variable parsing method faced me. It made me think very hard, but eventually I was correct.

 

My favourite "bug"

Posted on 27/2/07 by Felix Geisendörfer

Hey folks,

here comes an example of my favorite "bug" that drives me insane on occasion:

if (!$this->hasField($field));
{
    // Do Something
}

It just got me again and caused me to debug Model::hasField, finally implementing my own version of it until I realized what an idiot I am ... ; ). What's your favourite?

-- Felix Geisendörfer aka the_undefined

 
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56