My exception handling skills are very primary and I am always very confused about the way I should use them, not so much of the how/syntax. I am currently using C# (if there would be different things applicable to it).
My question is that what are the benefits of creating your own Exception class while developing an application? In comparison to throwing a standard Exception class exception. Basically what is a healthy practice of exceptions in your application.
Or if not benefits, then disadvantages?
By creating your own exceptions you can often create a more meaningful message (or more application specific type of message) for the end user, while still wrapping the original message, so as not to lose any useful information.
There is a great book by Bill Wagner that covers some reasoning about when you should or should not create your own exceptions along with some good practices for exception handling in general. Here is a small excerpt:
Your application will throw exceptions -- hopefully not often, but it
will happen. If you don't do anything specifc, your application will
generate the default .NET Framework exceptions whenever something goes
wrong in the methods you call on the core framework. Providing more
detailed information will go a long way to enabling you and your users
to diagnose and possibly correct errors in the field. You create
different exception classes when different corrective actions are
possible and only when different actions are possible. You create
full-featured exception classes by providing all the constructors that
the base exception class supports. You use the InnerException property
to carry along all the error information generated by lower-level
error conditions.
If there is a specific type of problem unique to your application that will call for a unique recovery strategy at a higher level in your application, you should create your own exception type so you can recognize and recover from that sort of problem optimally.
If the error is more of a "the caller did something wrong" variety, use the standard exception classes.
If you think your library is going to be long-lived and valuable, I would err on the side of creating your own exception classes, so that future users of your library can fashion their own recovery strategy.
Sometimes you want to do diffrent things for diffrent types of error, for example if a user inputs bad data it dosent make sence to crash the whole application and email the administrator. It would make sence to do that for a more serious exeption such as a stack overflow. You would then impliment diffrent catches depending on the type of error.
If a method is documented as throwing some particular class of exception in some particular circumstance, it should ensure that there's no way any exception of the class can bubble up through it in other circumstances. In many cases, the most practical way to ensure this may be to create a custom exception class.
Actually, I would regard much of the exception hierarchy as being pretty useless, and would suggest focusing on a fairly small number of exceptions, from which nearly all good exceptions should derive.
CleanFailureException -- The indicated operation could not be performed for some reason, but has not altered any object's state. There is no reason to believe any object's state is corrupt except to the extent implied by the operation's failure. This should be the type of exception thrown by a DoSomething method if a TrySomething method would return False. May in some cases be wrapped in a more severe instruction, if a failed operation leaves one or more objects in partially-altered or inconsistent states.
StateDisturbedException -- The indicated operation could not be completely performed for some reason, but may have been partially performed. The object on which an action was being performed has a state which complies with its own invariants, but may or may not comply with caller's expectations of it. Caller may attempt to use the object only after examining it and making sure it complies with expectations (changing it as needed). Alternatively, this exception should be caught at the point where the target object would no longer exist, and then wrapped in a CleanFailureException.
TargetStateCorruptException -- The indicated operation could not be performed because the particular object being acted upon is corrupt, but there is no particular reason to expect that corruption extends outside the object. This exception should be caught at the point where the target object would no longer exist, and then wrapped and replaced with CleanFailureException.
ParentStateCorruptException -- The indicated operation could not be performed because some object which the target's documentation would regard as a "parent" object is corrupt. Catch at the level where the corrupt parent objects would no longer exist, then wrap in a "CleanFailureException".
SystemOnFireException
While it may be nice to have exception names that indicate the nature of what went wrong, from a catching perspective what matters is whether one can safely catch and resume. Any exception hierarchy should focus on the latter issues, rather than the former. If the goal is to inform people of what went wrong, that should be done in Exception.Message.
The main benefits are to add information, so exceptions are more meaningful and thus allowing to catch exceptions that are specific to your application.
Throwing an exception is actually a more expensive operation than quietly failing, such as returning a bool. This question highlights what I mean:
How much more expensive is an Exception than a return value?
If you're writing something that you anticipate other developers are going to be using in their own project, then sure, an exception could be useful for them to make sure they're using your code right. Otherwise, if you're just using it within your own codebase, I would make sure to quietly fail.
One example where custom exceptions work well is when you are expecting external applications to interface with your project.
For example, if you had a small project that sends out an email it might make sense to throw a custom 'TooFewRecipients' error if you had a hard limit on the minimum number of recipients that must be emailed.
Custom exceptions will in general inherit from System.Exception
Remember that Exceptions should only be used for exceptional cases which your project can't handle in any other way, and they should be understandable enough to aid a 3rd party developer understand the issue. There is more information at MSDN
Related
I am reading some C# books, and got some exercise don't know how to do, or not sure what does the question mean.
Problem:
After working for a company for some time, your skills as a knowledgeable developer are recognized, and you are given the task of “policing” the implementation of exception handling and tracing in the source code (C#) for an enterprise application that is under constant incremental development. The two goals set by the product architect are:
100% of methods in the entire application must have at least a standard exception handler, using try/catch/finally blocks; more complex methods must also have additional exception handling for specific exceptions
All control flow code can optionally write “tracing” information to assist in debugging and instrumentation of the application at run-time in situations where traditional debuggers are not available (eg. on staging and production servers).
(I am not quite understand these criterias, I came from the java world, java has two kind of exception, check and unchecked exception. Developer must handle checked exception, and do logging. about unchecked exception, still do logging maybe, but most of the time we just throw it. however here comes to C#, what should I do?)
Question for Problem:
List rules you would create for the development team to follow, and the ways in which you would enforce rules, to achieve these goals.
How would you go about ensuring that all existing code complies with the rules specified by the product architect; in particular, what considerations would impact your planning for the work to ensure all existing code complies?
As you mentioned Java has checked and unchecked exceptions. For checked exceptions you have to either declare your method throws it, or handle the exception in the method. C# does not have that limitation, your method doesn't have to declare what exception it could possibly throw.
100% of methods in the entire application must have at least a standard exception handler, using try/catch/finally blocks; more complex methods must also have additional exception handling for specific exceptions
This seems like a stupid requirement. If you have no meaningful way to recover from an exception and continue executing normally, you would ideally allow the exception to bubble up the stack unimpeded. That way when you log the exception (right before shutting down gracefully, or not so gracefully) you'll have a full stack-trace of what exactly caused the exception. It is a very common mistake (from the code I've seen) to use pokemon exception handling and logging the exceptions too early (so you know something bad happened but not what piece of code triggered it.
You should also take a look at this list of similar question for a good overview of good exception handling practices.
And for good measure Vexing exceptions.
After you define your application architecture, you should determine how the exceptions generated by your application will be handled. The strategy should be to meet all security, privacy, and performance requirements. The following are general guidelines for an exception handling strategy:
Do not catch exceptions unless some kind of value can be added. In other words, if knowing about the exception is of no use to the user, to you, or to the application, do not catch it.
Do catch exceptions if you want to retry the operation, add relevant information to the exception, hide sensitive information contained in the exception, or display formatted information.
Generally, handle exceptions only at an application boundary (such as the top of a logical layer, tier, the boundary of a service, or at the top of a UI layer). Also, replace exceptions that contain sensitive information with new exceptions that contain information that can be exposed safely outside the current boundary.
Do not propagate sensitive information across trust boundaries. This is a standard security consideration, but it is frequently overlooked when dealing with exception information. Instead, replace exceptions that contain sensitive information with new exceptions that contain information that can be exposed safely outside the current boundary.
Make exceptions as accurate as possible and allow for specific actions to be taken when the exception is raised. Sometimes this may require writing custom exceptions with the required attributes.
Error messages that are displayed to users should be relevant and they should suggest the corrective action to take. In most cases, user-displayed error messages should never contain sensitive information, such as stack traces or server names.
I've dealt with instances where I would throw/rethrow an exception knowing that the code surrounding it would catch the specific exception. But is there any time you would want to throw an exception, knowing that it wouldn't be caught?
Or at least, NOT catch an exception?
Exceptions immediately halt the application unless their handled right? So I guess I'm asking if you would ever want to purposely let your application die?
If your application is primarily going to be used by other clients and is not standalone, it generally makes sense to throw exceptions if a condition arises that you don't know how to (or don't want to) handle, and there's no sensible way for you to recover from it. Clients should be able to decide how they want to handle any exceptions that you might throw.
On the other hand, if your application is the endpoint, throwing an exception essentially becomes a notification mechanism to alert people that something has gone terribly wrong. In such cases, you need to consider a few things:
How important is the continued running of the application? Is this error really unrecoverable? Throwing an exception and terminating your program is not something you want to be doing on the space shuttle.
Are you using exceptions as a proxy for real logging? There's almost never a reason to do this; consider a real logging mechanism instead. Catch the exception and have the logger work out what happened.
What are you trying to convey by throwing the exception yourself? Ask yourself what the value in throwing a new exception is, and consider carefully whether there isn't a better way to do what you want.
Not catching an exception may leave resources in a bad state. If you don't gracefully exit, things are generally not cleaned up for you. Make sure you understand what you're doing if you need to do this -- and if you're not going to catch it, at least consider a try-finally block so you can do some tidying up.
There's a very good rule that I came across a while ago:
Throw an exception when a method can't do what its name says it does.
The idea is that an exception indicates that something has gone wrong. When you are implementing a method, it is not your responsibility to be aware of whether it will be used correctly or not. Whether the code using your method catches the exception or not is not your responsibility, but the responsibility of the person using your method.
Another rule to follow is:
Don't catch an exception unless you know what you want to do with it.
Obviously, you should include cleanup code in a try...finally block, but you should never just catch an exception just for the sake of catching it. And you should never swallow exceptions silently. While there are occasions when you may want to catch all exceptions (e.g. by doing catch (Exception ex) in C#), these are fairly uncommon and generally have a very specific technical reason. For example, when you are using threads in .NET 2.0 or later, if an exception escapes from your thread, it will cause the entire application domain to unload. In these cases, however, at the very minimum you should log the exception details as an error and provide an explanation in the comments.
Sure. For example, if you're trying to load some bytes into a string in Java:
try {
String myString = new String(byteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
// Platform doesn't support UTF-8? What is this, 1991?
throw new RuntimeExceptione(e);
}
In this case, there is no graceful degradation, the platform simply can't support the operation desired. You can check for this condition at initialization all you want, but the constructor for String still throws this exception, and you have to deal with it. Either that, or use Charset.forName() :)
Generally, and certainly in early iterations of your application, don't catch the exception. More often than not, the recovery from an exception will require a business rule of some sort, and, more often than not, those business rules are not defined for you. If you "handle" the exception instead of letting the application die then you will most likely be inventing business rules for your customer. Not good.
The general pattern of catching every exception just for the sake of catching it has caused me more headaches than I can count. It usually happens that someone puts some sort of generic exception handling code throughout the application, which inevitably ends up hiding a bug or creating some behavior that is unwanted. (incidentally, catching and then not rethrowing is even worse.)
So, I'd suggest that you ask instead: "When should I catch an exception?"
Here's the thing ... it is about "layers", or "encapsulation", or "low coupling". At some place in your codebase, you're writing a method to do something. Say it's a public method. Therefore, it should not assume much or anything about the caller ... rather, it should merely do the job it is supposed to do, regardless of who is calling it and what context the caller is in.
And if, for some reason, it cannot complete its job, then it needs to tell the caller "Sorry, I couldn't do that, and here's why". Exceptions are an excellent mechanism to let it tell the caller that (not the only mechanism, but the best mechanism I've ever seen for most cases).
So, when you throw the exception, you have no idea whether it will be caught or not ... because you're exposing a public method and you have no idea who might choose to call it and why.
The catching of the exception is the job of the "context". For example, say you're writing a library with public methods that might throw exceptions. Then, say you're using that library from a Windows Forms app. The Windows Forms app might catch exceptions and show a message box to the user.
But later, you might use the same library from a Windows Service. The Service would be more likely to catch the exception, log it, return an error to the original caller, but keep running so it can process further requests.
So the exception is like a contractual agreement between the caller and the provider. The provider says, "I'll either do the job or tell you why I can't. What you do from there is your own business." And the caller says, "OK, if you can't do the job, just tell me why, and I'll decide what to do in that case."
But is there any time you would want to throw an exception, knowing that it wouldn't be caught?
I would say that if you're manually throwing an exception, most of the time you don't know if it will be caught. If you knew it would be caught you could just handle it yourself rather than throwing the exception in the first place.
To be fair, I suppose that depends in part on the kind of programming you're doing, and sometimes the same programmer ends up building both the library and the code that consumes said library.
Would you ever NOT catch an exception?
If you didn't expect/weren't aware an exception could be thrown. But putting that aside and assuming you are aware of the exception, sometimes you know about it at one tier but know the next tier up is the more appropriate place to handle it.
It depends on the type of application. Web applications can continue running even after exceptions have bubbled up to the execution context.
It is common practice to 'throw/rethrow' an exception if you catch the exception at a level where it can't be dealt with. But, you would almost always add context to the issue, at the very least add some logging at the higher level to say that it was caught and rethrown.
for example
A calls B calls C (throws exception)
B catches/rethrows
A catches.
In this case, you would want B to add some logging so that you can differentiate between B generating and throwing an error, and C generating and throwing an error. That would allow you a greater ability to debug and fix problems later.
In general you will almost NEVER want an exception to kill your program. The best practice is to catch the except and exit gracefully. This allows you to save any currently open information and release resources that are being used so they don't become corrupted. If you intend to exit, you can create your own 'core-dump' information report that includes the things you were doing when you caught the fatal exception.
If you let the exception kill your process you are eliminating your chance to get custom tailored crash information, and you are also skipping the part where you provide the user with a friendly error message and then exit.
So, I would recommend ALWAYS catching exceptions, and never voluntarily letting them run amok in your program.
EDIT
If you are writing a library, you have to choose ahead of time whether your function will throw an exception, or be exception safe. In those cases, sometimes you will throw an exception and have no idea if the calling party will catch it. But in that case, catching it is not your responsibility, as long as the api declares that the function could throw exceptions.
(I'm looking for a word that means 'could possibly throw exception'... anyone know what it is? It's going to bug me all day.)
Firstly, there absolutely are situations where it is better to not catch an exception.
Sometimes, an exception can sometimes tell you that your program is in an unknown state. There are a number of exceptions where this is pretty much intrinsically true given the exception type. A NullReferenceException essentially tells you "there is a bug". And by catching such an exception, you may hide the bug, which sounds good in the short term, but in the long term you'd be happier to fix it. The product may not crash, but it certainly won't have the expected behaviour.
But this is also true for exception types we invent for ourselves. Sometimes, the fact that exception A has been thrown should be "impossible" - and yet it has happened, so there's a bug.
Also, something very important happens when you catch an exception: the finally blocks for the whole call stack inside the try block (and anything it calls) will be executed. What do those finally blocks do? Well, anything. And if the program is in an unknown state, I really do mean anything. They could erase valuable customer data from the disk. They could throw more exceptions. They could corrupt data in memory, making the bug impossible to diagnose.
So when an exception indicates an unknown state, you don't want to run any more code, so whatever you do, don't catch the exception. Let it fly past, and your program will terminate harmlessly, and Windows Error Reporting will be able to capture the state of the program as it was when the problem was originally detected. If you catch the exception, you will cause more code to execute, which will screw up the state of the program further.
Secondly, should you throw an exception knowing it won't be caught? I think that question misunderstands the nature of reusable methods. The whole idea of a method is that it has a "contract" that it follows: it accepts certain parameters and returns a certain value, plus also it throws certain exceptions under certain conditions. That's the contract - it's up to the caller what they do with it. For some callers, exception A might indicate a recoverable condition. For other callers, it might indicate a bug. And from what I said above, it should be clear that if an exception indicates a bug, it must not be caught.
And if you're wondering what this means for the Microsoft Enterprise Library's Exception Handling Block: yes, it's pretty broken. They tell you to catch (Exception x) and then decide whether to rethrow based on your policy; too late - the finally blocks have already executed by that point. Don't do that.
You probably wouldn't want an uncaught exception anywhere where the end-users can see it, but it is often acceptable to let clients of your API (other programmers) decide how to handle exceptions.
For example, suppose you are designing a Java class library. You expose a public method that takes in a String. In your application, a null input value would cause an error. Instead of handling the error yourself, it would be acceptable to check for a null value, then throw an IllegalArgumentException.
You must, of course, document that your method throws this exception in this circumstance. This behavior becomes part of your method's contract.
It depends on what you mean by 'being caught'. Something, somewhere eventually catches the exception whether it be the underlying OS or something else.
We have a workflow system that executes job plans comprised of individual jobs. Each job runs a unit of code. For some of the exceptions, we don't want to handle them in the code but throw it up the stack so that the external workflow system catches it (which happens completely outside of the thrower's process).
If you're writing the entire application, then your reasons are your own. I can think of a few situations where you might want to throw the exception and let the app die, most of them are not very good reasons though.
The best reason is usually when debugging. I frequently disable exceptions while debugging to allow me to know better where something is failing. You can also just turn on thrown exception breaks in the debugger if you're running it on a machine with the debugger.
Another possible reason is when continuing after an exception is thrown doesn't make sense or would result in possible irrecoverable data corruption or worse (think Robots with laser beams, but then you should be damn sure your applicaiton deals with these situations IMO, crashing the program is just the lazy way).
If you're writing API code, or Framework code that you won't use yourself, then you have no idea if someone will catch your exceptions.
Yup, it's my ONLY opportunity to slap the developer consuming the service/object to tell them "Ur dO1n it WrOnG!!!!".
That and getting rid of possibilities that you don't want to permit or are seemingly "impossible". Apps that catch all exceptions and continue are just a walled garden surrounded by chaos.
If I need a moderately large system that is somehow processing data in what I believe to be a consistent manner.
And
Somewhere along the line, I detect that the application's state has become inconsistent.
And
The system doesn't (yet) know how to fix the inconsistency and recover gracefully
Then, yes, I would throw an exception with as much detail as possible and cause the application to die as quickly as possible, to avoid doing any further harm to the data. If it can be recovered, it'd be important not to exacerbate the problem by trying feebly to cover up the mess.
Later along the line, once the chain of events that led to the inconsistency is better understood, I higher facility can catch that exception, repair the state, and continue with minimal interruption.
A library will often throw exceptions based on defensive programming checks, should a condition arise that shouldn't have been allowed to arise by the application code. Applications code will often be written such that most of those invalid conditions will never arise, and therefore the exceptions will never be thrown, so there's no point catching them.
Depending on language (I'm mostly thinking in terms of C++ rather than C#, and not that clear what the differences are) the effect of an uncaught exception actually being thrown is probably the same as what used to be done in the days before exceptions were invented. A common policy for defensive programming in C libraries, for example, was to terminate the program immediately with an error message.
The difference is that if the exception throw does turn out to be possible (hopefully this will be discovered through unit testing), it is often relatively easy to add an exception handler that can recover from the problem in a more constructive way. You don't have to rewrite the library, or add complex checks in application code to ensure the condition cannot arise before the exception-throwing call is made.
I have quite a few exception throws that are never caught. They are all for defensive purposes, and while being uncaught is bad for an exception that does happen, this only ever happens during development and testing, for error conditions I failed to consider in the application code so far. And when it happens, it is unusual for the fix to be awkward - no need for a large-scale refactoring, no need for the applications code to be massively complicated with error condition checks, just a catch clause with a relatively simple recovery or "I'm sorry, Dave, I'm afraid I can't do that." without failing out the whole app.
I've just come across a property setter that catches exceptions (all Exceptions; I know that's bad, but it's not relevant here), and only logs them. First of all, I think it should through them again as well; why wait for a crash and a log study when you can know something is wrong right away?
However, my main question is, do I validate against invalid date values, add a RuleViolation object to a ValidationRules object on my document, or throw an InvalidDate exception, or just let the CLR throw the exception for me (invalid dates are nothing but invalid dates, not checked for range etc.)
It depends on the specific task at hand. If you are writing a library class that will be used as a component in other programs and the contract of the method of the class says that it should only accept valid dates then throwing the Exception is fine.
If you are accepting user input and then waiting for an exception is a bad practice. In this case you should validate the date yourself.
Exceptions are for exceptional cases, and should not be part of your logic. It usually means that a contract was broken by the programmer.
Exceptions should be thrown whenever the method or class member is unable to complete whatever task it is designed to accomplish.
So for a property setter, if the setter is unable to set the property, then it should throw an exception.
As to whether you should catch it and rethrow it, the answer is yes, but only if you need to process the exception immediately in the setter, before passing it up the stack... but logging it is not a reason to do that. In general, you should implement cross-cutting logging of exceptions at a higher level, where the exception is NOT going to be re-thrown... if you are taking care of those cross-cutting concerns higher up the stack somewhere, then no, definitely do not catch and re-throw the same exception.
However, if you are writing a tool, or a framework library, where you want your component's clients to have a clearly defined set of expected exceptions, and you have defined your own custom exceptions that your component will throw to client code, and which client components will expect to see, then you may want to catch CLR generated exceptions and rethrow your own custom exceptions instead.. Always include the Actual underlying exception in your custom exceptions "InnerException" property before passing it up the stack, so that the data in it is available to whatever system end up consuming it.
It really depends on the logic of your application. Exceptions should only really be thrown for circumstances that are exceptional. For something like validation it depends on the tolerance for invalid data.
When you are building an interractive application and the user may enter anything, it is probably ok that the document gets into an invalid state and you should expose validation information via properties on the document class.
If you are processing pre-prepared documents from a database or log file then it probably isn't ok for the document to be invalid and continuing to operate after that might corrupt data in the system. When that happens you should throw.
I think it depends where the date values come from. If it comes from user input or some other source where it is perfectly well possible to enter 'invalid' dates, then validation would be the way to go. On the other hand, if there is no foreseeable reason why the data values might be invalid, then throwing an exception is appropriate.
Catching and rethrowing is the worst thing to do. Its expensive to TRY, if youre just going to rethrow what the point? You can catch unhandled exceptions with the global.asax for example if you need to log them.
In terms of validation, from a web perspective i always use regex validators for dates, these fire client and server side so i know when im inside an
if(Page.IsValid)
block that my txtDate.Text is a valid date, so i dont bother checking because its just wasteful.
Unchecked exceptions are alright if you want to handle every failure the same way, for example by logging it and skipping to the next request, displaying a message to the user and handling the next event, etc. If this is my use case, all I have to do is catch some general exception type at a high level in my system, and handle everything the same way.
But I want to recover from specific problems, and I'm not sure the best way to approach it with unchecked exceptions. Here is a concrete example.
Suppose I have a web application, built using Struts2 and Hibernate. If an exception bubbles up to my "action", I log it, and display a pretty apology to the user. But one of the functions of my web application is creating new user accounts, that require a unique user name. If a user picks a name that already exists, Hibernate throws an org.hibernate.exception.ConstraintViolationException (an unchecked exception) down in the guts of my system. I'd really like to recover from this particular problem by asking the user to choose another user name, rather than giving them the same "we logged your problem but for now you're hosed" message.
Here are a few points to consider:
There a lot of people creating accounts simultaneously. I don't want to lock the whole user table between a "SELECT" to see if the name exists and an "INSERT" if it doesn't. In the case of relational databases, there might be some tricks to work around this, but what I'm really interested in is the general case where pre-checking for an exception won't work because of a fundamental race condition. Same thing could apply to looking for a file on the file system, etc.
Given my CTO's propensity for drive-by management induced by reading technology columns in "Inc.", I need a layer of indirection around the persistence mechanism so that I can throw out Hibernate and use Kodo, or whatever, without changing anything except the lowest layer of persistence code. As a matter of fact, there are several such layers of abstraction in my system. How can I prevent them from leaking in spite of unchecked exceptions?
One of the declaimed weaknesses of checked exceptions is having to "handle" them in every call on the stack—either by declaring that a calling method throws them, or by catching them and handling them. Handling them often means wrapping them in another checked exception of a type appropriate to the level of abstraction. So, for example, in checked-exception land, a file-system–based implementation of my UserRegistry might catch IOException, while a database implementation would catch SQLException, but both would throw a UserNotFoundException that hides the underlying implementation. How do I take advantage of unchecked exceptions, sparing myself of the burden of this wrapping at each layer, without leaking implementation details?
IMO, wrapping exceptions (checked or otherwise) has several benefits that are worth the cost:
1) It encourages you to think about the failure modes for the code you write. Basically, you have to consider the exceptions that the code you call may throw, and in turn you'll consider the exceptions you'll throw for the code that calls yours.
2) It gives you the opportunity to add additional debugging information into the exception chain. For instance, if you have a method that throws an exception on a duplicate username, you might wrap that exception with one that includes additional information about the circumstances of the failure (for example, the IP of the request that provided the dupe username) that wasn't available to the lower-level code. The cookie trail of exceptions may help you debug a complex problem (it certainly has for me).
3) It lets you become implementation-independent from the lower level code. If you're wrapping exceptions and need to swap out Hibernate for some other ORM, you only have to change your Hibernate-handling code. All the other layers of code will still be successfully using the wrapped exceptions and will interpret them in the same way, even though the underlying circumstances have changed. Note that this applies even if Hibernate changes in some way (ex: they switch exceptions in a new version); it's not just for wholesale technology replacement.
4) It encourages you use different classes of exceptions to represent different situations. For example, you may have a DuplicateUsernameException when the user tries to reuse a username, and a DatabaseFailureException when you can't check for dupe usernames due to a broken DB connection. This, in turn, lets you answer your question ("how do I recover?") in flexible and powerful ways. If you get a DuplicateUsernameException, you may decide to suggest a different username to the user. If you get a DatabaseFailureException, you may let it bubble up to the point where it displays a "down for maintenance" page to the user and send off a notification email to you. Once you have custom exceptions, you have customizeable responses -- and that's a good thing.
I like to repackage exceptions between the "tiers" of my application, so for example a DB-specific exception is repackaged inside of another exception which is meaningful in the context of my application (of course, I leave the original exception as a member so I don't clobber the stack trace).
That said, I think that a non-unique user name is not an "exceptional" enough situation to warrant a throw. I'd use a boolean return argument instead. Without knowing much about your architecture, it's hard for me to say anything more specific or applicable.
See Patterns for Generation, Handling and
Management of Errors
From the Split Domain and Technical Errors pattern
A technical error should never cause a
domain error to be generated (never
the twain should meet). When a
technical error must cause business
processing to fail, it should be
wrapped as a SystemError.
Domain errors should always start from a
domain problem and be handled by
domain code.
Domain errors should
pass "seamlessly" through technical
boundaries. It may be that such errors
must be serialized and re-constituted
for this to happen. Proxies and
facades should take responsibility for
doing this.
Technical errors should
be handled in particular points in the
application, such as boundaries (see
Log at Distribution Boundary).
The
amount of context information passed
back with the error will depend on how
useful this will be for subsequent
diagnosis and handling (figuring out
an alternative strategy). You need to
question whether the stack trace from
a remote machine is wholly useful to
the processing of a domain error
(although the code location of the
error and variable values at that time
may be useful)
So, wrap the hibernate exception at the boundary to hibernate with an unchecked domain exception such as a "UniqueUsernameException", and let that bubble up all the way to the handler of it. Make sure to javadoc the thrown exception even though it isn't a checked exception!
Since you're currently using hibernate the easiest thing to do is just check for that exception and wrap it in either a custom exception or in a custom result object you may have setup in your framework. If you want to ditch hibernate later just make sure you wrap this exception in only 1 place, the first place you catch the exception from hibernate, that's the code you'll probably have to change when you make a switch anyway, so if the catch is in one place then the additional overhead is almost zilch.
help?
I agree with Nick. Exception you described is not really "unexpected exception" so you should design you code accordingly taking possible exceptions into account.
Also I would recommend to take a look at documentation of Microsoft Enterprise Library Exception Handling Block it has a nice outline of error handling patterns.
The question is not really related to checked vs. unchecked debate, the same applies to both exception types.
Between the point where the ConstraintViolationException is thrown and the point, where we want to handle the violation by displaying a nice error message is a large number of method calls on the stack that should abort immediately and shouldn't care about the problem. That makes the exception mechanism the right choice as opposed to redesigning the code from exceptions to return values.
In fact, using an unchecked exception instead of a checked exception is a natural fit, since we really want all intermediate methods on the call stack to ignore the exception and not handle it .
If we want to handle the "unique name violation" only by displaying a nice error message (error page) to the user, there's not really a need for a specific DuplicateUsernameException. This will keep the number of exception classes low. Instead, we can create a MessageException that can be reused in many similar scenarios.
As soon as possible we catch the ConstraintViolationException and convert it to a MessageException with a nice message. It's important to convert it soon, when we can be sure, it's really the "unique user name constraint" that was violated and not some other constraint.
Somewhere close to the top level handler, just handle the MessageException in a different way. Instead of "we logged your problem but for now you're hosed" simply display the message contained in the MessageException, no stack trace.
The MessageException can take some additional constructor parameters, such as a detailed explanation of the problem, available next action (cancel, go to a different page), icon (error, warning)...
The code may look like this
// insert the user
try {
hibernateSession.save(user);
} catch (ConstraintViolationException e) {
throw new MessageException("Username " + user.getName() + " already exists. Please choose a different name.");
}
In a totally different place there's a top exception handler
try {
... render the page
} catch (MessageException e) {
... render a nice page with the message
} catch (Exception e) {
... render "we logged your problem but for now you're hosed" message
}
You can catch unchecked exceptions without needing to wrap them. For example, the following is valid Java.
try {
throw new IllegalArgumentException();
} catch (Exception e) {
System.out.println("boom");
}
So in your action/controller you can have a try-catch block around the logic where the Hibernate call is made. Depending on the exception you can render specific error messages.
But I guess in your today it could be Hibernate, and tomorrow SleepLongerDuringWinter framework. In this case you need to pretend to have your own little ORM framework that wraps around the third party framework. This will allow you to wrap any framework specific exceptions into more meaningful and/or checked exceptions that you know how to make better sense of.
#Jan Checked versus unchecked is a central issue here. I question your supposition (#3) that the exception should be ignored in intervening frames. If I do that, I will end up with an implementation-specific dependency in my high-level code. If I replace Hibernate, catch blocks throughout my application will have to be modified. Yet, at the same time, if I catch the exception at a lower level, I'm not receiving much benefit from using an unchecked exception.
Also, the scenario here is that I want to catch a specific logical error and change the flow of the application by re-prompting the user for a different ID. Simply changing the displayed message is not good enough, and the ability to map to different messages based on exception type is built into Servlets already.
#erikson
Just to add food to your thoughts:
Checked versus unchecked is also debated here
The usage of unchecked exceptions is compliant with the fact they are used IMO for exception caused by the caller of the function (and the caller can be several layers above that function, hence the necessity for other frames to ignore the exception)
Regarding your specific issue, you should catch the unchecked exception at high level, and encapsulate it, as said by #Kanook in your own exception, without displaying the callstack (as mentionned by #Jan Soltis )
That being said, if the underlying technology changes, that will indeed have an impact on those catch() already present in your code, and that does not answer your latest scenario.
I have some code that gives a user id to a utility that then send email to that user.
emailUtil.sendEmail(userId, "foo");
public void sendEmail(String userId, String message) throws MailException {
/* ... logic that could throw a MailException */
}
MailException could be thrown for a number of reasons, problems with the email address, problems with the mail template etc.
My question is this: do you create a new Exception type for every one of these exceptions and then deal with them individually or do you create one MailException and then store something in the exception (something computer-readable, not the description text) that allows us to do different things based on what actually happened.
Edit: As a clarification, the exceptions aren't for logs and what-not, this relates to how code reacts to them. To keep going with the mail example, let's say that when we send mail it could fail because you don't have an email address, or it could because you don't have a valid email address, or it could fail.. etc.
My code would want to react differently to each of these issues (mostly by changing the message returned to the client, but actual logic as well).
Would it be best to have an exception implementation for each one of these issues or one umbrella exception that had something internal to it (an enum say) that let the code distinguish what kind of issue it was.
In my code, I find that MOST exceptions percolate up to a UI layer where they are caught by my exception handlers which simply display a message to the user (and write to the log). It's an unexpected exception, after all.
Sometimes, I do want to catch a specific exception (as you seem to want to do). You'll probably find, however, that this is somewhat rare and that it is indicative of using exceptions to control logic -- which is inefficient (slow) and often frowned upon.
So using your example, if you want to run some special logic when the email server is not configured, you may want to add a method to the emailUtil object like:
public bool isEmailConfigured()
... call that first, instead of looking for a specific exception.
When an exception does happen, it really means that the situation was completely unexpected and the code can't handle it -- so the best you can do is report it to the user (or write it to a log or restart )
As for having an exception hierarchy vs exceptions-with-error-codes-in-them, I typically do the latter. It's easier to add new exceptions, if you just need to define a new error constant instead of a whole new class. But, it doesn't matter much as long as you try to be consistent throughout your project.
I usually start with a general exception and subclass it as needed. I always can catch the general exception (and with it all subclassed exceptions) if needed, but also the specific.
An example from the Java-API is IOException, that has subclasses like FileNotFoundException or EOFException (and much more).
This way you get the advantages of both, you don't have throw-clauses like:
throws SpecificException1, SpecificException2, SpecificException3 ...
a general
throws GeneralException
is enough. But if you want to have a special reaction to special circumstances you can always catch the specific exception.
#Chris.Lively
You know you can pass a message in your exception, or even the "status codes". You are reinventing the wheel here.
I have found that if you need to have CODE deciding what to do based on the exception returned, create a well named exception subclassing a common base type. The message passed should be considered "human eyes only" and too fragile to make decisions upon. Let the compiler do the work!
If you need to pass this up to a higher layer through a mechanism not aware of checked exceptions, you can wrap it in a suitable named subclass of RuntimeException (MailDomainException) which can be caught up high, and the original cause acted upon.
It depends on what your application is doing. You might want to throw individual exceptions in cases like
The application is high availability
Sending e-mail is particularly important
The scope of the application is small and sending e-mail is a large part of it
The application will be deployed to a site which is remote and you will only get logs for debugging
You can recover from some subset of the exceptions encapsulated in the mailException but not others
In most cases I would say just log the text of the exception and don't waste your time granularizing already pretty granular exceptions.
I think a combination of the above is going to give you the best result.
You can throw different exceptions depending on the problem. e.g. Missing email address = ArgumentException.
But then in the UI layer you can check the exception type and, if need be, the message and then display a appropriate message to the user. I personally tend to only show a informational message to the user if a certain type of exception is thrown (UserException in my app). Of course you should scrub and verify user input as much as possible further up the stack to make sure any exceptions are generated by truly unlikely scenarios, not as a filter for malformed emails which can easily be checked with a regex.
I also wouldn't worry about the performance implications of catching an exception from user input. The only time you are going to see performance problems from exceptions is when they are being thrown and caught in a loop or similar.
Instead of using exceptions, I tend to return a list of status objects from methods that may have problems executing. The status objects contain a severity enum (information, warning, error, ...) a status object name like "Email Address" and a user readable message like "Badly formatted Email Address"
The calling code would then decide which to filter up to the UI and which to handle itself.
Personally, I think exceptions are strictly for when you can't implement a normal code solution. The performance hit and handling restrictions are just a bit too much for me.
Another reason for using a list of status objects is that identifying multiple errors (such as during validation) is MUCH easier. After all, you can only throw one exception which must be handled before moving on.
Imagine a user submitting an email that had a malformed destination address and contained language that you are blocking. Do you throw the malformed email exception, then, after they fix that and resubmit, throw a bad language exception? From a user experience perspective dealing with all of them at once is a better way to go.
UPDATE: combining answers
#Jonathan: My point was that I can evaluate the action, in this case sending an email, and send back multiple failure reasons. For example, "bad email address", "blank message title", etc..
With an exception, you're limited to just percolating the one problem then asking the user to resubmit at which point they find out about a second problem. This is really bad UI design.
Reinventing the wheel.. possibly. However, most applications should analyze the whole transaction in order to give the best possible information to the user. Imagine if your compiler stopped dead at the first error. You then fix the error and hit compile again only to have it stop again for a different error. What a pain in the butt. To me, that's exactly the problem with throwing exceptions and hence the reason I said to use a different mechanism.
I tend to have less Exception types, although it's not really the OO way to do it. Instead I put an enum to my custom Exceptions, which classifies the Exception. Most of the time I have a custom base Exception, which holds on to a couple of members, which can be overridden or customized in derived Exception types.
A couple of months ago I blogged about the idea of how to internationalize Exceptions. It includes some of the ideas mentioned above.
While you can differenciate the code execution looking the exception don't matter if it's done by the "catch exceptionType hierarchy mode" or by "if(...) else...exception code mode"
but if you are developing software wich is going to be used by other people, like a library i think it's usefull create your own exception types to notice the other people that your sofware can throw other exceptions than the normal ones, and they better catch and resolve them.
When i use a library and their methods simply launch an 'Exception' i allways wonder: What can cause this exception?, how must my program react?, if there is a javadoc maybe the cause will be explained, but mustly of times there is not a javadoc or the exception is not explained. Too much overhead witch can be avoided with a WellChossenExceptionTypeName
It depends on whether the code that catches the exception needs to differentiate between exceptions or whether you are just using exceptions to fail out to an error page. If you need to differentiate between a NullReference exception and your custom MailException higher up in the call stack, then spend the time and write it. But most of the time programmers just use exceptions as a catch all to throw up an error on the web page. In this case you are just wasting effort on writing a new exception.
I would just go by
throw new exception("WhatCausedIt")
if you want to handle your exceptions, you could pass a code instead of "WhatCausedIt" an then react to the different answers with a switch statement.