Is the keeping of several booleans as state variables a bad programming practice?

282 views Asked by At

Suppose we have a complex class that interfaces with several different other objects, and these interactions depend on the states of one another.

Immediately I would attempt to use several state booleans to try and keep track of these states, but this often leads to messy code filled with IF statements.

Are there settled solutions or design patterns to handle this while minimizing the messiness?

As an example, consider something like this:

int Foo(int A, int B, inc C)
{
    if(_state1 && !_state2)
        return A+B;

    else if(_state1 && _state2 && _state3)
        return A+C;

    else if(!_state1 && (_state4 || _state5)
        return C;    
    ...
}    

It's easy to see how something like this would run out of control very quickly

1

There are 1 answers

0
Cel Skeggs On

Likely, one of the better ways to implement this would be with a state machine, depending on details that weren't provided. (I'm going to give my example in Java because that's what I'm familiar with and you didn't specify; however, it should be applicable to most OO languages.)

You'd want an enumeration, a state variable, and to use a switch statement to choose.

So, you'd want an enum:

public static enum ExampleState {
    // You would want explanatory names in a real program.
    INITIAL_STATE, SOME_STATE, OTHER_STATE
}

And then, on your complex class:

private ExampleState state = ExampleState.INITIAL_STATE;

public int foo(int a, int b, int c) {
    switch (state) {
    case INITIAL_STATE: return a + b;
    case SOME_STATE: return a + c;
    case OTHER_STATE: return c;
    default: throw new IllegalStateException("Unexpected state " + state);
    }
}

For a normal state machine, you'd also want methods like

public void changeStateInSomeSpecificWay() {
    switch (state) {
    case INITIAL_STATE:
        someAction();
        state = SOME_STATE;
        break;
    case SOME_STATE:
        someOtherAction();
        state = INITIAL_STATE;
        break;
    case OTHER_STATE:
        someThirdAction();
        state = INITIAL_STATE;
        break;
    default:
        throw new IllegalStateException("Unexpected state " + state);
    }
}