Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid boolean flags as an attribute

First of all I wanna say I don't have much experience in refactoring and don't know if this is off-topic.

I'm working with given code where a lot of boolean attributes are used, which I would like to avoid because of readability, and I don't know how to handle it in a proper way.

class MyClass(){
    boolean a;
    ...
    void function(){
        ...
        a = true;
        ...
    }

    void anotherFunction(){
        ...
        if(a == true){
            //do something
        } else {
            //do something else
        }
        ...
    }
    ...
}

The boolean a is used in multiple functions like this, where anotherFunctions are running the code regarding to a. This is tough to understand the code and the dependencies and furthermore hard for me to refactor it, because of the use of multiple attributes and local variables in anotherFunction. The effort to refactor this could be very high imo.

I always tried to avoid the use of a boolean like this, because in my eyes its not good practice. If I'm wrong don't hesitate to correct me.

Now I would like to know if I should refactor the code and spend the effort? Is there some kind of pattern which could be used in this case?

like image 437
Steve Benett Avatar asked Dec 09 '22 15:12

Steve Benett


1 Answers

You could use the state pattern. Encapsulate the state and behavior depending on the boolean variable in a separate abstract State class. When the boolean is set to false, change the state to an instance of FalseState (which extends State), and delegate to this FalseState instance. When the boolean is set to true, change the state to an instance of TrueState, and delegate to this TrueState instance.

For example, the following class

public class Apple {

    private boolean fresh = false;

    public String getColor() {
        if (fresh) {
            return "green";
        }
        else {
            return "brown";
        }
    }

    public void setFresh(boolean fresh) {
        this.fresh = fresh;
    }
}

could be refactored to

public class Apple {

    private AppleState state = new OldAppleState();

    public String getColor() {
        return state.getColor();
    }

    public void setFresh(boolean fresh) {
        this.state = state.nextState(fresh);
    }

    private static abstract class State {
        public abstract State nextState(boolean fresh);
        public abstract String getColor();
    }

    private static class OldAppleState extends State{
        public State nextState(boolean fresh) {
            return fresh ? new FreshAppleState() : this;
        }
        public String getColor() {
            return "brown";
        }
    }


    private static class FreshAppleState extends State{
        public State nextState(boolean fresh) {
            return fresh ? this : new OldAppleState();
        }
        public String getColor() {
            return "green";
        }
    }
}

I used inner classes, but you could of course use top-level classes.

like image 156
JB Nizet Avatar answered Dec 11 '22 08:12

JB Nizet