2017-01-06 4 views
0

Ich bin mir nicht sicher, wie benutzerdefinierte Ausnahmen am besten strukturiert werden können. Sagen wir, ich eine Situation, wo es eine Bibliothek ist, die eigene benutzerdefinierte Ausnahmeklasse führt, mit einem benutzerdefinierten Feld in es:Hinweise zur Strukturierung von benutzerdefinierten Ausnahmetypen

public class CustomException extends RuntimeException { 
    private final String additionalInfo; 

    public CustomException(String message, String additional) { 
    super(message); 
    this.additionalInfo = additional; 
    } 

    public String getAdditionalInfo() { 
    return additionalInfo; 
    } 
} 

Umgang mit diesem ist ziemlich einfach:

try { 
    something(); 
} catch (CustomException e) { 
    LOGGER.error(e.getMessage()); 
    LOGGER.error(e.getAdditionalInfo()); 
} 

So weit, so gut , aber was ist, wenn dies viele Schichten tief in eine Art von Service und behandelt auf diese Weise verpackt:

// in a subclass of a theoretical ServiceHandler interface 
public void handle() throws OperationFailedException { 
    try { 
    something(); 
    } catch (RuntimeException e) { 
    throw new OperationFailedException("The operation failed.", e); 
    } 
} 

Weiter unten in der Aufrufliste der Service Dispatch Code fängt diese neue excep Sie gibt die generische (sichere) Nachricht an den externen Aufrufer zurück und protokolliert die interne interne Ablaufverfolgung für die vollständige Ausnahme einschließlich der Ursache (unserem ursprünglichen benutzerdefinierten Ausnahmetyp). Das Problem ist jetzt, dass das zusätzliche Feld in CustomException aus den Protokollen verschwunden ist, da das Protokollierungsframework nur an getMessage() und dem Callstack interessiert ist.

try { // call to the ServiceHandler 
    sendResponseToClient(findServiceHandler(rpcName).handle(args)); 
} catch (Throwable th) { 
    LOGGER.error(th); 
    sendErrorToClient("An internal error occurred with incident ID: <id>"); 
} 

kann ich denke an ein paar Lösungen:

1) die Sache machen, dass die Service-Ausnahmen bewusst dieser besonderen Ausnahmetyp protokolliert, so kann es log es

2) außer Kraft setzengetMessage() so gibt es super.getMessage() + getAdditionalInfo()

3) Überall etwas heißt, dass eine dieser werfen konnte ich erneut auslösen es als etwas anderes mit dem zusätzlichen Feld in die Nachricht gebacken:

try { 
    something(); 
} catch (CustomException ce) { 
    throw new OperationFailedException("The operation failed because " + ce.getAdditionalInfo(), ce); 
} catch (RuntimeException e) { 
    throw new OperationFailedException("The operation failed", e); 
} 

Der eigentliche Anwendungsfall ist eine native Code-Bibliothek mit einem paar hundert Funktionen, und sie sind buchstäblich überall in dieser App aufgerufen. Dieser Ausnahmetyp ist ein allgemeiner Fehler "die API ist in unerwarteter Weise ausgefallen", daher ist sie deaktiviert, und im täglichen Betrieb würde ich nicht erwarten, jemals einen zu sehen.

(1) scheint, dass es leicht ist, neue Typen in Zukunft zu verpassen, wenn jemand in einem Jahr einen anderen benutzerdefinierten Ausnahmetyp hinzufügt, der alle Orte protokolliert und den entsprechenden Handler-Code schreibt Dort. (2) fühlt sich etwas faul an, da Sie mit einer Nachricht eine Ausnahme erstellen und eine andere Nachricht zurückbekommen würden. Wenn man das Muster in (3) anwendet, scheint es eine Menge Unordnung zu erzeugen, besonders wenn ich ein paar dieser benutzerdefinierten Ausnahmetypen habe, um die ich mich sorgen muss.

Welchen Ansatz sollte ich verwenden? Gibt es andere Möglichkeiten, oder würden Sie eine Umstrukturierung empfehlen, um dies zu umgehen?

+0

Warum schreiben Sie nicht einfach die zusätzlichen Informationen in die Nachricht? Oder wenn das nicht möglich ist, würde ich 2) gehen – NickL

Antwort

0

Es gibt im Wesentlichen zwei Fällen eine Ausnahme:

1) können Sie sich erholen

2) Sie können nicht, Sie wollen einfach nur Ihre Anwendung

verlassen Wenn Sie sich erholen können, Sie Vielleicht möchten Sie darüber nachdenken, eine geprüfte Ausnahme zu verwenden. Dann haben Sie haben, um mit der Ausnahme umzugehen, und der Compiler wird Ihnen sagen, wo Sie es fangen können.

Andernfalls, wenn die Anwendung nur abstürzt, möchten Sie möglicherweise diese zusätzliche Informationen zu der Nachricht hinzufügen, die Sie dem Superklassenkonstruktor geben.

Verwandte Themen