What is good practice when casting an exception within if?

Asked

Viewed 3,196 times

27

What is the best practice in this case, use the Else even knowing that the if will or will not make an exception?

option 1 (with Else):

if (condicao){
  throw new RuntimeException("Mensagem");
}else{
  System.out.println("Não deu exception");
}

option 2 (without Else):

if (condicao){
  throw new RuntimeException("Mensagem");
}
System.out.println("Não deu exception");
  • 2

    Only by "decompiling" the bytecode to find out... I believe that both forms are equivalent, so that a criterion to choose between one and the other would be subjective and/or would vary case by case.

  • That question would be better on Codereview.

  • 1

    @karlphillip probably if we ever have a codereview in pt, it will be migrated.

  • 1

    @Bacco In other words, what are you suggesting is that pt.SO presents questions that would be appropriate for Code Review, Programmers, Signal Processing, Superuser, Serverfault, Webmasters and Game Development just because there is no dedicated forum for each theme in Portuguese? This is gonna be a huge mess...

  • 1

    @karlphillip But I didn’t suggest anything! : ). As for this discussion, it was very extensive both in the goal and in area 51, I suggest a look at both, in particular http://meta.answall.com/questions/aqui-no-o-stackoverflow-com. In summary, here the limits are wider, but some issues really off topic have already been closed up. Anyway the community is still looking for their point of balance, and you can certainly contribute to the goal ( http://meta.answall.com ) with your opinion, which is the best way forward.

  • 1

    @Bacco Thank you very Much, Sir. ;)

  • Just a suggestion, if you’re pitching IllegalArgumentException and similar, it is worth using a library of preconditions like the Preconditions of the Guava or Validate from Apache Commons. These libraries remove the need for if and make code much more readable.

Show 2 more comments

4 answers

14


Although this is prone to a strong sense of personal opinion, I believe that best practice is nay block the else.

The reasons are as follows::

Readability of the code

Adding nested blocks, although in this small example will not cause a big impact, will only make it harder to read the code and make it more complex.

In practice, this can lead to situations with multiple levels of validation, as I’ve seen sometimes in systems out there:

if (condicao1){
    throw new RuntimeException("Mensagem 1");
}else{
    System.out.println("Não deu exception 1");
    if (condicao1){
        throw new RuntimeException("Mensagem 2");
    }else{
        System.out.println("Ainda não deu exception 2");
        if (condicao1){
            throw new RuntimeException("Mensagem 3");
        }else{
            System.out.println("Ainda não deu exception 3");
        }
    }
}

For those who think I’m exaggerating, it wasn’t once or twice that I saw methods with validations of 5, 6 or more levels in financial systems methods with somewhat complex business rules.

It’s not necessary

A condition that includes an exception release, or other instruction that will interrupt the execution of the method does not need this type of construction. Unnecessary code is a waste of time.

It is better to separate the initial validations

The initial validations of a method do not need and probably should not influence the main logic of the method.

public int meuMetodo(String parametro) {

    if (parametro == null || parametro.isEmpty()) 
        throw new IllegalArgumentException("Parâmetro não informado!");

    //lógica aqui
    return 123;

}
  • It is not good practice to leave an if without {}. Even in the book Java Coding Guidelines can lead to security problems.

  • 5

    Matter of coding style! Is perfectly acceptable nay use keys when the if must execute only one command, and the coding style of the person requires her to skip a line right after the instructions of the if, as was the case of the above example.

  • @uaiHebert I agree, I don’t usually do this. To tell you the truth I didn’t even notice while typing. In Java this can lead us, for example, to think that indentation will put two commands inside the if. The problem is that I’m studying Python, so you’ve seen... : S

12

From the performance point of view, there is no reason to choose between one and the other, the difference should be negligible. Although the representation of the two forms in the bytecode be different, the performance will be very similar, with a difference of a few cycles at most (in contrast, a miss cache L1 "wastes" 10-40 cycles, L2 more than 600).

From the point of view of readability, I believe it will depend on the semantics of your program. If the condition if refers to an exceptional case, I believe that the ideal is to omit the else:

if ( denominador == 0 )
    throw new RuntimeException("Não pode dividir por zero");
quociente = numerador / denominador;

On the other hand, if the condition if is part of a mutually exclusive set, so I think it would be interesting to include the else (or maybe even a else if):

if ( x < 10 )
    return foo(x);
else if ( 10 <= x && x <= 20 )
    throw new RuntimeException("x não pode estar dentro do intervalo");
else if ( 20 < x )
    return bar(x);
// else
//     throw new RuntimeException("Isso nunca deve acontecer");
  • It is not good practice to leave an if without {}. Even in the book Java Coding Guidelines can lead to security problems.

  • 1

    @uaiHebert I prefer to let each choose their own coding style. Personally, I dislike this syntax, but if the Java community has this as a consensus (I wouldn’t know, because I haven’t worked with this language for years) feel free to edit my example code.

  • @Bacco I usually work with Python, which does not have { } and uses edentation to define blocks. If I were programming in Java today, I would probably forget that { } exists (in the same way that I usually forget to put ; at the end of the instructions) and would create a if with multiple instructions. The problem is: only the first will be inside the if, others will be out. This is a common mistake, and many people suggest never omit the { } because of this (agree or not another story). That’s one reason, although I don’t know what uaiHibert refers to when it says "security problems".

  • 1

    @mgibsonbr even understand what you said, and even I sometimes distract when I mix for example, Harbour and C in the same source, and forget the ";" in part C. Now, to say that using if without {} is not good practice already sounds a little prepotent. It’s like using OOP or not. There is no better, who knows how to use both uses in the right place and the right way, as the language allows, and it is good.

7

Your if is a "Guard clause": a clause that, if true, prevents the execution of the rest of the method code (or a loop). Guard clauses always contain "jump" code, such as return, throw, break or continue. They serve as preconditions for execution of certain code blocks.

My personal opinion is that these clauses do not need to else, since the code will "jump" out anyway:

if (condicao) throw new RuntimeException("Oops");

.... resto do código

Imagine a method with many preconditions, using else would make the code more illegible.

Note that I also do the following for "Guard Clauses":

  • I leave the code of if and "jump" on the same line
  • do not use a block delimited with {}

See a answer to a similar question I did in the O.R..

In Martin Fowler’s classic book Refactoring, there is a refactoring to transform from nested conditionals to Guard clauses.

5

In my opinion, let alone context better. In general, a different context is started with { and finalized with }, and from the point of view of those who read the code, it amounts to things from the past that must be remembered so that the code can be understood.

For example:

public int metodo(int parametro) {
    if (parametero < 0) {
        throw new IllegalArgumentException();
    } else {
        // Estamos no contexto do else que está dentro do contexto do método.
        // Ou seja, você tem que ter estes dois contextos em mente.
        return 42 + parametro;
    }
}

Already here:

public int metodo(int parametro) {
    if (parametero < 0) {
        throw new IllegalArgumentException();
    }

    // Estamos no contexto do método, fora de qualquer if ou else.
    return 42 + parametro;
}

This becomes quite evident in codes like this:

public boolean validaCPF(String cpf) {
    if (cpf == null || cpf.length() != 11) {
        return false;
    } else {
        int a = 0, b = 0;
        for (int i = 0; i < 9; i++) {
            int c = cpf.charAt(i) - '0';
            if (c < 0 || c > 9) {
                return false;
            } else {
                a += c * (i + 1);
                b += c * (9 - i);
            }
        }
        a = (a % 11) % 10;
        b = (b % 11) % 10;
        if (cpf.charAt(9) - '0' == a && cpf.charAt(10) - '0' == b) {
            return true;
        } else {
            return false;
        }
    }
}

It’s much better this way:

public boolean validaCPF(String cpf) {
    if (cpf == null || cpf.length() != 11) return false;

    int a = 0, b = 0;
    for (int i = 0; i < 9; i++) {
        int c = cpf.charAt(i) - '0';
        if (c < 0 || c > 9) return false;
        a += c * (i + 1);
        b += c * (9 - i);
    }
    a = (a % 11) % 10;
    b = (b % 11) % 10;
    return cpf.charAt(9) - '0' == a && cpf.charAt(10) - '0' == b;
}

This demonstrates that if Else can be avoided, the code gets cleaner.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.