metodo migliore per ripristinare lo stato se si verifica un errore durante l'aggiunta / eliminazione

5

Quindi ho un framework generico con un concetto di oggetti figlio e genitore, gli oggetti non devono essere dello stesso tipo e posso aggiungere o rimuovere uno di essi. L'aggiunta di chiamate si aggiunge a tutti i bambini e informa i genitori, inversa per la rimozione.

il concetto di Parent è abbastanza generico da consentire un loop tra le classi. A può essere un genitore di B che è un genitore di C che è un genitore di A. Questo funziona ancora, dal momento che contrassegno un oggetto come aggiunto o rimosso come primo passo nella classe astratta; quindi anche se una dipendenza circolare chiama Aggiungi una seconda volta sullo stesso oggetto, la seconda volta attraverso l'add ritornerà senza fare nulla (perché il booleano aggiunto è già impostato) e interrompiamo la nostra ricorsione.

Se si verificano alcune eccezioni impreviste, desidero ripristinare il mio stato su ciò che era prima che si verificasse l'eccezione. Lo stavo facendo con la gestione delle eccezioni, se rilevo una connessione run time rimuovo gli oggetti che ho aggiunto e aggiorno i genitori prima di lanciare l'eccezione. È qui che la mia logica può fallire. A partire da ora ho ripristinato il metodo AddObject chiamando removeObject e viceversa. Se il mio stato in qualche modo finisse in uno stato veramente bizzarro, potrei continuare a lanciare eccezioni, aggiungere lanci e chiamate rimuovere, togliere tiri e chiamate add, ecc ecc. Penso che questo abbia ancora una possibilità di ricorsione infinita; anche se, ammettiamolo, qualcosa dovrebbe già essere incasinato nel mio stato perché accada.

C'è un modo più semplice per eseguire la mia logica di rollback per evitare questo potenziale? In un punto come questo, dovrei dire che il mio stato dovrebbe essere una volta che recupero comunque?

    
posta dsollen 30.04.2013 - 01:49
fonte

4 risposte

2

C'è un modo più pulito ed è di usare strutture dati immutabili / persistenti. Questa è un'idea della programmazione funzionale, ma non c'è davvero alcuna ragione per cui non si possa farlo anche in un paradigma orientato agli oggetti.

Costruisci i dati in modo tale da non essere mai cancellato o mutato. Gli aggiornamenti creano una nuova struttura senza modificare i dati della vecchia struttura. Se un aggiornamento va storto, si ritorna alla versione precedente. Se ha successo, puoi scartare la versione precedente a seconda delle tue esigenze.

link

    
risposta data 30.04.2013 - 14:50
fonte
2

Se ti puoi permettere la memoria, puoi fare uno scatto prima di apportare qualsiasi modifica. Se tutto va bene, elimina l'istantanea. Se qualcosa va storto, rilascia la nuova versione e torna allo snapshot.

Se questo è troppo costoso, puoi prima calcolare quali parti potrebbero essere interessate (DFS o qualcosa del genere) e solo scattare un'istantanea di quelle parti.

    
risposta data 30.04.2013 - 01:58
fonte
0

Sono disponibili due modelli di progettazione per le operazioni di annullamento / ripetizione che vale la pena esaminare. Il primo è il Command Design Pattern: -

link

E il secondo è il motivo di design di Memento: -

link

Spero che ti aiuti.

    
risposta data 01.05.2013 - 18:05
fonte
0

In primo luogo, hai davvero bisogno di ripristinare lo stato? Quando qualcosa è andato storto nel tuo programma, ha senso cercare di rimanere in piedi piuttosto che crash e masterizzare? Può essere molto impegnativo cercare di rendere il tuo programma resiliente a quel genere di cose, e devi valutare se staresti meglio spendendo quel tempo a correggere i bug che causano le eccezioni.

Suggerisco di fare qualcosa relativo alla tecnica usata da un database. I database tengono un registro di tutte le modifiche apportate in modo che possano eseguire il back-through del log e annullare tutte le modifiche. Quindi avrei il codice che assomiglia a

transaction = TreeTransaction()
try
{
    foo.add(bar, transaction);
    bar.add(goat, transaction);
    transaction.commit();
}
catch(...)
{
    transaction.rollback();
}

A seconda della lingua, di solito ci sono alcuni modi per migliorare il modello. L'idea è che tutte le modifiche vengano apportate nel contesto di una transazione. Quando si verifica un errore imprevisto, il metodo di rollback rimette tutto come era. Commit può rendere ufficiali le modifiche, se questo ha senso.

    
risposta data 01.05.2013 - 23:47
fonte

Leggi altre domande sui tag