Re: Some same exceptions used in a given file
Merciadri Luca wrote:
Thanks for the example. And now if another method of the same class
throws also an IOException, but whose action needs not to be the same?
For example, how would I convert
==
public void foo
{
try
{
// ...
}
catch (IOException problem1)
{
}
}
public void bar
{
try
{
// ...
}
catch (IOException problem2)
{
}
}
==
?
I might do
==
public void foo throws IOException
{
// ...
}
public void bar throws IOException
{
// ...
}
==
and then catch the exception in the caller, but how do I differentiate
from problem1 to problem2? Sorry for this silly question, but it seems
not that habitual regarding Google answers on this.
There are a few approaches.
Right now you're starting from the leaf level of how to implement try-catch
and trying to glean an overall strategy. A better approach is the exact
opposite: Decide on your overall *application-domain* strategy first.
As you code in various layers of your application, think of a type as part of
the internal API for the application - a one-shot library. Good O-O
principles dictate that a compoment have a well-defined purpose and external
contract for interaction with other components. None of those strategic
conversations involve exceptions as such - just conditions and desired
responses and state transitions involving those conditions.
At the nitty-gritty detail level of implementation, OTOH, exceptions signal
out-of-band issues - things that stop the action. But their effect is local -
not strategic, but specific to a particular action in service of that
strategic effect. Since the strategic conversation is exception-agnostic, the
component must convert that exceptional condition into the appropriate
response that accords with its contract for interaction.
That contract varies with the layer involved. If the layer is a deeper one,
say a data-access layer (DAL), it functions exactly like an API. Again,
define its contract from the outside - what should API clients experience?
Sometimes that means that a particular API method has an 'Exception' subtype
as part of its contract. But that is dictated by the strategic purpose of the
API, not by knee-jerk, thoughtless reactions to lower-level events.
That upward view often comprises an application-specific exception, one that
tells the application "something lower broke", and then uses the 'cause'
attribute to say what.
How fine-grained does the top level view have to be, for Pete's sake? Why be
so obsessive-compulsive?
Usually the 'cause' chain and stack trace contains everything needed for
debugging, and nothing needed for the strategic upline viewpoint. Usually.
So here's how you convert low-level exceptions to higher-level ones, if (and
only if) that's what your strategy requires:
public void actByContract( Foo stimulus ) throws LewsException
{
BufferedReader reader;
try
{
reader = new BufferedReader( new FileReader( stimulus.getFile() ));
}
catch ( IOException exc )
{
final String msg = "actByContract() broke";
logger.error( msg, exc );
LewsException lewx = new LewsException( msg, exc );
throw lewx;
}
)
Key points:
- Log and act upon exceptions at the lowest point they occur, if they aren't
one of your own wrapper exceptions like 'LewsException'.
- Don't let exceptions walk all the way out of an application or lower-level
exceptions out of a component - convert them to some strategically valid,
contract-authorized interactions with outsiders.
- Do determine the strategically and contractually valid interactions for
the application and every component, first, before implementation.
- Do allow only strategically and contractually valid interactions to occur
and none other.
--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg