Pergunta

Hoje um colega de trabalho sugeriu que eu refatorasse meu código para usar uma instrução de rótulo para controlar o fluxo através de dois loops for aninhados que eu havia criado.Nunca os usei antes porque pessoalmente acho que diminuem a legibilidade de um programa.Estou disposto a mudar de ideia sobre usá-los se o argumento for sólido o suficiente.Quais são as opiniões das pessoas sobre as declarações dos rótulos?

Foi útil?

Solução

Muitos algoritmos são expressos mais facilmente se você puder passar por dois loops (ou um loop contendo uma instrução switch).Não se sinta mal por isso.Por outro lado, pode indicar uma solução excessivamente complexa.Portanto, afaste-se e observe o problema.

Algumas pessoas preferem uma abordagem de “entrada única, saída única” para todos os loops.Isso quer dizer evitar completamente o break (e continue) e o retorno antecipado dos loops.Isso pode resultar em algum código duplicado.

O que eu evitaria fortemente fazer é introduzir variáveis ​​auxiliares.Ocultar o fluxo de controle dentro do estado aumenta a confusão.

Dividir loops rotulados em dois métodos pode ser difícil.As exceções provavelmente são muito pesadas.Experimente uma abordagem de entrada única e saída única.

Outras dicas

Os rótulos são como goto:Use-os com moderação e somente quando eles tornarem seu código mais rápido e mais importante, mais compreensível,

por exemplo, se você estiver em grandes loops com seis níveis de profundidade e encontrar uma condição que torne o resto do loop inútil para ser concluído, não faz sentido ter 6 alçapões extras em suas declarações de condição para sair do loop mais cedo.

Rótulos (e goto's) não são maus, só que às vezes as pessoas os usam de maneira ruim.Na maioria das vezes, estamos tentando escrever nosso código para que seja compreensível para você e para o próximo programador que aparecer.Torná-lo super rápido é uma preocupação secundária (tenha cuidado com a otimização prematura).

Quando rótulos (e gotos) são mal utilizados, eles tornam o código menos legível, o que causa tristeza para você e para o próximo desenvolvedor.O compilador não se importa.

Existem poucas ocasiões em que você precisa de rótulos e eles podem ser confusos porque raramente são usados.No entanto, se você precisar usar um, use um.

POR FALAR NISSO:isso compila e executa.

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}

Estou curioso para saber qual é a sua alternativa aos rótulos.Acho que isso vai se resumir ao argumento de "retornar o mais cedo possível" vs."use uma variável para armazenar o valor de retorno e retorne apenas no final."

Os rótulos são bastante padronizados quando você tem loops aninhados.A única maneira de realmente diminuir a legibilidade é quando outro desenvolvedor nunca os viu antes e não entende o que significam.

Nunca vi rótulos usados ​​"in the wild" no código Java.Se você realmente deseja quebrar loops aninhados, veja se consegue refatorar seu método para que uma instrução de retorno antecipada faça o que você deseja.

Tecnicamente, acho que não há muita diferença entre um retorno antecipado e um selo.Praticamente, porém, quase todo desenvolvedor Java viu um retorno antecipado e sabe o que faz.Eu acho que muitos desenvolvedores ficariam pelo menos surpresos com um rótulo e provavelmente ficariam confusos.

Aprendi a ortodoxia de entrada única/saída única na escola, mas desde então passei a apreciar as declarações de retorno antecipadas e a quebra de loops como uma forma de simplificar o código e torná-lo mais claro.

Eu argumentaria a favor deles em alguns locais. Achei-os particularmente úteis neste exemplo:


nextItem: for(CartItem item : user.getCart()) {

  nextCondition : for(PurchaseCondition cond : item.getConditions()) {
     if(!cond.check())
        continue nextItem;
     else
        continue nextCondition;

  }
  purchasedItems.add(item);
}

Acho que com o novo loop for-each, o rótulo pode ficar bem claro.

Por exemplo:

sentence: for(Sentence sentence: paragraph) {
  for(String word: sentence) {
    // do something
    if(isDone()) {
      continue sentence;
    }
  }
}

Acho que isso fica muito claro ao ter seu rótulo igual à sua variável no novo for-each.Na verdade, talvez Java devesse ser mau e adicionar rótulos implícitos para cada variável heh

Eu usei um loop rotulado Java para uma implementação de um método Sieve para encontrar números primos (feito para um dos problemas matemáticos do projeto Euler), o que o tornou 10x mais rápido em comparação com loops aninhados.Por exemplo, if(certa condição) volte para o loop externo.

private static void testByFactoring() {
    primes: for (int ctr = 0; ctr < m_toFactor.length; ctr++) {
        int toTest = m_toFactor[ctr];
        for (int ctr2 = 0; ctr2 < m_divisors.length; ctr2++) {
            // max (int) Math.sqrt(m_numberToTest) + 1 iterations
            if (toTest != m_divisors[ctr2]
                        && toTest % m_divisors[ctr2] == 0) {
                continue primes; 
            }
        } // end of the divisor loop
    } // end of primes loop
} // method

Perguntei a um programador C++ quão ruins são os loops rotulados, ele disse que os usaria com moderação, mas ocasionalmente podem ser úteis.Por exemplo, se você tiver 3 loops aninhados e, para certas condições, quiser voltar ao loop mais externo.

Então eles têm sua utilidade, depende do problema que você estava tentando resolver.

Eu nunca uso rótulos em meu código.Eu prefiro criar um guarda e inicializá-lo para nulo ou outro valor incomum.Essa guarda costuma ser um objeto de resultado.Não vi nenhum dos meus colegas de trabalho usando rótulos, nem encontrei nenhum em nosso repositório.Realmente depende do seu estilo de codificação.Na minha opinião, o uso de rótulos diminuiria a legibilidade, pois não é uma construção comum e geralmente não é usada em Java.

Sim, você deve evitar o uso de rótulos, a menos que haja um motivo específico para usá-los (o exemplo de simplificação da implementação de um algoritmo é pertinente).Nesse caso, eu recomendaria adicionar comentários suficientes ou outra documentação para explicar o raciocínio por trás disso, para que alguém não apareça mais tarde e o destrua com alguma noção de "melhorar o código" ou "livrar-se do cheiro do código" ou alguma outra desculpa potencialmente BS.

Eu igualaria esse tipo de questão a decidir quando se deve ou não usar o ternário if.A principal justificativa é que isso pode impedir a legibilidade e, a menos que o programador tenha muito cuidado ao nomear as coisas de maneira razoável, o uso de convenções como rótulos poderá piorar muito as coisas.Suponha que o exemplo usando 'nextCondition' e 'nextItem' tenha usado 'loop1' e 'loop2' para seus nomes de rótulos.

Pessoalmente, os rótulos são um daqueles recursos que não fazem muito sentido para mim, fora do Assembly ou do BASIC e outras linguagens igualmente limitadas.Java tem muitas construções de controle e loop mais convencionais/regulares.

Achei que os rótulos às vezes são úteis em testes, para separar a configuração usual, exercitar e verificar fases e agrupar instruções relacionadas.Por exemplo, usando a terminologia BDD:

@Test
public void should_Clear_Cached_Element() throws Exception {
    given: {
        elementStream = defaultStream();
        elementStream.readElement();
        Assume.assumeNotNull(elementStream.lastRead());
    }
    when:
        elementStream.clearLast();
    then:
        assertThat(elementStream.lastRead()).isEmpty();
}

Suas opções de formatação podem variar, mas a ideia central é que os rótulos, nesse caso, forneçam uma distinção perceptível entre as seções lógicas que compõem seu teste, melhor do que os comentários.Eu acho que o Spock A biblioteca apenas se baseia nesse recurso para declarar suas fases de teste.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top