I know there are some questions about boolean flags: Is it wrong to use a boolean parameter to determine behavior?, Multiple boolean arguments - why is it bad? which indicates the following code is bad:
public void myMethod(boolean b){
doThis();
if(b){
doThat();
}
}
myMethod(true);
and should be refactored as:
public void myFalseMethod(){
doThis();
}
public void myTrueMethod(){
doThis();
doThat();
}
myTrueMethod();
which eliminates the if-else with that boolean. However, the solutions seems works for hardcoded boolean parameters only, what if the original boolean value is not hardcoded, but loaded from some dynamic load data? eg:
boolean b=this.userData.isValid && this.checkbox.selected;
myMethod(b);
I found it is almost unavoidable to "use boolean to determine behavior", what I tried to refactor:
Refactor method 1: separate 2 functions:
boolean b=this.userData.isValid && this.checkbox.selected;
if(b){
myTrueMethod();
}else{
myFalseMethod();
}
Which I think it is not better than the boolean flag version because it is still "use boolean to determine behaviour". Also it requires me to repeat the if-else if there are other places that call myMethod(b), which seems violating DRY principle.
Refactor method 2 : introduce parameter object:
public class MyMethodParameterObject{
public boolean b;
}
public void myMethod(MyMethodParameterObject obj){
doThis();
if(obj.b){
doThat();
}
}
MyMethodParameterObject obj=new MyMethodParameterObject();
obj.b=this.userData.isValid && this.checkbox.selected;
myMethod(obj);
I don't understand why it would be better than the original one because the if-else still exists, but have more codes, seems more complex.
Refactor 3 : Polymorphism
public interface IMyClass(){
public void run();
}
public class MyFalseClass implements IMyClass{
public void run(){
doThis();
}
}
public class MyTrueClass implements IMyClass{
public void run(){
doThis();
doThat();
}
}
boolean b=this.userData.isValid && this.checkbox.selected;
IMyClass myClass=null;
if(b){
myClass=new MyTrueClass();
}else{
myClass=new MyFalseClass();
}
myClass.run();
Polymorphism makes the good uses of virtual table, which selected the required implementation automatically. But in this case, I still need a if-else to convert the boolean value to corresponding implementation, which I think it is more complex and unnecessary, why don't I use boolean flag directly?
Refactor 4 : use reflection:
public class MyClass{
public void myMethod_false(){
doThis();
}
public void myMethod_true(){
doThis();
doThat();
}
}
boolean b=this.userData.isValid && this.checkbox.selected;
Method m=null;
try{
method=myClass.getClass.getMethod("myMethod_"+b);
.
.
.
}catch(Exception e){
}
It truly eliminates the if else, avoiding "use boolean to determine behaviour", but I think it is harder to maintain, besides having more code, I may type the method name wrongly in the string. Also it is harder to find which method is actually called.
So I think if the boolean is from dynamic data, using boolean flag is the simplest solution. Is it true? if not, what am I missed about "refactoring boolean parameter"? Is there any solutions to refactor "dynamic boolean parameter" in better way?