goto per migliorare DRY-ness OK? [duplicare]

1

Il mio codice ha molti controlli per rilevare errori in vari casi (molte condizioni comporterebbero lo stesso errore), all'interno di una funzione che restituisce una struttura di errore. Invece di apparire così:

err_struct myfunc(...) {
    err_struct error = { .error = false };

    ...

    if(something) {
        error.error = true;
        error.description = "invalid input";
        return error;
    }

    ...

        case 1024:
            error.error = true;
            error.description = "invalid input";  // same error, but different detection scenario
            return error;
            break;  // don't comment on this break please (EDIT: pun unintended)
            ...

L'uso di goto nel seguente contesto è considerato migliore dell'esempio precedente?

err_struct myfunc(...) {
    err_struct error = { .error = false };

    ...

    if(something) goto invalid_input;

    ...

        case 1024:
            goto invalid_input;
            break;

    return error;

    invalid_input:
        error.error = true;
        error.description = "invalid input";
        return error;
    
posta Marco Scannadinari 17.08.2014 - 21:38
fonte

2 risposte

3

se usi goto il tuo codice legge meglio, usalo. È un linguaggio come gli altri. Siamo più all'età di Dijkstra.

link

int parse()
{
    Token   tok;

reading:
    tok = gettoken();
    if (tok == END)
        return ACCEPT;
shifting:
    if (shift(tok))
        goto reading;
reducing:
    if (reduce(tok))
        goto shifting;
    return ERROR;
}

Questo è un caso in cui i goto-s sono ancora più eleganti di qualsiasi altra struttura.

    
risposta data 17.08.2014 - 22:12
fonte
1

When you see a good move, look for a better one.
—Emanuel Lasker, 27-year world chess champion

La pulitura / gestione degli errori di quel modulo è uno degli usi accettabili di goto , specialmente in C. L'uso di goto è meglio che ripetere queste tre righe, ma puoi fare ancora meglio. Cerca sempre la mossa migliore.

Per prima cosa, è improbabile che quegli errori siano veramente identici. Ad un certo punto, qualcuno si chiederà in quali condizioni hai effettivamente colpito, quindi sei tornato dove hai iniziato. Hai bisogno di un modo sintetico per distinguere tra diversi errori nel momento in cui vengono rilevati.

Ecco una soluzione:

const err_struct myfunc(...) {
    const err_struct success       = { .error = false };
    const err_struct invalid_input = { .error = true, .description = "invalid input" };

    ...

    if(something) 
        return invalid_input;

    ...

        case 1000:
            return custom_error("Expected %d, found 1000", expected);

        case 1024:
            return invalid_input;

    ...

    return success;
}

Per descrizioni degli errori di uso comune, li definirei insieme a err_struct , il che renderebbe più semplice la coerenza con la dicitura nel sistema e aiuta a mantenere un errore di battitura accidentale in una descrizione da parte del codice.

    
risposta data 18.08.2014 - 18:55
fonte

Leggi altre domande sui tag