Exception Registry

Copyright 2003,2020 Nikolas S. Boyd. All rights reserved. Nik Boyd

Exception Registry

Object Structural

Intent

Convert an elaborate set of legacy system exception codes to an hierarchy of classified exceptions.

Motivation

Legacy software systems often lack the benefits of object-oriented technologies. One impact of this can be seen in how they surface exceptions through their public interfaces. Legacy system interfaces often include an elaborate, complex set of exception codes. This can complicate the integration of a legacy system with one designed with object-oriented technologies, even when the legacy system is integrated using some wrapper object(s).

Legacy exception indicators are often returned as coded values. Such exception codes do not support convenient organization and handling of the exceptions. The client becomes encumbered with behavior for filtering the returned codes to handle those few in which it has an interest. The exception codes may have evolved in an ad-hoc fashion. At worst, the encoding of exception values is arbitrary, with little or no planning beyond the recognition that problems arise in the server that need to be handled somehow by the client. The set of legacy exception codes can be filtered or summarized in the legacy system wrapper, but the level of detail required by each prospective client will often be unpredictable. Translating the exception codes into thrown exceptions will usually be a better alternative.

Many modern object-oriented programming languages provide syntactic support for exception handling – e.g., C++ and Java. These built-in language mechanisms provide a convenient programming model for distinguishing between normal behavior and exceptional situations. The best exception models allow the design and use of exceptions as classes. This model allows the exceptions to be organized into hierarchies. The client benefits by being able to focus only on those broad or narrow classes of exceptions in which it has an interest. Thus, the server will raise detailed exceptions, while the client can “listen” for specific or general exceptions, or choose to ignore certain kinds of exceptions altogether.

Given a well-defined exception mechanism, it is possible to establish an ExceptionRegistry that contains a set of RegisteredExceptions. Each exception code can be mapped to an exception class. For each unique exceptional condition, a corresponding kind of SpecificException class is defined. The exception classes can then be organized into a classification hierarchy. This usually requires the addition of new classes that generalize some of the exceptions.

For a static exception map, each SpecificException class has a single instance registered in the ExceptionRegistry. When an exception code is returned from a legacy function, the wrapper locates the corresponding exception instance in the ExceptionRegistry in order to throw it. The wrapper clients can then choose which kinds of exceptions they will handle based on the organization of the exception hierarchy.

Applicability

Use the Exception Registry pattern when

  • you need some wrapper(s) for a legacy system, especially one without benefit of an object-oriented design.
  • the legacy system indicates problems using return values, and each value identifies a specific kind of exception.
  • you want to map the set of exception codes returned by the legacy system into a hierarchy of exceptions.

Structure

except

Participants

  • ExceptionRegistry
    – maps each exception code to a RegisteredException.

  • RegisteredException
    – serves as a common base class for a set of legacy exception classes.
    – registers each derived exception class instance during its construction.

  • SpecificException
    – identifies a specific kind of legacy exception.
    – indicates a specific kind of legacy exception occurred when thrown.

  • LegacySystemWrapper
    – wraps and objectifies the legacy system.
    – locates registered exceptions based on their legacy exception codes.
    – throws an exception when the legacy system returns an exception code.

  • LegacySystem
    – provides a service through a public interface.
    – surfaces exceptions using coded return values.

Collaborations

  • During construction, the LegacySystemWrapper instantiates all the SpecificException classes.
  • During construction, each SpecificException instance registers itself in the ExceptionRegistry.
  • The Client uses the LegacySystemWrapper to access a service provided by a LegacySystem.
  • The LegacySystem detects an exception and returns an exception indicator.
  • The LegacySystemWrapper supplies the exception indicator to the ExceptionRegistry.
  • The ExceptionRegistry maps the exception indicator to a SpecificException.
  • The LegacySystemWrapper throws the SpecificException instance.

Consequences

The Exception Registry pattern has the following consequences:

  1. Uniform Exception Handling. The ExceptionRegistry maps all returned exception values to classified exceptions. The LegacySystemWrapper need not concern itself with how exceptions are presented to its Clients. The LegacySystemWrapper simply uses the ExceptionRegistry to identify the appropriate kind of exception and throw it. The LegacySystemWrapper can surface all the exceptions returned by the LegacySystem without concern for whether they will be used by any particular Client.

  2. Simpler Code. Clients no longer need to have elaborate code for detecting the exceptions in which they are interested. They can simply use the standard exception handling mechanism available in the programming language to catch those exceptions they need to handle. Unhandled exceptions will be dealt with by whatever means is standard for the platform.

Implementation

  1. Uniquely Identifiable Exceptions. Exception codes which adhere to a consistent identification scheme are the easiest to map. Each exception code serves as an unique key used to identify and look up an instance of a SpecificException class. When instantiated during the construction phase, each SpecificException registers itself in the ExceptionRegistry using its unique identifier, i.e. its exception code value.

  2. Multiple Exceptions. Sometimes, a legacy system will return multiple exceptions encoded into a single value or a returned data structure. In this case, the LegacyWrapper can apply one of the following strategies as appropriate:

    1. Exception Prioritization. If the possible exceptions can be prioritized and only one of them needs to be indicated to the caller, the LegacyWrapper can apply the rules for prioritizing the exceptions, look up the most important one using the ExceptionRegistry, and throw it.

    2. Exception Aggregation. If all the exceptions are equally important and need to be available to the caller, the LegacyWrapper can throw an AggregatedException class that contains a collection of all the SpecificExceptions returned by the LegacySystem. Each SpecificException is still identified and looked up using the ExceptionRegistry.

Legacy Candidates

The following systems have elaborate exception codes:

  • The ISO 7816-41 standard defines an elaborate set of result codes for response APDUs resulting from command APDUs issued against compliant Smart Cards.

  • The Microsoft Windows APIs2 have an elaborate set of system error codes returned accessed via the GetLastErr() function.

Related Patterns

  • Singleton.3 The ExceptionRegistry class will usually be a singleton, as will each kind of SpecificException. The specific exceptions should be Singletons rather than Flyweights so that the standard exception handling mechanism of the programming language may be used to resolve the appropriate exception handler when each exception is thrown.

References

  1. International Standards Organization. Information technology — Identification cards — Integrated circuit(s) cards with contacts — Part 4: Interindustry commands for interchange. ISO 7816-4, 1995.
  2. Microsoft. Windows Application Programming Interface. Microsoft Developer Network.
  3. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley Publishing, Inc., 1995. ISBN 0-201-63361-2.