Handling Failure - UML

The preceding design provides a solution for client - side caching of ProductDescription objects in a persistent file, to improve performance, and also to provide at least a partial fall - back solution if the external products service can't be accessed. Perhaps 10,000 products are cached in the local file, which may satisfy most requests for product information even when the external service fails.

What to do in the case where there isn't a local cache hit and access to the external products service fails? Suppose that the stakeholders asked us create a solution that signals the cashier to manually enter the price and description, or cancel the line item entry.

Figure 36.7 Threads and asynchronous messages in the UML

Figure 36.8 Active class notation

This is an example of an error or failure condition, and it will be used as a context to describe some general patterns in dealing with failures and exception handling. Exception and error handling is a large topic, and this introduction will just focus on some patterns specific to the context of the case study. First, some terminology:

  1. Fault :- the ultimate origin or cause of misbehavior.
    • Programmer misspelled the name of a database.
  2. Error :- a manifestation of the fault in the running system. Errors are detected (or not).
    • When calling the naming service to obtain a reference to the database (with the misspelled name), it signals an error.
  3. Failure :- a denial of service caused by an error.
    • The Products subsystem (and the NextGen POS) fails to provide a product information service.

Throwing Exceptions

A straightforward approach to signaling the failure under consideration is to throw an exception.

Guideline : Exceptions are especially appropriate when dealing with resource failures (disk, memory, network or database access, and other external services).

An exception will be thrown from within the persistence subsystem (actually. probably starting from within something like a Java JDBC implementation i. where a failure to use the external products database is first detected. The exception will unwind the call stack back up to an appropriate point for its handling.

Suppose that the original exception (using Java as an example) is a
java.sql.SQLException. Should a SQLException per se be thrown all the way up to the presentation layer? No. It is at the wrong level of abstraction. This leads to a common exception handling pattern:

Pattern: Convert Exceptions [BrownOl]

Within a subsystem, avoid emitting lower level exceptions coming from lower subsystems or services. Rather, convert the lower level exception into one that is meaningful at the level of the subsystem. The higher level exception usually wraps the lower - level exception, and adds information, to make the exception more contextually meaningful to the higher level.

This is a guideline, not an absolute rule. "Exception" is used here in the vernacular sense of something that can be thrown; in Java, the equivalent is a Throwable.

Also known as Exception Abstraction [Renzel97].

For example, the persistence subsystem catches a particular SQLException, and (assuming it can't handle it) throws a new DBUnavailableException, which contains the SQLException. Note that the DBProductAdapter is like a facade onto a logical subsystem for product information. Thus, the higher level DBProductAdapter (as the representative for a logical subsystem) catches the lower level DBUnavailableException and (assuming it can't handle it) throws a new ProductlnfoUnavailableException, which wraps the DBUnavailableException.

Consider the names of these exceptions: Why DBUnavailableException rather than, say, PersistenceSubsystemException? There is a pattern for this:

Pattern: Name The Problem Not The Thrower [GrossoOO]

What to call an exception? Assign a name that describes why the exception is being thrown, not the thrower. The benefit is that it makes it easier for the programmer to understand the problem, and it the highlights the essential similarity of many classes of exceptions (in a way that naming the thrower does not).

Exceptions in the UML

  1. In a class diagram, how to show what exceptions a class catches and throws?
  2. In an interaction diagram, how to show throwing an exception? For a class diagram, Figure presents the notation:

Figure 36.9 Exceptions caught and thrown by a class

In the UML, an Exception is a specialization of a Signal, which is the specification of an asynchronous communication between objects. This means that in interaction diagrams, exceptions are illustrated as asynchronous messages.

Figure shows the notation, using the prior description of SQLException translated to DBUnavailableException as an example.

Figure 36.10 Exceptions in an interaction diagram

In summary, UML notation exists to show exceptions. However, it is rarely used.

This is not a recommendation to avoid early consideration of exception handling, Quite the opposite: At an architectural level, the basic patterns, policies, and collaborations for exception handling need to be established early, because it is awkward to insert exception handling as an afterthought. However, the low - level design of handling particular exceptions is felt by many developers to be most appropriately decided during programming or via less detailed design descriptions, rather than via detailed UML diagrams.

Handling Errors

One side of the.design has been considered: throwing exceptions, in terms of converting, naming, and illustrating them. The other side is the handling of an exception.

Two patterns to apply in this and most cases are:

Pattern: Centralized Error Logging [Renzel97]

Use a Singleton - accessed central error logging object and report all exceptions to it. If it is a distributed system, each local singleton will collaborate with a central error logger. Benefits:

  1. Consistency in reporting.
  2. Flexible definition of output streams and format. Also known as Diagnostic Logger [Harrison98].

It is a simple pattern. The second is:

Pattern: Error Dialog [Renzel97]

Use a standard Singleton - accessed, application - independent, non - UI object to notify users of errors. It wraps one or more UI "dialog" objects (such as a GUI modal dialog, text console, sound beeper, or speech generator) and delegates the notification of the error to the UI objects. Thus, output could go to both a GUI dialog and to a speech generator. It will also report the exception to the centralized error logger. A Factory reading from system parameters will create the appropriate UI objects. Benefits:

  1. Protected Variations with respect to changes in the output mechanism.
  2. Consistent style of error reporting; for example, all GUI windows can call on this singleton to display the error dialog.
  3. Centralized control of the common strategy for error notification.
  4. Minor performance gain; if an "expensive" resource such as a GUI dialog is used, it is easy to hide and cache it for recycled use, rather than recreate a dialog for each error.

Should a UI object (for example, ProcessSaleFrame) handle an error by catching the exception and notifying the user? For applications with only a few windows.and simple, stable navigation paths between windows, this straightforward design is fine. This is currently true for the NextGen application.

Keep in mind, however, that this places some "application logic" related to error handling in the presentation (GUI) layer. The error handling relates to user notification, so this is logical, but it is a trend to watch. It is not inherently a problem for simple UIs with a low chance of UI replacement, but it is a point of fragility. For example, suppose a team wants to replace a Java Swing UI with the IBM Java Micro View GUI framework for handheld computers.

There is now some application logic in the Swing version that has to be identified and replicated in the Micro View version. To some degree, this is inevitable with 01 replacements; but it will be aggravated as more application logic migrates upwards. In general, as more non - UI application logic responsibilities migrate to the presentation layer, the probability of design or maintenance headaches increases.

For systems with many windows and complex (perhaps even changing) navigation paths, there are other solutions. For example, an application layer of one or more controllers can be inserted between the presentation and domain layers.

Furthermore, a "view manager mediator" object [GHJV95, BMRSS96] that is responsible for having a reference to all open windows, and knowing the transitions between windows, given some event El (such as an error), can be inserted.

This mediator is abstractly a state machine that encapsulates the states (displayed window) and transitions between states, based on events. It may read the state (window) transition model from an external file, so that the navigation paths can be data - driven (source code changes are not necessary). It can also close all the application windows, or tile or minimize them, since it has a reference to all windows.

In this design, an application layer controller may be designed with a reference to this view manager mediator (hence, the application controller is coupled "upwards" to the presentation layer). The application controller may catch the exception and collaborate with the view manager mediator to cause notification (based on the Error Dialog pattern). In this way, the application controller is involved with workflow for the application, and some error logic handling is kept out of the windows.

Detailed UI control and navigation design is outside the scope of this introduction, and the simple design of the window catching the exception will suffice. A design using an Error Dialog is shown in Figure.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

UML Topics