Guards: Isn't it true the we can replace them if “if” - “else if” - “else” without any significant drawbacks? [closed]

softwareengineering.stackexchange https://softwareengineering.stackexchange.com/questions/416258

  •  16-03-2021
  •  | 
  •  

Pergunta

There are a lot of examples over Internet that show why you should use guards.

For example:

public double getPayAmount() {
  if (isDead){
    return deadAmount();
  }
  if (isSeparated){
    return separatedAmount();
  }
  if (isRetired){
    return retiredAmount();
  }
  return normalPayAmount();
}

The author compares the above version with

public double getPayAmount() {
  double result;
  if (isDead){
    result = deadAmount();
  }
  else {
    if (isSeparated){
      result = separatedAmount();
    }
    else {
      if (isRetired){
        result = retiredAmount();
      }
      else{
        result = normalPayAmount();
      }
    }
  }
  return result;
}

... and of course, the first one looks better.

But the author (all of the authors) ignores the fact that the first version can be changed to

public double getPayAmount() {
  if (isDead){
    return deadAmount();
  }
  else if (isSeparated){
    return separatedAmount();
  }
  else if (isRetired){
    return retiredAmount();
  }
  else {
    return normalPayAmount();
  }
}

which is not that ugly (compared to the second one).

And it makes me wonder whether guards are really so useful as authors trying to convince me. Could you show the case where guards are really make the code much better?

Foi útil?

Solução 2

Here is an example from Implementation Patterns book by Kent Beck:

// version without guards
void compute() {
  Server server= getServer();
  if (server != null) {
    Client client= server.getClient();
    if (client != null) {
      Request current= client.getRequest();
      if (current != null)
        processRequest(current);
    }
  }
}
// version with guards
void compute() {
  Server server= getServer();
  if (server == null)
    return;
  Client client= server.getClient();
  if (client == null)
    return;
  Request current= client.getRequest();
  if (current == null)
    return;
  processRequest(current);
}

It seems this is exactly what I searched for. There are only 2 ways to write this function and the second one (i.e., with guards) is really better.

Outras dicas

And it makes me wonder whether guards are really so useful as authors trying to convince me. Could you show the case where guards are really make the code much better?

Your example is biased because it uses return inside the if bodies, forcing the method to end when it enters an if. This pretty much excludes the relevance of any code after the else of any if statement that evaluates to true.

If you don't use return, then if .. if .. and if .. else if .. else behave very differently.

public double getPayAmount() {
  var result = 0;

  if (isDead){
    result += 100;
  }
  else if (isSeparated){
    result += 50;
  }
  else if (isRetired){
    result + = 25;
  }

  return result;
}

Assuming all booleans are true, without the else it'd return 175, with the else it'd return 100.


But the author (all of the authors) ignores the fact that the first version can be changed to

Sure, you could use it, but that doesn't mean that it must be mentioned. When you use returning if bodies, the else is irrelevant. There's no point to having it.

Using simple step through debugging is going to explain it much better than a written answer will.

The short answer here is that for any if which returns in its body, the else can be removed without changing the flow of the code, therefore makking it irrelevant to write an else.

Licenciado em: CC-BY-SA com atribuição
scroll top