Questão de estilo

Normalmente você gostaria de estruturar seus programas como:

fazalgumacoisa(); if (problema) { return; } fazoutracoisa(); if (outroproblema) { return; } fazaindaoutracoisa(); if (aindaoutroproblema) { return; } naoseimaisoquefazer(); while (esperandoasolucao) { fazqualquercoisa(); if (ohoh_problema) { return; } } tudobem();

O problema de fazer assim é que, embora isso seja bastante claro (é difícil deixar mais claro que isso), existem muitos lugares onde é proibido ter mais de um return dentro de uma rotina. (Bom, há gosto para tudo…)

Antigamente (no tempo que “goto” era só um sobrenome japonês, e você podia usar e abusar à vontade do GOTO) você podia escrever assim:

fazalgumacoisa(); if (problema) { goto trataerro; } fazoutracoisa(); if (outroproblema) { goto trataerro; } fazaindaoutracoisa(); if (aindaoutroproblema) { goto trataerro; } naoseimaisoquefazer(); while (esperandoasolucao) { fazqualquercoisa(); if (ohoh_problema) { goto trataerro; } } tudobem(); return; trataerro: tratamentodeerros();

Como goto não funciona no Java, então inventaram a lógica invertida, que é um “if” dentro do outro.
Eu chamo isso de “Programação 45 graus” ou “Programação em serra” porque você vê claramente triângulos ou “dentes de serra” no seu código.
Obviamente, como tudo que é invertido, é difícil de entender.
E é por isso que a complexidade ciclométrica (uma medida que aqueles engenheiros de software inventaram para te deixar com mais cabelos brancos, e basicamente mede quantos ifs e whiles você tem dentro de sua rotina) vai lá para cima.

fazalgumacoisa(); if (!problema) { fazoutracoisa(); if (!outroproblema) { fazaindaoutracoisa(); if (!aindaoutroproblema) { naoseimaisoquefazer(); while (esperandoasolucao) { fazqualquercoisa(); if (ohoh_problema) { break; } } if (!ohoh_problema) { tudobem(); } } } }

Goto não existe no Java, mas existem labels e o comando “break”. A única coisa invertida que
há é que o label é posto NO COMEÇO DO LOOP, não no fim do loop, que seria para onde o “break” iria.
O programa original ficaria como:

bloco1: do { fazalgumacoisa(); if (problema) { break bloco1; } fazoutracoisa(); if (outroproblema) { break bloco1; } fazaindaoutracoisa(); if (aindaoutroproblema) { break bloco1; } naoseimaisoquefazer(); while (esperandoasolucao) { fazqualquercoisa(); if (ohoh_problema) { break bloco1; } } tudobem(); } while (false);

A complexidade ciclométrica cai (para o PMD ou Checkstyle, não sei qual dos pacotes, isso é apenas um if dentro de um loop), e é bastante fácil entender isso se explicar o que é “break label;” e “do { } while (false);” que são dois truques da linguagem.
Só não sei se o PMD ou o Checkstyle vão chiar com o “break label;” que realmente não é muito usado.

P.S. Ora, tudo que falei daria para resolver fazendo um monte de “throw new XXXException” e “catch (XXXException ex)”. Mas isso nem sempre é desejável (por problemas de desempenho, e porque Exceptions são condições excepcionais, não formas de modificar o fluxo de seu programa.)

P.S. 2 - Acho que me expressei mal - é que em muitos lugares (fábricas de software, etc.) há alguns padrões de estilo a serem seguidos; um deles é o que desestimula aos programadores o uso de múltiplos RETURNS em um mesmo método.

Isso é um post ou um artigo?

Aproveitando, o que está errado com este código?

fazalgumacoisa();
if (problema) {
    return;
}
fazoutracoisa();
if (outroproblema) {
    return;
}
fazaindaoutracoisa();
if (aindaoutroproblema) {
    return;
}
naoseimaisoquefazer();
while (esperandoasolucao) {
    fazqualquercoisa();
    if (ohoh_problema) {
        return;
    }
}
tudobem();

Bom parece que nao tem nada de errado! O thingol apenas disse que em alguns casos não se pode ter mais de um return dentro de uma rotina. É como se fosse uma regra. Será que é isso mesmo… :roll: hehehehe

se não aparecer uma colução tu pode ficar em loop infinito :smiley:

isto não é muito bom

Num entendi nada :oops: Brincadeira :slight_smile:

Interessante.

Pois eh. Eu tambem acho mais claro a opcao de ir dando return conforme as condicoes forem acontecendo - fica mais claro pra ler/entender o software (IMHO).

[code]- parametro eh nulo, return.

  • string esta vazia, return.
  • condicao excepcional, return.
  • outra excecao, return.
  • pronto, agora vamos com o codigo principal
  • return[/code]

Porem, existe essa tal “regra do unico return”. Uma maneira que vejo de se fazer isso sem ser com infinitos ifs encadeados ou jogando excecoes, eh ter variaveis de controle e varios ifs simples (nao eh menos porco):

[code]- parametro eh nulo, erro = true

  • if !erro e string esta vazia, erro = true
  • if !erro e condicao excepcional, erro = true
  • if !erro e outra excecao, erro = true
  • if !erro vamos com o codigo principal
  • return[/code]

Nao sei. Continuo achando returns multiplos uteis para deixar o codigo limpo e facilitar o fluxo na leitura (conforme as coisas vao acontecendo ja vou eliminando certas condicoes no meu cerebro, nao preciso manter tudo em mente ate o ultimo return).

Enfim, acho que vou desabilitar essa regra no meu PMD. :mrgreen:

Marcio Kuchma

questao de estilo ainda prefiro fazer uma instrução de outro modo…

if (x==0)
{
  if (x>5)
  {
      //
   }
   else
   {
       //
    }
}

mas como o thingol disse ‘questão de estilo’ :smiley:

Códigos dignos de um Daily WTF!

(não sei porque goto’s me dão náuseas!)