Debugging techniques for Web development 2 – Configuring your environment

In the previous issue we discussed using the right tools to more easily debug your Web development scripts.

Now these tools can be made even more useful if they are configured in a way that makes the developer’s life easier.

2. Configuring your environment for better productivity

If you don’t make yourself at home in your own code base, who will?

Configuring your environment can mean many things, but the points I would like to cover in this post are:

  • Setting up your editor / subversion / server so that you can get through the day in the most painless way
  • Creating a development environment that works alongside your production
  • Writing your code so that if something goes wrong you can easily pinpoint the cause and quickly fix it

Setting up editor / server & co

When you start working on a project, you often want to start small and avoid wasting massive investments to organise your code. Now, once you’ve done it a few times, you’ll realize that settings up a clean and comfy environment doesn’t take that much effort, and really pays off in the long run.

By that I mean the following:

On the editor

  • Making sure your editor is the right one for the language you use, and is extendible. This means it allows you to define keyboard shortcuts for the kind of things you often do. I like creating shortcuts for the following stuff:
    • firing up a svn diff or svn commit command. Most of the time it’s just to figure out if I’ve changed the file at all, sometimes it’s to do an actual commit
    • opening the browser at a given location
    • bookmarks for often-used config files (e.g. the apache ini)

On the server

A common practice with beginners using a webserver is to put all their projects under a single root, so they can then get pages at

http://localhost/project1 (which will point to c:\bla\bla\root\project1)
http://localhost/project2 (which will point to c:\bla\bla\root\project2)

Now, by tweaking some config, you can achieve a much more symmetric setup, where your 2 projects will be hosted on the root of some (virtual) server. In order to do so, do the 2 following things:

    • Add as many entries as you like in your hosts files (see Wikipedia), of the following form
# all these names point to your localhost
# but Apache will see the difference
# due to the VirtualHosts directive

127.0.0.1    project1
127.0.0.1    project2
    • Add virtual hosts in your Apache config, like this

    DocumentRoot "c:\bla\bla\root\project1"
    ServerName project1

The result of that is the ability to get the website (from your computer that is!) at an address like

     http://project1/

I know – in theory it shouldn’t matter whether your pages are at the root of your server or not! However in practice it is a source of so much pain and wasted time when your local setup runs on a sub-folder of the root and your production setup runs on the root, and some things do not work as expected on your production server. Life’s too short to try and make it work (and some of the frameworks are just rubbish at working outside of the root of a server and you do not plan to fix them).

In the database

Not that I am doing it routinely, but some cool database features can be leveraged to make your life easier:

  • Views: these are queries that you can use as if they were a table. So for instance, if you’ve got a query like this
SELECT user_id, user_name FROM users WHERE user_type = 'admin'

Then you would create a view by doing this

CREATE VIEW admins AS
SELECT user_id, user_name FROM users WHERE user_type = 'admin'

Subsequently, you can then do

SELECT user_name FROM admins

This can be useful when you are debugging and don’t want to endlessly retype the same WHERE clauses.

  • Triggers: never used these, but they look pretty powerful. They allow you to have cascading effects in your tables, or prevent you from doing operations which would violate relationships (e.g. preventing you from deleting a user in the users table if the posts table still has entries linked to that user)

In your system

Create scripts to perform standard tasks.  I personally think that people who write batch / unix scripts are masochists, and so I do it in python much more easily. That includes

  • Issuing ssh commands to a remote server (e.g. svn update)
  • Tranfering files through SCP
  • Creating a dump of your mysql database using mysqldump
  • Going to some of your favorites directories

Creating a development environment

For some people, a development environment is something they are not even aware of and which consists of a series of commented print (PHP) or console.log (Javascript) statements scattered randomly in their code, and which will be uncommented when needed – and sometimes accidentally pushed to production with unpredictable consequences…

Any serious framework will consider the development environment an integral part of the project, and provide an API that will allow the developper to leave trails of what is happening. At the same time it is important that the user does not see any of this, be it for better customer experience or sometimes as a security precaution (i.e. avoiding to give the user insights in the server-side code). This can happen by having the notion of environment at the API level. This means that

  • At the root of your code (the HTML page for Javascript, your controller for PHP), there needs to be an assesment of what the current environment is, i.e. ‘development’, ‘testing’, or ‘production’. This can be done by some environment variable, some local file, can be based on the hostname (or the virtual host – even better!), or perhaps by some cookie on the user’s browser.
if ( /*... */ )
    $ENVIRONMENT = 'production'
if ( /* ... */ )
    $ENVIRONMENT = 'development'
  • Any setting that has reasons to vary depending on the environment should be predicated on the environment. So, for instance, the MySQL database could be a function of the environment, for instance like this
$db['production']['database'] = 'projectdb_prod';
$db['dev']['database']        = 'projectdb_dev';

And the subsequent calls will be like this

$server = $db[ $ENVIRONMENT ]['database']

A golden rule – A SINGLE CODEBASE

 The ‘single codebase’ rule means that you do not want to have different versions of the same file depending on the server. This would be difficult to maintain / deploy (not least because it would have to be outside of your control version system), and soon or later you are going to accidentally overwrite the config of one server onto another and scratch your head to understand the source of a bug. Instead, you want all the settings to be in the common codebase, and ensure that the choices are done on-the-fly depending on the environment / host / OS.

Writing your code so it is debuggable

Separation of concerns

Modularity, for example as in MVC frameworks can dramatically improve the debuggability of your code. This is because the business logic will be testable independently of the GUI (which tends to be tough to test).

Hard to give precise guidelines, but let’s say that the rule of thumb is to make it so that you can test key features of your application with one-liners and without having to use the user interface.

Using configuration settings or even bits of code that can be changed at runtime

A technique I have found useful, which is more related to fine-tuning the Javascript part of your application than debugging it, is that of using configuration settings.

For instance, in an app I am developping, I need to parametrize many settings so that some graphics looks as good as possible.

Previously my code was looking a bit like this

some_setting       = 0.5
some_other_setting = 25
timestep           = 0.25
some_curve         = timestep * some_setting + x * some_other_setting + /* .. */

This meant that, in order to test changes to any of these settings (say, move some_setting to 0.6), I needed to reload my page. Given that I am now convinced that one-page (javascript) apps are the future of the web, I end up with a page whose initialization can take up to 10 seconds. Given the features, this is acceptable for the end-user, but for debugging purposes, it is a bit of a pain.

The idea I came up with (well this must be a design pattern – I just don’t know how it’s called) was to use a global function to get and set settings, and attach a callback that gets triggered every time the settings are changed.

This broadly worked as follows.

In a library, I would have

// ideally this first line should be in a project specific library whilst
// the rest is totally generic
function DefaultSettings() { return { 'SOME_SETTING' : 0.5 /* ... */ } }
current  = DefaultSettings()
onchange = function() {}
function Settings(key) { return current[key] }
function SettingsSet(key,value)
{
     current[key] = value;
     onchange(); // trigger callback
}
function SettingsReset() { current = DefaultSettings(); onchange(); }
function SettingsAttachCB( callback ) { onchange = callback }

Then my code above would become

some_setting       = Settings('SOME_SETTING');
some_other_setting = Settings('SOME_OTHER_SETTING');
timestep           = Settings('TIMESTEP');
some_curve         = timestep * some_setting + x * some_other_setting + /* .. */

And in my initialization function, I would have a line like this

SettingsAttachCB( SomeRefreshFunction );

This would mean that, once the page has loaded, I can go to the Chrome debugger console, type SettingsSet('SOME_SETTING', 0.6), and that will automatically trigger SomeRefreshFunction.

Settings

As a matter of fact, I even wrote a little HTML widget that turns current in JSON into a popup window, and allows some users to modify it.

Now, if you’re into it, you can push this idea a bit further by having some bits of code like this

fn_to_apply = Settings('FN_TO_APPLY')
/* ... */
x = fn_to_apply(some_args);

and then interactively setting

SettingsSet('FN_TO_APPLY', function(args) { /* ... */ } )

Which effectively allows you to modify arbitrary parts of your code without having to reload the page. There might be limitations to that (especially if you are instantiating objects and using some of their member functions, although that might work to some extent).

If you like this particular technique, google ‘data-driven programming‘ or ‘table-driven programming‘. A lot of the ideas of Web 2.0 (CMSes like WordPress in particular) are somewhat using this approach of table-driven programming, because the code (in this case HTML) does not reside in html files, but instead are stored in tables, so they can be modified by the user rather than only by the developer.

Conclusion

Overlooking the possibilities to configure your system in a way that suits your project may result in a suboptimal environment. The few tricks given above should be reasonably easy to follow, and have made me gain a lot of time and focus on my projects – so I hope they will be helpful for you as well.

In the next issue, we will discuss techniques similar to the one described in the previous paragraph, and that will allow the developper to fix his javascript after the page has loaded, rather than going through long edit/reload cycles.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s