2015-10-26 13 views
5

Sto scrivendo un componente aggiuntivo per un altro software tramite la sua API. Le classi restituite dall'API possono essere accessibili solo tramite il software nativo e l'API. Quindi sto scrivendo i miei oggetti POCO/DTO stand-alone che si associano alle classi API. Sto lavorando a una funzione che leggerà in un file nativo e restituirò una raccolta di questi oggetti POCO che posso rubare altrove. Attualmente sto usando JSON.NET per serializzare queste classi su JSON se questo è importante.Design pattern per includere errori con valori di ritorno

Per esempio potrei avere un DTO come questo

public class MyPersonDTO 
{ 
    public string Name {get; set;} 
    public string Age {get; set;} 
    public string Address {get; set;}  
} 

..e un metodo come questo di leggere le "Persone" nativi nella mia DTO oggetti

public static class MyDocReader 
{ 
    public static IList<MyPersonDTO> GetPersons(NativeDocument doc) 
    { 
     //Code to read Persons from doc and return MyPersonDTOs 
    } 
} 

Ho installato unit test con un file di test, tuttavia continuo a incontrare problemi imprevisti durante l'esecuzione dell'esportazione su altri file. A volte gli oggetti nativi avranno valori inattesi, o ci saranno errori flat nell'API che generano eccezioni quando non c'è motivo.

Attualmente, quando si verifica qualcosa di "eccezionale", registro l'eccezione e l'esportazione non riesce. Ma ho deciso che preferirei esportare quello che posso e registrare gli errori da qualche parte.

L'opzione più semplice sarebbe quella di registrare e ingoiare le eccezioni e restituire ciò che posso, tuttavia in questo caso il codice di chiamata non sarebbe stato in grado di sapere quando si è verificato un problema.

Un'opzione che sto considerando è la restituzione di un dizionario di errori come parametro separato. La chiave identifica la proprietà che non può essere letta e il valore conterrà i dettagli dell'eccezione/errore.

public static class MyDocReader 
{ 
    public static IList<MyPersonDTO> persons GetPersons(NativeDocument doc, out IDictionary<string, string> errors) 
    { 
     //Code to read persons from doc 
    } 
} 

In alternativa, stavo anche considerando di archiviare gli errori nell'oggetto di ritorno stesso. Questo gonfia la dimensione del mio oggetto, ma ha il vantaggio di archiviare gli errori direttamente con i miei oggetti. Quindi più tardi, se l'esportazione di qualcuno genera un errore, non devo preoccuparmi di rintracciare il file di registro corretto sul proprio computer.

public class MyPersonDTO 
{ 
    public string Name {get; set;} 
    public string Age {get; set;} 
    public string Address {get; set;} 

    public IDictionary<string, string> Errors {get; set;} 
} 

Come viene gestito in genere? C'è un'altra opzione per riportare gli errori insieme ai valori di ritorno che non sto considerando?

+0

A seconda dell'implementazione, Martin Fowler considera l'ultima opzione la più valida. Esiste anche il modo Eccezione, in cui si genera un'eccezione quando qualcosa va storto. – Fals

+0

Ti capita di avere un link a un post sul blog o una presentazione in cui Martin parla di questo? –

+0

Esiste il collegamento per il post: http://martinfowler.com/articles/replaceThrowWithNotification.html – Fals

risposta

4

Invece di restituire errori come parte delle entità, è possibile includere il risultato in un messaggio di risposta o di risposta. Gli errori potrebbero quindi essere una parte del messaggio di risposta al posto delle entità.

Il vantaggio di questo è che le entità sono pulite

Il rovescio della medaglia è che sarà più difficile per mappare gli errori di nuovo a offendere entità/attributi.

Quando si inviano lotti di entità questo inconveniente può essere un grosso problema. Quando l'API è più orientata all'entità singola, non importa più di tanto.

+0

Questa è una buona opzione, ma sfortunatamente sto raramente lavorando con singoli oggetti. Il caso d'uso più comune è quello di confrontare un numero di esportazioni di oggetti da due file separati. Sto anche serializzando quasi sempre l'oggetto restituito a JSON e trattando quel JSON più tardi. Quindi memorizzare gli errori separatamente sarebbe problematico. –

+0

Credo che intendesse restituire 'ParseResponse' che è definito come' public class ParseResponse {public IList Persons {get; set;} public IList Eccezioni {get; set;}} 'È quindi possibile serializzare return.Persons e sarebbe privo di dati sullo stato/codice di ritorno. –

+0

Sì, questo è ciò che intendevo –

1

In linea di principio, se qualcosa va storto in API (che non può essere ripristinato), il codice chiamante deve essere consapevole del fatto che si è verificata un'eccezione. Quindi può avere una strategia in atto per affrontarlo.

Perciò, l'approccio che mi viene in mente è influenzata dalla stessa filosofia -

1> definire la propria eccezione Diciamo IncompleteReadException. Questa eccezione deve avere una proprietà IList<MyPersonDTO> per memorizzare i record letti fino a quando si è verificata l'eccezione.

public class IncompleteReadException : Exception 
{ 
    IList<MyPersonDTO> RecordsRead { get; private set; }  

    public IncompleteReadException(string message, IList<MyPersonDTO> recordsRead, Exception innerException) : base(message,innerException) 
    { 
     this.RecordsRead = recordsRead; 
    } 
} 

2> Quando si verifica un'eccezione durante la lettura, si può prendere l'eccezione originale, avvolgere l'eccezione originale in questo & tiro IncompleteReadException

In questo modo il codice chiamante (codice applicazione), per avere una strategia in atto per affrontare la situazione quando vengono letti dati incompleti.