2015-10-26 7 views
5

Ich schreibe ein Add-In für eine andere Software über seine API. Die von der API zurückgegebenen Klassen können nur über die native Software und die API zugreifen. Also schreibe ich meine eigenen Stand-alone-POCO/DTO-Objekte, die den API-Klassen zugeordnet sind. Ich arbeite an einer Funktion, die in einer nativen Datei liest und eine Sammlung dieser POCO-Objekte zurückgibt, die ich anderswo gestohlen habe. Derzeit verwende ich JSON.NET, um diese Klassen zu JSON zu serialisieren, wenn das wichtig ist.Entwurfsmuster für das Einschließen von Fehlern mit Rückgabewerten

Zum Beispiel habe ich eine DTO ähnliche Objekte

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

..und ein Verfahren wie dieses könnte die native "Personen" in meine DTO zu lesen

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

I Unit-Tests Setup mit einer Testdatei, aber ich laufe immer wieder auf unerwartete Probleme, wenn ich meinen Export für andere Dateien ausführe. Manchmal haben native Objekte unerwartete Werte, oder es werden in der API Fehler angezeigt, die Ausnahmen auslösen, wenn es keinen Grund dafür gibt.

Derzeit, wenn etwas "Ausnahme" passiert, protokolliere ich nur die Ausnahme und der Export schlägt fehl. Aber ich habe beschlossen, dass ich lieber exportieren möchte, was ich kann, und die Fehler irgendwo aufzeichnen.

Die einfachste Möglichkeit wäre, nur um sich einzuloggen und die Ausnahmen zu schlucken und zurück, was ich kann, aber dann gäbe es keine Möglichkeit für meine Berufung Code zu wissen, wenn es ein Problem gab.

Eine Option, die ich in Betracht ziehe, ist die Rückgabe eines Fehlerwörterbuchs als separaten Parameter. Der Schlüssel würde die Eigenschaft identifizieren, die nicht gelesen werden konnte, und der Wert würde die Details der Ausnahme/des Fehlers enthalten.

Alternativ habe ich auch erwogen, nur die Fehler im Rückgabeobjekt selbst zu speichern. Dies vergrößert die Größe meines Objekts, hat aber den zusätzlichen Vorteil, dass die Fehler direkt mit meinen Objekten gespeichert werden. Später, wenn jemandes Export einen Fehler erzeugt, muss ich mich nicht darum kümmern, die richtige Log-Datei auf ihrem Computer zu finden.

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;} 
} 

Wie wird dies in der Regel behandelt? Gibt es eine andere Möglichkeit, die Fehler zusammen mit den Rückgabewerten zu melden, die ich nicht in Betracht ziehe?

+0

Abhängig von der Implementierung hält Martin Fowler die letzte Option für die beste. Es gibt auch eine Ausnahme, bei der Sie eine Ausnahme auslösen, wenn etwas schief geht. – Fals

+0

Haben Sie zufällig einen Link zu einem Blogpost oder einer Präsentation, wo Martin darüber spricht? –

+0

Da geht der Link für den Beitrag: http://martinfowler.com/articles/replaceThrowWithNotification.html – Fals

Antwort

4

Statt Fehler als Teil der Entitäten Rückkehr Sie das Ergebnis in einer Antwort oder Antwortnachricht wickeln könnte. Fehler könnten dann ein Teil der Antwortnachricht anstelle der Entitäten sein.

Der Vorteil hierbei ist, dass die Einheiten sind sauber

Der Nachteil ist, dass es schwieriger sein wird, die Fehler wieder zu beleidigen Einheiten/Attribute abzubilden.

Beim Senden von Gruppen von Elementen kann dieser Nachteil ein großes Problem sein. Wenn die API eher single-entity-orientiert ist, ist das nicht so wichtig.

+0

Das ist eine gute Option, aber leider arbeite ich selten mit einzelnen Objekten. Der typische Anwendungsfall besteht darin, mehrere Objektexporte aus zwei separaten Dateien zu vergleichen. Ich bin auch fast immer Serialisierung des zurückgegebenen Objekts zu JSON und Umgang mit diesem JSON später. Es wäre problematisch, die Fehler separat zu speichern. –

+0

Ich glaube, er meinte, dass Sie 'ParseResponse' zurückgeben würden, die als 'public class ParseResponse {public IList Personen {get; set;} public IList Exceptions {get; set;}}' Sie können dann return.Persons und serialisieren es wäre frei von irgendwelchen Status-/Rückkehrcodedaten. –

+0

Ja, das habe ich gemeint –

1

Im Prinzip, wenn etwas in API schief geht (die wiederhergestellt werden können), muss der anrufenden Code darüber im Klaren sein, dass eine Ausnahme aufgetreten ist. Es kann also eine Strategie haben, um damit umzugehen.

Daher ist der Ansatz, der mir in den Sinn kommt durch die gleiche Philosophie beeinflusst wird -

1> Definieren Sie Ihre eigenen Ausnahme Lets IncompleteReadException sagen. Diese Ausnahme muss eine Eigenschaft IList<MyPersonDTO> haben, um die gelesenen Datensätze bis zum Auftreten der Ausnahme zu speichern.

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> Wenn eine Ausnahme auftritt, während das Lesen, können Sie die ursprüngliche Ausnahme abfangen, wickeln Sie die ursprüngliche Ausnahme in diesem & Wurf IncompleteReadException

Dies wird die Telefonvorwahl (Application Code) ermöglichen, haben eine Strategie, um mit der Situation fertig zu werden, wenn unvollständige Daten gelesen werden.