4 de ago. de 2013

Return Early: um opção para simplificar expressões condicionais

Há uma grande polêmica sobre ter ou não vários returns em um método. Alguns defendem que deve haver apenas um retorno. Outros defendem que deve-se retornar assim que houver um valor a devolver.

Enfim, este artigo aplica a segunda técnica, onde retornamos o mais cedo possível. Esta técnica é conhecida como:

RETURN EARLY

Dar um retorno cedo ajuda a descomplicar expressões condicionais. Bem, tudo fica melhor com um exemplo não é? Considere uma classe Seguranca, usada para computar o Nivel de Acesso de um dado Usuario. Veja a seguir:

public class Seguranca {
 
 public enum NivelAcesso {
  Nenhum, Visitante, Operador, Administrador;
 }

 public static NivelAcesso privilegio(Usuario usuario) {
  NivelAcesso nivel = null;

  if (!usuario.isBloqueado()) {
   if (usuario.getCargo() != null) {
    if (usuario.getCargo() == Usuario.Cargo.Gerente) {
     nivel = NivelAcesso.Administrador;
    } else if (usuario.getCargo() == Usuario.Cargo.Funcionario) {
     nivel = NivelAcesso.Operador;
    }
   } else {
    nivel = NivelAcesso.Visitante;
   }
  } else {
   nivel = NivelAcesso.Nenhum;
  }

  return nivel;  
 }
 // ... 

Esta implementação aplica um único ponto de saída, um único retorno no fim do método. Isto é bom, por um lado, pois facilita acompanhar o fluxo da lógica, e ruim por outro, pois começa a aninhar as expressões condicionais.

A seguir uma implementação alternativa, uma refatoração, onde é usado o return early:

public class Seguranca {
 
 public enum NivelAcesso {
  Nenhum, Visitante, Operador, Administrador;
 }

 public static NivelAcesso privilegio2(Usuario usuario) {

  if (usuario.isBloqueado()) {
   return NivelAcesso.Nenhum;
  }

  if (usuario.getCargo() == Usuario.Cargo.Gerente) {
   return NivelAcesso.Administrador;
  }

  if (usuario.getCargo() == Usuario.Cargo.Funcionario) {
   return NivelAcesso.Operador;
  }

  return NivelAcesso.Visitante;
 }

 // ... 

A mecânica do return early é simples: usar as regras mais restritivas antes, por exemplo, no caso de usuário estar bloqueado já não é necessário checar cargo e demais condições. A regra geral fica no fim, ou seja, no exemplo, se não está bloqueado e não há cargo definido então é visitante.

Para finalizar, esta técnica é independente de linguagem, mesmo que os exemplos estejam escritos em Java.

Código fonte disponível aqui: https://github.com/marciojrtorres/livro-aps/tree/master/return_early

Nenhum comentário: