Questão de estilo

7 respostas
T

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.

7 Respostas

dsiviotti

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();
E

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

urubatan

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

isto não é muito bom

kartler

Num entendi nada :oops: Brincadeira :slight_smile:

Interessante.

kuchma
"thingol":
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...)

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).

- parametro eh nulo, return.
- string esta vazia, return.
- condicao excepcional, return.
- outra excecao, return.
- pronto, agora vamos com o codigo principal
- return

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):

- 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

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

keller

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:

Daniel_Quirino_Olive

Códigos dignos de um Daily WTF!

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

Criado 7 de outubro de 2004
Ultima resposta 10 de out. de 2004
Respostas 7
Participantes 8