t is better to list the guidelines 1] that we will pursue while designing exception hierarchy of our system.
From 1 above, First of all, if we analyze possible exceptions that system can generate, we can come up with a classification, which makes things easier. Nearly every package in the system (see packaging information?) consists of two basic operations; Formation and Service.
Formation refers to the processes in which instances of components (Calendar, Property, etc.) are formed via parsing files, which are generally pointed by URLs. In fact, initializing components consists further sub-elements. For example; parsing XML files, trying to load dynamic classes, etc.So, any abnormal conditions caused during these processes will be referred as FormationExceptions.
Service refers to processes in which components provide unique behaviors via their methods. As in Formation, this operation also consists of sub-elements. For example; dynamically loaded method calls, component search, update, remove method calls, etc. So, any abnormal conditions caused during these processes will be referred as ServiceExceptions.
From 2 above, A method is certainly allowed to return null or 0 when it can not find a component or find 0 number of components. This is generally true for parsing APIs, and exceptions are detected and thrown in higher levels.
From 3 above, It would be better to form or use an existing exception class for each kind of abnormal condition that may cause an exception to be thrown. So, a basic hierarchical exception structure (such as explained above) might obviously be specialized by adding leaf or node exceptions.
From 4 above, If we allow unchecked exceptions, in which a user does not have to be concerned, program will exit abruptly, therefore loosing all previous successfully loaded components (CalendricSystems, Calendars, etc.). This is due to persistency lack of the system.
Now let's look at Exception Hierarchy Design of the system under above circumstances. General hierarchy tree will look like;
(X refers to a component name, such as; Calendar, CalendricSystem, etc.)
According to above hierarchy other components will look like (A bold item means it can be further specialized under its node);
Calendar
Property
Field
CalendricSystem
TemporalDataTypes
And obviously all these Exceptions will be under a tauzamanException root node.
The main idea is that, a parent component will throw its Exceptions, no matter what other components throw when parent calls them and an abnormal situation occurs. For example; When forming a CalendricSystem via a URL, it does not give much understanding to user if PropertyFormationException is thrown. Instead a CalendricSystemFormationException is thrown embellished with information from PropertyFormationException.
According to all above ideas, here are two alternatives to Exception Handling of tauzaman;
1. see Design 1. Advantages of this design are:
try{...} catch(XException e){...}
2. see Design 2
try{...} catch(tauzamanXException e){...}
Design 1 is chosen to be implemented.
Exceptions on Registration Process
Registration Exceptions for the system added later. Here is the design decisions and rationale for them;
We could possibly from a RegistrationException class and include every specific message inside it. However, this is not what we intended to do form the beginning, since any exception can also be caught by catching CalendricSystemException anyway. So, to be specific about exceptions, which also clears the try and catch code, we specialized each individual and meaningful exceptions.
There were mainly three options; one of them extending new exceptions under the branch of CalendricSystemException, second, we could extend it under the branch of CalendricSystemServiceException and the last one is to extend it under the branch of tauzamanException as an individual exception. Not to add to many branches, which makes design and implementation hard to handle, first option is excluded, and last option seems to be abstract and violates Service and Formation exception understanding. The fact that all registration processes involve with Calendric Systems made us to choose second option. (see design issues related to user registration)
Exception Chaining
For precise back tracing of exceptions, all levels of (including Low Level ones) Exceptions will include a cause throwable object in their constructors along with a String message, which consists of the detailed explanation of the error. The reason even the Low Level Exceptions have causes in their constructors is that, there is in fact one lower level of exceptions, namely Lowest Level Exceptions, which are produced by Java itself and not dependent to our system. For example; MalformedURLException, Exceptions of ClassLoader and XML Parser classes. As a design decision, we don't want to throw these Exceptions to the user directly. These exceptions will be thrown by wrapping them inside more meaningful exceptions for the user. So, design criteria about exception chaining is;
Note: XFormationExceptions could have a specialized element called, ElementNotFoundException, which would also take just a String argument.
However, because of the following reasons, yet another exception hierarchy will be employed (idea will be still same);
3. see Design3.
References:
[1] Venners, B. Designing with Exceptions. On-line; http://www.javaworld.com/javaworld/jw-07-1998/jw-07-techniques.html