Funky Bugz: The Short-Circuit

I think this is a pretty common programming pattern:

boolean updated = false;
for (MyUpdater updater : MyUpdatersList) {
    updated = updated || updater.update(someData);
}

if (updated) {
    performPostUpdateTask(someData);
}

Obviously, this code is supposed to loop over my list of updaters (forgive my unimaginative names), give each one of them the opportunity to update the data, and do something only if at least one of them has actually modified it.

Alas! Most programming languages (Java included), will short-circuit this line, effectively preventing all the updaters after the first one from being called.

This is especially dangerous if you are writing code for future extension, and you plan for other people to add updaters later. You will probably test this loop with one updater: the one you currently need, and conclude it is working fine. The coders that will maintain this code in the future will have a blast trying to figure out what went wrong after they relied on your design!

Good thing I stepped through the code and wondered how come I cannot step into these methods!

Advertisements

5 thoughts on “Funky Bugz: The Short-Circuit”

  1. I use short-circuits wherever they are useful, as long as the code remains readable. In the example you gave, it is very clear from the code that updating should stop after the first successful update, even though iteration continues. If this was not the intention of the coder, well, it is certainly not the short-circuit’s fault!

    1. I use it too, it’s not the point. This is not an anti-short circuit article, I just found it funny.

      And clearly, since these bugs happen and happen quite a lot, it is not that obvious on first sight. In this example, had the intention been to stop the updating after the first update, I would expect the coder to state it explicitly in the loop condition, and not iterate over all the objects needlessly.

  2. Well, there are a few ways to look at this:
    1. This may in fact represent the desired behavior – not very readable and not optimized, but still. Lets assume its not.

    2. We can re-write the updating line correctly:
    * update = updater.update(someData) || update;
    * update |= updater.update(someData); // Yes, I know not all the languages support this operator
    * if (updater.update(someData)) update = TRUE; // Check you understand why this works! How optimized do you think this is (compared to the alternatives)?

    3. There is a serious problem of trying to do too much in a single line(*). If it was spread over two lines, like this:
    * updateResult = updater.update(someData);
    * update = update || updateResult;
    There would be no problem. First we run the current updater, then update the value of “update”. Simple, more readable, it will make it easier to print out the return value (for, say, debugging?) and all at the price of adding a single variable. Which the compiler (assuming it’s a decent one) will optimize away. The lesson here is to trust the compiler (at least for the low-level stuff, unless you are some super-expert). The compiler is smarter than you, the compiler is better than you, the compiler loves you and takes care of you. So long as you aren’t being smart-ass.

    (*) I should note that I talk the talk but I don’t walk the walk. It was known to be that I wrote whole functions (and complicated ones) in a single line! Hi if you don’t understand me code- DON’T MESS WITH IT!

      1. I think this is the first time somebody LOLed something I said about code. The usual responses to me code are more along the lines of shock, horror, despair and/or the urge to gauge your own eyes out.
        So… Thanks!

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