It is not possible to generalize and define any parameter boolean
is a problem. Whether it is a problem or not, it will vary from the objective, context or even size of the method/class that is receiving this boolean parameter. And to solve it, it will also depend on whether we are talking about a class or method receiving this parameter.
Simpler cases: few parameters
For example, if I want to popular an object Saldo
:
new Saldo("1.12", false);
The first parameter is the credit value and the second is a boolean indicating whether the incoming balance is blocked or not.
For a case like this, simple and straightforward, this boolean won’t give you headaches or confuse you in the use of the class.
Now let’s go to the method. Using your example, we would have a call from this method like this:
teste(objeto, false);
Just as with the class, there are few parameters and usually will not create confusion. Of course when we simply see a parameter false
, we have no indication of what that means outside the class and method. In these simple cases, a simple variable extraction can help:
new Saldo("1.12", isSaldoBloqueado);
teste(objeto, isEspecial);
Some languages also have named Parameters, which helps a lot in understanding the code and replacing this variable extraction technique. Other Ides, such as Java’s Intellij IDEA, by default display the name of the method’s internal boolean variables in its call (simulating a named Parameter), greatly facilitating the understanding of the code.
In simple cases like this, I end up being more practical instead of trying to break in several methods or classes the code just to try to get rid of Boolean. I’m not saying leaving like this is good practice, but I don’t want to be extreme enough to say that this should not exist at all in the code. But, undoubtedly, they are codes that deserve attention.
Let us leave this for the more complex cases explained below.
More complex cases: many parameters
When we have many parameters, the situation changes picture. Imagine the following class instantiation and call methods:
new Saldo("1,23", true, false, false);
teste(objeto, true, dataLimite, true, false);
Although it can extract some variables and improve the situation, the result is not always satisfactory. For having more boolean variables, the chances of getting confused are higher and, especially in the case of the method, we have a beginning of bad Smell: probably this method is doing too many things or the code internally is confused.
How to solve in objects?
In objects, it is usually simpler to solve. You have two options:
- Break into more classes, better distributing responsibilities
- Using a Pattern as Builder.
That is, for an object initially like this: new Saldo("1,23", true, false, false);
, we could refactor to have:
new Saldo("1,23", new Bloqueado(true, dataLimite), new Composto(false, false));
It can also use the presence of the object itself or not to compose the content of the object itself and using different constructors for this. In the example above, we could have two builders for Saldo, one of them accepting the Bloqueado
and the other not.
Alternative:
Saldo.builder
.valor("1,23")
.bloqueado(true)
.dataLimite(dataLimite)
.saldoComposto(false)
.saldoCompostoBloqueavel(true)
.build();
I don’t particularly like the Builder
if there is the possibility of refactoring to separate the information into more objects. With the Builder
, you can easily forget to set one of the above information and break your code without noticing.
Now, in the case of methods, things can get a little complicated.
How to solve in methods?
With the methods, we have more options, but not all look good. Let’s start with an example.
public String enviar (String mensagem, boolean erro) {
if (!erro)
service.enviarSucesso(mensagem);
else
service.enviarErro(mensagem);
}
This method has more than one responsibility. The call of the same would be:
enviar("mensagem", true);
Just want you don’t want to have this boolean
. To solve this case, you can pass the responsibility to whoever calls the method decide:
enviarErro("mensagem");
enviarSucesso("mensagem");
In this way, the methods will do only one thing (only responsibility). However, this can result only in condition transfer (change the if
class), depending on the code.
Another alternative, more OOP, could be:
Mensagem mensagem = new Sucesso("mensagem");
Mensagem mensagem = new Erro("mensagem");
Including, in case of use of object oriented classes, techniques as Decorator can delete several boolean parameters, as previously demonstrated in the example of Saldo
.
No . Net framework (mscorlib) only 1.89% of the functions made available (public) has a bulletin as the last argument. It doesn’t mean anything, but it may be indicative of how common this practice is used.
– Bruno Costa
@Brunocosta yes, I think you should use where you fit. But if you analyze new things just I think you tend to use a lot less. In fact there is a lot of case that is abusive.
– Maniero