Sta usando per la sintassi del loop per un blocco "con (variabile)" un anti-pattern?

6

Mi sono ingannato con for -loops, ho ricordato la parola chiave with di delphi e ho trovato il seguente pattern (definito come un modello live in IntelliJ IDEA):

for ($TYPE$ $VAR$ = $VALUE$; $VAR$ != null; $VAR$ = null) {
    $END$
}

Dovrei usarlo nel codice produttivo? Penso che potrebbe essere utile per creare variabili di collegamento temporanee come queste variabili di un carattere in lamd e couting per cicli. Inoltre, controlla se la variabile che intendi utilizzare nel blocco è null prima. Considera il caso seguente in un'applicazione swing:

// init '+1' button
for (JButton b = new JButton("+1"); b != null; add(b), b = null) {
    b.setForeground(Color.WHITE);
    b.setBackground(Color.BLACK);
    b.setBorder(BorderFactory.createRaisedBevelBorder());
    // ...
    b.addActionListener(e -> {
        switch (JOptionPane.showConfirmDialog(null, "Are you sure voting +1?")) {
            case JOptionPane.OK_OPTION:
                // ...
                break;
            default:
                // ...
                break;
        }
    });
}
    
posta Binkan Salaryman 12.11.2015 - 15:10
fonte

2 risposte

33

Non è un anti-pattern, perché significherebbe che è una tecnica comunemente usata che è in qualche modo problematica. Questo codice non soddisfa il criterio "comunemente usato".

Tuttavia, è problematico. Ecco alcuni dei suoi problemi:

  • Ingannevole: utilizza una struttura ad anello, ma non esegue mai più di una volta.
  • Nascondere un assegno: il controllo! = null è facile da perdere dove è collocato. Il codice nascosto è più difficile da capire. Inoltre, non è chiaro se la condizione sia effettivamente necessaria o solo lì per terminare il ciclo dopo la prima iterazione. (Le tue affermazioni sul controllo indicano che hai situazioni in cui è necessario, mentre nel tuo esempio non lo è, poiché new non restituisce mai nulla.)
  • Nascondere un'azione: l'istruzione add (b) è ancora più nascosta. Non è nemmeno sequenzialmente nella posizione in cui ti aspetteresti.
  • Non necessario: puoi solo dichiarare una variabile locale. Se non vuoi che il suo nome sia visibile, puoi usare un'istruzione di blocco per limitarne l'ambito, sebbene che sia un anti-pattern (o almeno un odore di codice), a indicare che tu dovrebbe estrarre una funzione.
risposta data 12.11.2015 - 15:22
fonte
29

Quello che stai facendo è offuscare il tuo codice, non renderlo più chiaro. Ci vuole un sacco di sforzo per capire che questo "ciclo" verrà eseguito solo una volta. Invece, potresti semplicemente usare un blocco di istruzioni per limitare l'ambito della variabile:

{
    JButton b = new JButton("+1");
    b.setForeground(Color.WHITE);
    ...
}

Se sei interessato a lambda, puoi anche definire una funzione with statica che consente l'utilizzo come

with(new JButton("+1"), b -> {
    b.setForeground(Color.WHITE);
    ... 
});

Questo può essere un po 'più chiaro, ma è ancora molto indiretto rispetto al blocco semplice che realizza la stessa cosa, senza alcuna possibilità di introdurre nuovi errori.

    
risposta data 12.11.2015 - 15:24
fonte

Leggi altre domande sui tag