PDA

Visualizza la versione completa : [ALL] Curiosita' sul controllo di flusso di un programma


mciasco
17-03-2010, 19:30
Scusate, spesso mi imbatto in situazioni in cui devo eseguire una serie di operazioni all'interno di un "task" piu' generale e spesso l'operazione i-esima deve essere eseguita solo se la precedente e' andata a buon fine.

Per esempio ho un task generico che per coerenza logica e' suddiviso in 4 operazioni A, B, C e D. Ogni operazione e' ovviamente una funzione.
Ad esempio:
- A = lettura di un file con i dati di connessione
- B = connessione ad un db
- C = esecuzione select
- D = lettura recordset ottenuto

Ognuna di queste 4 operazioni dipende dal successo della precedente (vabbe' a parte la prima che va sempre eseguita...).

Sinceramente a me fa abbastanza schifo scrivere codice del tipo:


if(A)
if(B)
if(C)
if(D) ...
else errore D
else errore C
else errore B
else errore A


Anche perche' non sempre le cose sono cosi' lineari.

Vorrei sapere se voi seguite degli schemi precisi o meno. Questa e' una questione piuttosto sottovalutata in programmazione ma alla fine la "ciccia" dei nostri programmi e' proprio costituita da tutti quei brutti IF, SWITCH, WHILE, FOR... di cui anche la programmazione ad oggetti prima o poi necessita.

antotan
17-03-2010, 21:42
Dipende molto dal contesto.
In generale qualche modo per evitare la fila di if c'č, ma dipende dai fattori con cui operi.
Se ad esempio le funzioni che utilizzi ritornano 0 in caso di fallimento e 1 in caso di successo, puoi sfruttare la short-circuit evaluation dell'operatore and, se il tuo linguaggio lo supporta, facendo dunque:



if(A && B && C && D)
{
// ok
}
else
{
// errore
}


Hai la certezza che D verrā eseguita solo se C va a buon fine. C sse B va a buon fine, B sse A va a buon fine.

Oppure puoi utilizzare la gestione delle eccezioni. Supponendo che tutte le funzioni lancino un'eccezione in caso di errore:



try {
A;
B;
C;
D;
} catch(Expection& e)
{
// ...
}


Se un operazione lancia un'eccezione, sei certo che nessun'altra operazione successiva nel blocco try venga eseguita.
Personalmente utilizzo questa, quando posso.

:ciauz:

LeleFT
18-03-2010, 14:23
Un'alternativa (che non mi piace particolarmente, ma a volte viene usata) č l'approcio FSM (Finite-State-Machine) al problema. Utile nei casi in cui, ad esempio, uno degli step debba essere ritentato per un certo numero di volte in caso di errore, prima di terminare definitivamente.

Pseudo-codice:


while( condizione_ciclo ) {
switch( stato ) {
case 0: /* Primo task */
if ( A ) {
stato = 1;
} else {
/* ritento (stato = 0) o esco (stato = -1) ? */
}

case 1: /* Secondo task */
if ( B ) {
stato = 2;
} else {
/* ritento (stato = 1) o esco (stato = -1) ? */
}

case 2: /* Terzo task */
if ( C ) {
stato = 3;
} else {
/* ritento (stato = 2) o esco (stato = -1) ? */
}

...

default:
condizione_ciclo = false;
}
}


Ciao. :ciauz:

Loading