Domanda

Oggi un collega mi ha suggerito di rifattorizzare il mio codice per utilizzare un'istruzione label per controllare il flusso attraverso 2 cicli for nidificati che avevo creato.Non li ho mai usati prima perché personalmente penso che diminuiscano la leggibilità di un programma.Sono comunque disposto a cambiare idea sul loro utilizzo se l'argomentazione è sufficientemente solida.Quali sono le opinioni delle persone sulle dichiarazioni delle etichette?

È stato utile?

Soluzione

Molti algoritmi vengono espressi più facilmente se è possibile saltare attraverso due cicli (o un ciclo contenente un'istruzione switch).Non sentirti male per questo.D’altro canto, potrebbe indicare una soluzione eccessivamente complessa.Quindi stai indietro e guarda il problema.

Alcune persone preferiscono un approccio "ingresso singolo, uscita singola" a tutti i cicli.Vale a dire evitare del tutto l'interruzione (e la continuazione) e il ritorno anticipato dei cicli.Ciò potrebbe comportare la creazione di codice duplicato.

Ciò che eviterei fortemente di fare è introdurre variabili ausiliarie.Nascondere il flusso di controllo all’interno dello stato aumenta la confusione.

Dividere i cicli etichettati in due metodi potrebbe essere difficile.Le eccezioni probabilmente sono troppo pesanti.Prova un approccio a ingresso singolo e uscita singola.

Altri suggerimenti

Le etichette sono come quelle di Goto:Usali con parsimonia e solo quando rendono il tuo codice più veloce E cosa ancora più importante, più comprensibile,

ad esempio, se ti trovi in ​​grandi loop profondi sei livelli e incontri una condizione che rende inutile il completamento del resto del loop, non ha senso avere 6 botole extra nelle dichiarazioni di condizione per uscire anticipatamente dal loop.

Le etichette (e i goto) non sono malvagie, è solo che a volte le persone le usano in modo sbagliato.La maggior parte delle volte stiamo effettivamente cercando di scrivere il nostro codice in modo che sia comprensibile per te e per il prossimo programmatore che arriva.Renderlo super veloce è una preoccupazione secondaria (diffidare dell'ottimizzazione prematura).

Quando le etichette (e i goto) vengono utilizzati in modo improprio, rendono il codice meno leggibile, il che causa problemi a te e allo sviluppatore successivo.Al compilatore non importa.

Ci sono poche occasioni in cui hai bisogno di etichette e possono creare confusione perché vengono utilizzate raramente.Tuttavia, se è necessario utilizzarne uno, utilizzane uno.

A proposito:questo viene compilato ed eseguito.

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

Sono curioso di sapere qual è la tua alternativa alle etichette.Penso che tutto questo si ridurrà all'argomento "ritorno il prima possibile" vs."usa una variabile per contenere il valore restituito e restituiscilo solo alla fine."

Le etichette sono piuttosto standard quando si hanno cicli nidificati.L'unico modo in cui riducono realmente la leggibilità è quando un altro sviluppatore non li ha mai visti prima e non capisce cosa significano.

Non ho mai visto etichette usate "in natura" nel codice Java.Se vuoi davvero interrompere i cicli nidificati, vedi se riesci a rifattorizzare il tuo metodo in modo che un'istruzione return anticipata faccia ciò che desideri.

Tecnicamente, immagino che non ci sia molta differenza tra un ritorno anticipato e un'etichetta.In pratica, però, quasi tutti gli sviluppatori Java hanno visto un ritorno anticipato e sanno cosa fa.Immagino che molti sviluppatori rimarrebbero almeno sorpresi da un'etichetta e probabilmente sarebbero confusi.

A scuola mi è stata insegnata l'ortodossia di ingresso singolo/uscita singola, ma da allora ho imparato ad apprezzare le dichiarazioni di ritorno anticipato e l'uscita dai cicli come un modo per semplificare il codice e renderlo più chiaro.

Direi a loro favore in alcune posizioni, li ho trovati particolarmente utili in questo esempio:


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

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

  }
  purchasedItems.add(item);
}

Penso che con il nuovo ciclo for-each l'etichetta possa essere davvero chiara.

Per esempio:

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

Penso che sia davvero chiaro avendo la tua etichetta uguale alla tua variabile nel nuovo for-each.In effetti, forse Java dovrebbe essere malvagio e aggiungere etichette implicite per ciascuna variabile eh

Ho utilizzato un ciclo etichettato Java per un'implementazione di un metodo Sieve per trovare i numeri primi (fatto per uno dei problemi di matematica del progetto Eulero) che lo ha reso 10 volte più veloce rispetto ai cicli nidificati.Ad esempio, se (certa condizione) torna al ciclo esterno.

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

Ho chiesto a un programmatore C++ quanto siano pessimi i loop etichettati, ha detto che li avrebbe usati con parsimonia, ma occasionalmente possono tornare utili.Ad esempio, se hai 3 cicli nidificati e per determinate condizioni vuoi tornare al ciclo più esterno.

Quindi hanno i loro usi, dipende dal problema che stavi cercando di risolvere.

Non uso mai le etichette nel mio codice.Preferisco creare una guardia e inizializzarla su nullo o altro valore insolito.Questa guardia è spesso un oggetto risultante.Non ho visto nessuno dei miei colleghi utilizzare etichette, né ne ho trovato nessuna nel nostro repository.Dipende davvero dal tuo stile di codifica.A mio avviso l'utilizzo delle etichette ridurrebbe la leggibilità in quanto non è un costrutto comune e di solito non viene utilizzato in Java.

Sì, dovresti evitare di usare le etichette a meno che non ci sia un motivo specifico per usarle (l'esempio in cui semplifica l'implementazione di un algoritmo è pertinente).In tal caso, consiglierei di aggiungere commenti sufficienti o altra documentazione per spiegare il ragionamento alla base in modo che qualcuno non arrivi più tardi e lo tolga dall'idea di "migliorare il codice" o "eliminare l'odore del codice" o qualche altra scusa potenzialmente stronzata.

Identificherei questo tipo di domanda con la decisione quando si dovrebbe o non si dovrebbe usare il ternario se.La logica principale è che può impedire la leggibilità e, a meno che il programmatore non sia molto attento a nominare le cose in modo ragionevole, l'uso di convenzioni come le etichette potrebbe peggiorare molto le cose.Supponiamo che l'esempio che utilizza "nextCondition" e "nextItem" abbia utilizzato "loop1" e "loop2" per i nomi delle etichette.

Personalmente le etichette sono una di quelle funzionalità che non hanno molto senso per me, al di fuori dell'Assembly o del BASIC e di altri linguaggi altrettanto limitati.Java ha molti costrutti di controllo e loop più convenzionali/regolari.

Ho trovato che le etichette a volte siano utili nei test, per separare le consuete fasi di configurazione, esercizio e verifica e le dichiarazioni relative al gruppo.Ad esempio, utilizzando la 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();
}

Le tue scelte di formattazione possono variare, ma l'idea centrale è che le etichette, in questo caso, forniscano una distinzione evidente tra le sezioni logiche che compongono il tuo test, meglio di quanto possano fare i commenti.Penso che la Spock la libreria si basa proprio su questa funzionalità per dichiarare le sue fasi di test.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top