A debugging case study.

The thing about software development is that there's an inherent conflict in it. In order to get the functionality we've come to expect these days, a program has to be fairly complicated. On the other hand, in order to keep an intellectual handle on the system, developers need to make it as simple as possible. Otherwise, you're liable to lose your grip on the system and end up staring a a screen full of code that is obviously correct, yet is nonetheless not working as expected.

I had one of those moments today. I was trying to add some caching to LnBlog's plugin system. I started off by adding some caching code to the recent entries plugin (look to the left - it's the 5th panel down in the sidebar). But then I thought better of it and decided I'd save myself some work by sharing the code through the base Plugin class. That way, all the plugins could use it without having to copy it over and over again. Perfect! However, when I tested it out, I noticed that section header for the calendar plugin had mysteriously disappeared. And yet, I hadn't even touched the calendar plugin. What was going on?

And so, my search began. The process went something like this.

Step 1: Check the new code

The first step is always to check the new code. If something changed and then something broke, then whatever changed is the most obvious culprit. In this case, the new code included a new sidebar output event handler for the recent entries plugin and switching back to the old handler eliminated the bug. However, I didn't see anything looked obviously wrong with the new code. To make matters even stranger, I discovered that I could eliminate the bug by using an event handler with the same signature as the old version, but which merely called the new one in its body. Say what?

Step 2: Check the calling code

The next place to look is one step back in the code. In this case, I looked at the event registry. When the sidebar output event is raised, the event registry handles calling the event handlers. This was also suspect, because I had recenty added data parameters to the event handlers. However, there didn't appear to be anything wrong here either.

Step 3: Check the affected code

Normally, this would come sooner, but my next step was to look at the calendar plugin. Since I hadn't actually changed anyting in this plugin, my assumption was that the problem must be an interaction with some of the new code. Since that wasn't panning out, it was time to try something else.

Step 4: Pulling it all together

As I was looking at the calendar code, it all became clear. The sidebar output event handler takes an optional parameter which can be set to turn off the display of the section heading and container DIV element (for AJAX calls). This parameter is called $nodiv and the default value is false. The eevent register now takes a data parameter. Somehow, a data parameter is getting passed on to the calendar plugin. So the problem was that data was inadvertently getting passed on to the calendar.

I went back to the event register code and looked at the data parameter code. The same parameter gets passed to every event handler. Back over to the new recent entries plugin. It takes an optional parameter, passed by reference, with a defalut value of false. However, when the handler got the value[bfalse[/b], it reassigned that parameter to an object for the current blog.

And there it was. I was assigning a value an optional reference parameter. (Which I only had to do because PHP doesn't do function overloading.) That change was then propogated to other event handlers. Since the calendar event handler depended on getting false as its parameter value, it didn't function as expected.

On the up side, it was a nice, easy, one-line fix. Isn't that always the way? Tracking down the bug always seems to take ten times as long as fixing it.

You can reply to this entry by leaving a comment below. This entry accepts Pingbacks from other blogs. You can follow comments on this entry by subscribing to the RSS feed.

Add your comments #

A comment body is required. No HTML code allowed. URLs starting with http:// or ftp:// will be automatically converted to hyperlinks.