1

I wasn't sure exactly what to call these situations, so I'll illustrate it.

If I have something like this in a method:

if (i <= 5) 
    doSomething();
else 
    doSomethingElse();

but I know that i will never be less than or equal to 5 once it exceeds 5, it becomes unnecessary to continue checking the if-statement once it branches off the first time.

Is it a good idea to implement a strategy pattern in this case, to avoid redundant checks?

class strategy1 implements strategy {

    Object obj; // stores a reference to the object that uses it

    void run() {
       if (i <= 5)
            doSomething();
        else {
            obj.strategy = new strategy2(obj);
            obj.strategy.run();
        }
    }
}

class strategy2 implements strategy {

    void run() {
        doSomethingElse();
    }

}

and the object simply calls strategy.run()

I feel like this sacrifices some readability and simplicity for performance, but it also makes it clear that i will not fall below 6 once it hits 6, which provides some more information than the if-statement alone did. Is there a better way?

3
  • 6
    I will point out that many systems that have some form of branch prediction will switch to the 'assume the else' rather quickly. Other times, the compiler may be able to detect it via static analysis. See Why is processing a sorted array faster than an unsorted array? Furthermore, until performance is an issue and you've identified this test as a hot spot - don't worry about it. Developer time is more important.
    – user40980
    Jul 22, 2015 at 18:39
  • 5
    What makes you think this is automatically more performant than just passing over the if statement a few times. Have you tested this to determine that it actually is? Do you iterate often enough to matter even if it does? Does shaving a few microseconds off your execution even matter? I'm guessing the answer to all of those is 'no'. Jul 22, 2015 at 18:40
  • ...see also: Replace Type Code with Class...
    – gnat
    Jul 22, 2015 at 19:17

3 Answers 3

6

What you are proposing looks like a Replace Type Code [or a conditional] with State/Strategy refactoring.

Possible reasons for doing it:

  1. Conditionals have become complex, or are anticipated to become complex in the future.
  2. The conditionals incur delays or tax resources.

Reasons for not doing it:

  1. The conditionals are simple at the present, and the conditionals are not expected to become complicated in the future.
  2. Evaluating the conditionals does not incur appreciable delays, and does not tax other resources.

At the present, the conditional i < 5 fits both reasons for not doing this refactoring.

p.s. I think what you are describing is a kind of a state pattern rather than stategy pattern. Having said that, state and strategy patterns have similar inner workings. Just picking at terminology.

1
  • you're right, it seems that I described a textbook state pattern example!
    – Ryan
    Jul 22, 2015 at 18:40
3

The simplest code doing the job is the best.

The first version just works. And it is very simple: All it has to do is to evaluate which of two functions to call, and then to call the right one. Little chance of error. Trivial to change if the determination what to call changes.

Now you are making things complicated. You assume that once the second function has been called, the condition will never be such that the first function should be called again. That's a big assumption, and "never" is a very long time. How much will you kick yourself if it turns out that i can be reset to 1, and your code breaks, and the only way to fix it is to remove your clever code and reintroduce the simple check? How much will I want to kick you if your clever code leads to this bug, and it's my job to fix it?

0

I will approach it from different side of things - in this case you will get the advantage of branch prediction. If you say you have a sorted sequence, this should be ideal in your case.

The idea is your original if statement will be extremely fast before the crossover and shortly after. So, chances are it will be faster than actually having logic around it.

The way branch prediction works, is your processor would try to guess the outcome of the statement base don the past outcomes and preload the following statements accordingly. If you sequence is sorted, your processor would be correct 99.9999% of the time except a couple times after the crossover, which actually gains you speed.

Not the answer you're looking for? Browse other questions tagged or ask your own question.