Nuovo tentativo di un'istruzione o chiamata in un blocco catch - codice odore o anti-pattern?

1

Mi chiedo quanto è meglio eseguire questa operazione per una grande quantità di file. Vorrei un po 'di pensieri su se questa copia / incolla è abbastanza accettabile da un compromesso .

  • prova a scrivere un file
  • se la dir di destinazione non esiste, crearla
  • riprova a scrivere il file. Se qualcos'altro genera ed eccezione, rilancia.
try{
   File.Copy("@D:\foo.txt", @"C:\mydir\foo.txt");
}
catch (DirectoryNotFoundException){    
   CreateDirectoryForFile(@"C:\mydir");
   File.Copy("@D:\foo.txt", @"C:\mydir\foo.txt"); //copy pasted from the try block
}

C'è un blocco più semplice che è più facile da leggere, ma porta a un numero maggiore di chiamate IO su disco che è necessario:

CreateDirectoryForFile(@"C:\mydir\foo.txt");
File.Copy("@D:\foo.txt", @"C:\mydir\foo.txt");

È possibile migliorare il modello 1?

    
posta p.campbell 23.06.2014 - 01:12
fonte

2 risposte

6

Il semplice principio è che questo non è un Exception di per sé, è una condizione prevista e quindi dovrebbe essere controllato usando if (Directory.Exists(...)) per vedere se la directory di destinazione non esiste (e allo stesso modo if (File.Exists(...)) per verificare se il il file esiste già in quella directory se questo è importante per il tuo scenario).

Stai pagando un prezzo ad alte prestazioni per questo perché le eccezioni sono più costose. Ad esempio, verifica che quando cerchi di ottenere un elemento da Dictionary utilizzando un indicizzatore, genera KeyNotFoundException se l'elemento non esiste. Per evitare di ottenere e intercettare questa eccezione, in genere le persone prima controllano l'esistenza dell'elemento utilizzando il metodo Contains e lo prelevano solo se esiste. Pertanto, la classe Dictionary ha quindi fornito un TryGetValue che proverà a recuperare l'elemento, ma se l'elemento non esiste in Dictionary , restituirà solo un false che lo indicherà.

Come sottolineato da DeadMG nei commenti, ci potrebbero essere casi in cui la concorrenza funziona meglio quando non si controlla e si esegue semplicemente l'operazione. Un esempio potrebbe essere che se il tuo codice creasse solo la directory, potrebbe essere meglio usare solo Directory.Create invece di verificare la presenza perché lo stato del file system potrebbe cambiare tra il controllo e l'operazione effettiva.

Una linea guida di codifica che utilizzo è che se un metodo consente di verificare una condizione per la quale può essere lanciata un'eccezione, considera prima l'utilizzo di tale metodo e fa affidamento solo sull'eccezione se c'è una strong ragione per non controllare prima . Esistono casi validi, in particolare sulla rete in cui, se si verifica l'esistenza di un file e successivamente lo si elimina, si potrebbero verificare elevati costi di latenza o larghezza di banda, nel qual caso potrebbe essere preferibile tentare un'azione e rilevare un'eccezione. Le API di archiviazione di Azure, ad esempio, utilizzano tale approccio.

Evita le eccezioni quando una condizione è una delle possibilità valide e non ci sono buoni motivi per preferire le eccezioni. Nel tuo caso, è normale perché la directory non esista, e non una condizione di errore, e stai trattando sul disco locale.

EDIT: aggiornato dopo il commento di DeadMG, la mia risposta iniziale era focalizzata solo sul codice nella domanda.

    
risposta data 23.06.2014 - 02:04
fonte
0

Questa è una violazione di DRY . Lo eviterei davvero. Prima o poi qualcosa cambierà e ti morderà.

Potresti

  1. Riforma il codice pertinente come una funzione
  2. Mostra le stringhe come costanti
  3. Scrivi un ciclo che può consentire solo un tentativo.

Qualsiasi cosa per evitare il taglia e incolla.

    
risposta data 23.06.2014 - 01:55
fonte

Leggi altre domande sui tag