Object-oriented – How to output exception messages in GUI applications in order to decouple application code to GUI code

couplingexceptionsguiobject-oriented

I want to make GUI applications such that the non-GUI code is independent from the GUI one (let's say I'll use Java 8 and Swing for example). The goal is that I could hypothetically change the GUI API/library, or the kind of UI, for example shifting from a GUI to a console output, without modifying the non-GUI code (also in observance of the Open/Closed principle).

In particular, my question is about how to handle exception messages so that they can be output to any UI: let's say that I have try/catch blocks in my non-GUI code, like this (in the example I'm using Java but the language is irrelevant):


try {
    do something;
} catch (AnException e) {
    System.err.println("Exception message");
}

Obviously the println wouldn't be executed in the GUI, so the user would be unaware of the message. My goal is to show the exception message through the GUI. A simple way would be to swap the println for a GUI print method, but doing this my code wouldn't be independent from the GUI. How to solve this problem? Which is the standard approach (if there's such a thing) to deal with this problem?

The question can be generalized to any kind of output message in non-interface-related code.

Best Answer

There are different ways of dealing with the described situation. And before you start a "best practice"-debate - none of them is "better" than the others in general, you need to evaluate which one fits best to your case.

A simple solution for the case of an "exception" is by simply not catching the exception in some non-GUI code and let it bubble up to the GUI layer, which then catches and displays it. That is what exceptions are primarily made for - they can be thrown at place where the code cannot handle or output them, and catched upstream at a place where this is possible.

If this is not sufficient because you want the non-GUI code to generate the exception message, catch the original exception and rethrow one with a better text:

try {
    do something;
} catch (AnException e) {
    throw new AnotherException("My specific exception message");
}

A more general solution was scetched by Robert Harvey in the comments: the idea of using "callbacks". The calling "GUI" provides a functional callback for a certain output function (in form of an interface implementation, or by using the functional programming concepts from Java 8). The callback is passed to the non-GUI code which then calls it whenever it wants to output some text.

There is well-known an architectural pattern which utilizes these techniques to make a full separation between a GUI-framework dependendent layer and a framework-independent layer, it is called Model-View-Presenter. The (GUI-framework dependent) View implements a full interface for all basic UI functionality, but does not provide any UI logic. The UI logic is located in the Presenter class instead, which requires an instance of this interface and makes use of it to control the UI. That way, the Presenter is not bound to a specific UI framework. Maybe that is what you are looking for.

Related Topic