Qual è un modo corretto di concatenare le istruzioni se quella precedente è ok [duplicato]

3

Attualmente sto lavorando su un grande file che devo analizzare ed elaborare e ogni passo deve essere fatto in un ordine mentre faccio query SQL e ho bisogno di ID inseriti per fare altri inserimenti ... Il problema è che trovo spesso il mio codice simile a questo:

if( function1() ) {
    // process things to continue
    if( function2() ) {
        // process things to continue

        // ... and so on

    } else {
        // fail2
    }
} else {
    // fail1
}

E lo stesso vale per le convalide dei form, ecc ... e diventa davvero difficile seguire i passaggi, e non è piacevole vedere il codice.

Come ho già detto, ho bisogno di function1 da eseguire prima di function2 , quindi non posso fare altrimenti che essere sicuro che le funzioni precedenti siano state eseguite correttamente.

Esiste un modo corretto o uno schema di progettazione per codificare questo tipo di funzioni condizionali concatenate?

(FYI: Io uso OO PHP5, e sono praticamente un principiante in termini di standard nella programmazione, quindi per favore non decapitare se è casuale!)

(relativo a possibili duplicati di Quando, se mai, dovrebbe Funzioni della catena a margherita? ): le funzioni possono essere utilizzate separatamente e quindi non possono essere utilizzate con collegamento a margherita (vedere "B" nel collegamento indicato).

I //Fail s sono qui per "alzare un flag" per dire che c'è stato un problema e più avanti nel codice (dopo il if / elses) esegue il rollback di tutte le modifiche (con il rollback della transazione di PDO). Ma vorrei avvisare l'utente che c'è stato un problema, scrivere un messaggio (errore del database? Valori vuoti? ...) e magari passare più informazioni come variabili da visualizzare / debug.

    
posta Strannch 11.06.2015 - 16:16
fonte

2 risposte

4

il modo più semplice per fare il refactoring è usare una variabile di successo, ad esempio

res = do_stuff();
if (res)
    res = do_more_stuff();
if (res)
    ....

Se utilizzi un contatore invece di una variabile di successo booleana, puoi anche stabilire se tutti i passaggi sono riusciti alla fine (cioè il contatore sarà uguale al numero di passaggi eseguiti correttamente)

L'unica cosa che non si può fare con questo modello è di avere clausole 'else' diverse per errore, ma si può invece lanciare un'eccezione per gestire il flusso (non è consigliabile se si prevede che i passaggi falliscano). È possibile tenere traccia dell'ultimo metodo che è stato eseguito e avere un gestore di switch alla fine del metodo che ha chiamato la corretta routine di fail per ciascuno, ma che può diventare disordinato, a seconda delle circostanze, naturalmente.

Ci sono modi più complessi per gestirlo - ad esempio, invece di chiamare ogni metodo, chiamare un helper che prende 2 funzioni come parametri, il metodo da chiamare e il metodo da chiamare in caso di fallimento, quindi l'helper può restituire true / false come prima, o costruisci una raccolta di funzioni da chiamare e scorrere attraverso di essa, chiamando ognuna a turno .. ma queste sono le migliori per circostanze speciali quando ne hai bisogno. Come dici tu sei un po 'un principiante, andrei per lo schema che ho suggerito inizialmente, è semplice.

    
risposta data 11.06.2015 - 16:50
fonte
0

È possibile calcolare la gestione degli errori, in modo che la funzione possa semplicemente restituire per errore. In C / C ++ questo sarebbe simile a questo:

int handleError(int errorCode, char* message) {
    if(errorCode) {
        //Notify user, whatever
    }
    return errorCode;
}

int functionThatCanFail(...) {
    int result;

    if(result = handleError(do_stuff(), "do_stuff() failed")) return result;
    if(result = handleError(do_more_stuff(), "do_more_stuff() failed")) return result;
}

Naturalmente, è possibile avere un piccolo set di tali funzioni di gestione degli errori per distinguere, ad esempio, da errori fatali, errori e avvertimenti o che gestiscono diverse convenzioni di restituzione degli errori (ad esempio il codice di errore rispetto al puntatore NULL). In C ++, la differenziazione successiva può essere gestita da un modello, ma non è più una considerazione indipendente dal linguaggio.

    
risposta data 11.06.2015 - 18:15
fonte