Thanks
At the OOA/D level all you need is a relationship path to navigate. That
path may have multiple binary segments between individual classes. For
example:
* R3 throws to 1
[Customer] ------------------- [ErrorLog]
| 1
|
| R1
|
| places
| *
[Order]
| 1
|
| R2
|
| contains
| *
[LineItem]
+ addDiscount()
If a problem occurs during processing in LineItem::addDiscount, one can
navigate R2 -> R1 -> R3 to get to the [ErrorLog]. All you have to ensure
through relationship instantiation is that there is always a valid path
instantiated between any object that may have an error and the error log
object.
Note that this is quite abstract. That is because exception processing
is highly implementation dependent. In practice you might put a handler
in [Customer] that actually talks to [ErrorLog] and the navigation R2 ->
R1 might be automated via a language-specific implementation of 'throw'
that uses the call stack.
Because of that implementation dependence, one does not normally provide
explicit exception processing in OOA/D models. Instead one just provides
placeholders for any unique objects needed as part of the recovery. In a
fault tolerant application you will probably need an object to
encapsulate the specific recovery rules and policies that are unique to
the problem in hand.
When error handling is a major consideration in the application, one can
provide a Handler object to field the error messages. Since those
messages will usually come from the OS or the 3GL language
infrastructure, one can consider them as external events to the
subsystem. For example, sending an event to the outside world maps
conveniently to 'try'/'throw' in a specific OOPL and triggering the
handler by the OS or language infrastructure maps conveniently to an
incoming external event dispatched by the subsystem interface to the
Handler. One advantage of this is that one can provide different
handlers for different problems with the same model infrastructure
(e.g., different instances of the [Handler] class).
If one does this, though, I would advise keeping the handler simple. If
there is complex recovery processing I would delegate it to objects like
your ErrorLog. Those objects would, in turn, have relationships to any
objects that need to be twiddled during the recovery. IOW, one should
separate the concerns of exception mechanics and actual recovery rules
and policies since the exception mechanics will be
implementation-dependent while the recovery will be problem
space-specific. Note that patterns like the GoF Strategy can be useful
for this, as in:
[Handler]
| *
|
| R1
|
| delegates to
| 1
[ErrorRecoveryStrategy]
A
| R2
+-------------+---....
| |
[Abort] [Cleanup]
| 1
|
| R3
|
| resets
| *
[Customer]
Here [Handler] has no direct relationships with other problem objects
because it is triggered by an external event. It just encapsulates a
mechanism for exception event mechanics. The actual recovery is
delegated to [ErrorRecoveryStrategy]. Then R3 represents relationships
with the objects that a recovery needs to process.
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
h...@pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
in...@pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
eg throw (CustomException). Every class may be throwing this
exception or one of its derivatives.
> Hi, thats great. Just one issue i need clarity. If the various
> objects are throwing a particular exception object - as opposed
> to the handler. Should this exception class be shown on the diagram.
> ie CustomException is maybe part of a hierarchy.
It depends. B-) If the object is primarily an implementation object
(i.e., it exists because it makes it easier to use the exception
handling facilities provided by the language or OS), then it probably
doesn't need to be explicit in the OOA/D model. OTOH, if the object is a
critical part of some unique exception handling strategy that is
important to the problem in hand (e.g., exception processing has high
priority in the requirements), then it should probably be explicitly
identified along with the rest of the strategy.
Sorry to be vague, but there are no cookbook rules. Deciding what needs
to be abstracted one a case-by-case basis is one of the reasons OO
designers get the Big Bucks. B-)