Designing a class with **Exceptions**
When I design a class I often have trouble deciding if I should throw an exception or have 2 func with the 2nd returning an err value. In the case of 2 functions how should I name the exception and non exception method?
For example if I wrote a class that decompresses a stream and the stream had errors or incomplete I would throw an exception. However what if the app is trying to recover data from the stream and excepts an error? It would want a return value instead? 开发者_Go百科So how should I name the 2nd function?
Or should I not have both an exception method and a nonexception method?
Or should I not have both an exception method and a nonexception method?
That. Unless you really have time to burn maintaining two separate but mostly-identical methods.
If you really need to allow for clients that won't consider errors exceptional, then just indicate them with a return value and be done with it... Otherwise, just write the exception-throwing version and let the odd error-eating client handle the exception.
It depends on the language, but...
In my opinion, two versions of each potentially failing method imposes too high a cognitive burden on the API user, and too high a burden on the API maintainer. My personal preference is for exceptions, since that's fewer parameters to remember the order of.
I believe that you should try to use exceptions even if you're not going to exit program in some cases. You just need to create a specific exception type for your errors. And catch only them when you need to do some spefic logic. All other exceptions will go to upper level of your code. For example you've created function which throws exception on any error. And you don't want to exit program if user specified incorrect file name. Here is how it can look:
## this is top level try/catch block
try {
## your main code is here
...
## somewhere deep in your code
try {
## we trying to open file specified by user
}
catch (FileNotFoundException) {
## we are not going to exit on this error
## let's just show a user an error message
## and try to ask different file to open
}
} catch (Exception) {
## catch all exceptions here
## the best thing we can do here is save exception to log and quit }
}
We just need to create hierarchy of exceptions (if your language allows it):
Exception <-- MoreSpecificException
This approach is used in Java
Exceptions should normally be used for exceptional conditions, whatever they may be. Being unable to decompress a file is probably an exceptional condition (unless, for example, you're writing a program to scan for badly compressed files). Bad data may or may not be exceptional.
If you've got a class decompressing a stream, then what it should do is decompress the stream, and not try to interpret its contents. Another class should use the first class to get decompressed input, and do the interpretation. That gives you separation of functionality, and good cohesion. Avoid classes where you're tempted to put an "And" in their names: "DecompressAndParseInput" is a bad class name.
Given two classes, there's no particular reason why you have to use the same error-reporting method for both. The decompressor could throw, and the parser could return an error code.
I would only throw an exception on the decompression function if the results were not usable. If they were usable, return the results and then the function that reads those results can throw an exception instead. IE
try
{
results = decompress(file); // only throws exceptions on non-usable files
} catch (FileNotFoundException) {
// file was not usable, can't recover anything, insert nuclear error handling here
}
try
{
read(results);
} catch (ErrorThatIsRecoverableException) {
partialRead(results);
}
so read() is the function you call on normal data, partialRead is the function that handles trying to recover screwed-up-but-still-usable data. And of course, you don't necessarily need exceptions or separate functions at all- you could do the error handling all within the read() function.
精彩评论