You are here

debug

"You have to have something bad happen to you"

Steve Yegge on code’s worst enemy:

… This brings us to the second obviously-bad thing that can go wrong with code bases: copy and paste. It doesn’t take very long for programmers to learn this lesson the hard way. It’s not so much a rule you have to memorize as a scar you’re going to get whether you like it or not. Computers make copy-and-paste really easy, so every programmer falls into the trap once in a while. The lesson you eventually learn is that code always changes, always always always, and as soon as you have to change the same thing in N places, where N is more than 1, you’ll have earned your scar….

Code reuse is great, although some languages punish you for it: Coldfusion takes a performance hit on behalf of debug logging whenever it crosses a component boundary, even if debugging is turned off. And a lot of includes scattered across the place can make it difficult to track what’s going on (unless you use those very IDEs that Steve suggests treat code like heaps of dirt to be rearranged). I suppose ultimately it’s about developing an instinct for balancing short-term performance, ongoing maintainability and long-term scalability, and you only learn that by dint of many, many scars.

Taking Drupal to pieces

Since listening to Garrett Coakley speak at the first Geek Night on the topic of Drupal, I’ve been sniffing round that open-source CMS. He kindly came to speak to us again, and very inspiring it was too. We’re now having a deeper look at it, seeing what it can do, what are its strengths and weaknesses; that sort of thing.

Drupal is certainly very interesting. Its notion of presentation is remarkable in that, at a certain level, all content consists of homogeneous nodes, whether that consists of uploaded files, images, blog posts, taxonomy categories, or embedded YouTube videos. In addition its API for templating, both as a library of functions and as a workflow that one can hook into, probably rivals WordPress in its scope and power. At the same time, though, the implicit homogeneity makes it hard to structure fundamentally heterogeneous sites; and the API hooks are very difficult to unravel: frequently you’ll want to get at a function some ten levels deep, and probably three of those levels can be overridden by your own code, but which, and how?

I want to mention more at a later date, to do Drupal justice, but suffice it to say for now that the complex hierarchy of the hook-in workflow is almost entirely opaque in PHP, a language that provides rather terse error reporting, without the function debug_print_backtrace(). Well worth a look if you’re debugging spaghetti-code, especially when all you can see is the White Screen of Death. Sprinkle it around as the gentle British rain from heaven: lightly, but often.

How to write a Javascript file

Now I know the title sounds presumptuous, but there’s a certain methodology I’ve settled into that seems to work really well for encouraging Javascript that’s legible and safe. I thought I’d share it with anyone that doesn’t consider themselves a JS playa, in case it’s of some use to you too.

Most Javascript libraries these days are written in a similar way, so it seems to be de facto recognised best practice, but it’s worth showing the anatomy of the simple case so you can build on it rather than having to work out what’s going on from an enormous, somewhat crufty sprawl.

/*
    @description Javascript template
    @createdBy JPS
    @createdOn 2006-10-03
    @notes Standard template
*/
    
MyObjectWithHandyName = {
    
    // Properties
    p: {
        // HTML IDs
        i: { },
    
        // HTML classes
        c: { },
    
        // Something else we might need to reference
        sthg: {}
    
        // Be wary of accidental trailing commas here, as it’s the end of
        // the array and IE doesn’t like a comma at that position
    },
    
    // Methods here - use hierarchy if large object
    DOM: {},
    eyeCandy: { dropdowns: {}, errors: {} },
    httpReq: {},
    
    // Window onload method - instantiates everything
    go: function() {
        alert(’OK!’);
    }
    
};
    
// Now add onload handler to do anything your object needs to do when page loads
    
// Prototype
// Event.observe(window, ‘onload’, MyObjectWithHandyName.go, false);
    
// Mochikit & others
// addLoadEvent(MyObjectWithHandyName.go);
    
// No library?
window.onload = MyObjectWithHandyName.go;

What’re the advantages of the above? Well, first of all, it just formalizes what you’ve already decided to do: that is, to encapsulate all the functionality to do with a certain something in one file. This just puts it all in one object, which you could call DHTML, or iFoo, or GoogleHack, or MyApp. It prevents collisions with standard Javascript functions, library functions you might include etc. Also, if in future you want to know if a function has been defined on a page, but from a different Javascript file, it’s sufficient for a smallish project to check the top-level object exists.

Secondly, the system is very extensible, and tidy with it. If configuration variables go in the hierarchical p(roperties) block at the top of the file, then you can re-use your code by, say, including a second Javascript file on certain pages, that rewrites this configuration. You can even change methods like this, if you know where they’re going to be, in a safe, extensible way. The hierarchy of the whole object means you can nest methods as far down as you want: then, if you find yourself repeating much of the hierarchy, you can use the with(object) control structure to tidy your code:

foo: { bar: { quux: { a: function() {…}, b: function() {…} } } },
    
blort: {
    with(foo.bar.quux) {
        a();
        b();
        a(b(a()));
    }
    foo.bar.quux.a();
}

Thirdly, it’s easy to maintain. Encapsulation and a certain predictability, and the encouragement to make methods small and put them somewhere that makes sense rather than build e.g. sprawling validation methods that, oh, do a bit of browser sniffing as well, and a bit of alert() calling… this definitely forces me to be careful in what I write, and that puts me in a good position to fix things later on.

I can’t say I’ve done any serious testing, but this way of building functionality seems far more robust, and exits more gracefully (on most decent browsers), than other paradigms for Javascript design. It’s possible this is how the whole Javascript community is now coding and I’m teaching my grannies to suck eggs: certainly it’s not how you’d code given ten minutes on Google, so it probably bears repeating.

A few caveats, of course, because there is no silver bullet:

  • All function definitions go in MyObjectWithHandyName: nothing outside that apart from the onload to do any actual function calls.
  • Any text used more than once (URLs, HTML classes, alert text, repalcement text etc.) goes in p at the top of the script.
  • Any event handlers should be wary of what they get as their first parameter, and what the this object refers to: depending on how they get called, that might change from event to element to their hierarchical container in MyObjectWithHandyName.
  • Trailing commas: at the end of an associative array, don’t leave a trailing comma as Firefox will quietly ignore it but IE will give one of its typically opaque syntax errors.
  • Similarly, don’t omit commas between elements—{ a: {} b: {} } is wrong—as all browsers will die. Easily done, if you’re writing a new method and you forget the go() already exists.

Anyway, give it a go and see what you think.

Subscribe to RSS - debug