[C#] Knowing what exception a method will throw



  • I have been trying to figure out what kind of exceptions XElement.Load and Save will throw, I'd figure a IOException and a XmlException, but there is no way to be sure. Java has checked exceptions, so the exceptions a method throws is documented in the method signature.

    I have been trying to read http://msdn2.microsoft.com/en-us/library/bb298435.aspx to see if the exceptions are documented. But no luck.

    Is there a general way in C# to know what kind of exceptions a method will throw?



  •  It is usually documented right on that page.

    Kind of like you see here: http://msdn2.microsoft.com/en-us/library/0w3csw16.aspx

    My guess is the documentation is incomplete. Maybe the method doesn't actually throw any exceptions unique to it?

     

    Anyway, this is not usually the case, it is usually easy to find this info.

    All the Linq stuff is pretty new, maybe someone else knows of a better place for documentation?



  • @Ice^^Heat said:

    I have been trying to figure out what kind of exceptions XElement.Load and Save will throw, I'd figure a IOException and a XmlException, but there is no way to be sure. Java has checked exceptions, so the exceptions a method throws is documented in the method signature.

     

    Java also has unchecked exceptions, which are not documented in the method signature. In fact, most people (including me) think that checked exceptions were a bad idea. In any case, the specific Exceptions a method can throw should of course be listed in its API documentation. 



  • I think I kind of like it the Java way. You don't have to guess what exceptions will be thrown.

    Why would it be a bad idea?

     



  • I'm probably going to get this wrong (I don't do Java all that much), but you need to catch all checked exceptions for methods you call including both the ones specified by the method as well as could be caught and rethrown.  So depending on how many levels you go, it might be easier to catch RuntimeException (sort of equivalent to Exception in C#) instead of the following


    Catch (IOException) { ..... }

    Catch (ArgumentException) { .... }

    Catch (NullException) { .... } 

    Catch (AnotherException) { .... } 

    Catch (YetArgumentException) { .... } 


    You'll find several threads about it that do better justice.  I remember one where ammoQ was dissing it in relation to jdbc drivers.

     

    As far as you original question, usually the exceptions are documented but apparently the coders forgot to put the comments in their code.  When in doubt, you could always walk the execution tree with Reflector - it sucks to walk all the possible execution paths, but you should get most of them in a few clicks.

     



  • @Ice^^Heat said:

    I think I kind of like it the Java way. You don't have to guess what exceptions will be thrown.

    Why would it be a bad idea?

     

    It forces you to either scatter Exception handling code around (which defeats the point of exceptions) or pollute your method signatures with lists of "throws" clauses that get longer the farther up the call hierarchy you are:

    public void mainAppMethod()
    throws IOException, SQLException, RemoteException, InterruptedException, NoSuchMethodException, InstatiationException, ParserConfigurationException, TransformerException, UserException, ...
    {
    }

    And of course you STILL have to guess what RuntimeExceptions might be thrown because those don't have to be listed in the "throws" clause. 




  •  

    I'm probably going to get this wrong (I don't do Java all that much), but you need to catch all checked exceptions for methods you call including both the ones specified by the method as well as could be caught and rethrown.

    You have to catch them, yes. You do not have to catch them all by their specific name and make an individual block for each of them. Use catch (Exception e) {} if you want to catch an error, don't care what kind it was, and don't want to do different things depending on what kind of error it was.

    Checked exceptions are part of the interface contract, a part that specifies "look, you HAVE to handle this problem when it happens" for the client. Errors which indicate resource leaks, synchronization errors, and catastrophic failures seem good candidates for being checked. There seem to be a lot of checked exceptions that don't need to be checked in the Java API. But if you don't care about catching and handling an error, who cares? Just throw an empty generic catch block in there and leave a comment about why you don't care about this error.

    Brazzy's example is really the kind that illustrates how people who don't know how exception handling works (in Java) can write bad code. It's not a problem with the language. Nobody is forcing you to write throws BlahException x20. Organize the hierarchy of your execeptions properly, or just throw something generic if you know your client does not need to do different things for each exception, or just make it unchecked, because it's unlikely that you have 20 different error conditions that are all bad enough to reasonably insist your client handle.



  • @brazzy said:

    It forces you to either scatter Exception handling code around (which defeats the point of exceptions) or pollute your method signatures with lists of "throws" clauses that get longer the farther up the call hierarchy you are:

    public void mainAppMethod()
    throws IOException, SQLException, RemoteException, InterruptedException, NoSuchMethodException, InstatiationException, ParserConfigurationException, TransformerException, UserException, ...
    {
    }

    And of course you STILL have to guess what RuntimeExceptions might be thrown because those don't have to be listed in the "throws" clause. 


    Yike. If you're doing that, you aren't using exceptions correctly. It appears you're trying to force them all to propagate to the top, the way C# would.

    A little good program design goes a long way. You do know you're supposed to write your own exception classes, with names that relate to your application, right? Then if you have a class that relies on XML internally, you wrap XML-related exceptions in an application exception and throw that, instead of exposing every exception the internal implementation can throw.

    Now, here's the thing about RuntimeExceptions. You do not have to guess which RuntimeExceptions will be thrown, because in Java, RuntimeExceptions are those exceptions you are never supposed to catch. RuntimeExceptions are problems which the programmer can and should prevent.

    For instance, if you get an IllegalArgumentException, your code is broken. Do not catch the problem and sweep it under the rug; debug it and fix the problem. If it's happening due to user input, you should have checked the validity of the user input before passing it to a method which doesn't allow certain values. In other words, RuntimeExceptions exist specifically to reveal broken code.



  • @VGR said:

    Yike. If you're doing that, you aren't using exceptions correctly. It appears you're trying to force them all to propagate to the top, the way C# would.

    What if there's not really anything very useful I can do about those exceptions deep down in the application and I *want* them to propagate to somewhere near the top where I can handle them generically? 

    @VGR said:


    A little good program design goes a long way. You do know you're supposed to write your own exception classes, with names that relate to your application, right? Then if you have a class that relies on XML internally, you wrap XML-related exceptions in an application exception and throw that, instead of exposing every exception the internal implementation can throw.

    I very much doubt I am supposed to scatter code all over my application that rewraps exceptions and have nearly every method in the app declare that it "throws MyAppException". If there were no checked exceptions, It would have pretty much the same effect except for the need to rewrap exceptions and declare something generic (neither of which achieves anything useful).

     

    @VGR said:

    Now, here's the thing about RuntimeExceptions. You do not have to guess which RuntimeExceptions will be thrown, because in Java, RuntimeExceptions are those exceptions you are never supposed to catch. RuntimeExceptions are problems which the programmer can and should prevent.

    For instance, if you get an IllegalArgumentException, your code is broken. Do not catch the problem and sweep it under the rug; debug it and fix the problem.

    Do you have much real world programming experience? That sounds like a nice theory, but in reality, you do not have control over how other programmers whose code you use design their exceptions. And there is no perfection and some bugs end up in production code, and clients do NOT appreciate losing data when an application crashes because a programmer thinks that catching a RuntimeException is "sweeping the problem under the rug". 

     



  • @Nether said:

    Just throw an empty generic catch block in there and leave a comment about why you don't care about this error.

    Do. Not. Do.This. Ever. Or raptors sent by the gods of programming will come to hunt you down. Any exception that is caught should at the very least be logged, unless you're writing unit tests and actually expect the exception to occur.

    @Nether said:

    Brazzy's example is really the kind that illustrates how people who don't know how exception handling works (in Java) can write bad code. It's not a problem with the language. Nobody is forcing you to write throws BlahException x20. Organize the hierarchy of your execeptions properly, or just throw something generic if you know your client does not need to do different things for each exception, or just make it unchecked, because it's unlikely that you have 20 different error conditions that are all bad enough to reasonably insist your client handle.

     

    The funny thing is that ALL of the exceptions I listed are checked exceptions that occur somewhere in the standard Java API library. If you have an application that uses File IO, a Database, RMI, XSLT and reflection, you have the choice betweeen

    • throws declarations like that
    • "throws Exception"
    • lots of exception handling or -rewrapping code sprinkled all over the application
    As you said, the Java API is full of checked exceptions that probably should not have been. What makes you believe you're that much better at API design than all of them? Making those exceptions checked probably seemed like the right decision to them at the time.


  • @lpope187 said:

    You'll find several threads about it that do better justice.  I remember one where ammoQ was dissing it in relation to jdbc drivers.

    Can't find that thread myself, too. Anyway, the reasoning against checked exceptions is because they are a problematic with inheritance, especially with interfaces.

    That't because a overwritten method may not throw exceptions that the corresponding method of the superclass did not specify. But when you define an interface, you have only a very vague idea which execptions the actual classes implementing said interface might need to throw. For that reason, in JDBC, each and every method is specified to possibly throw SQLException, even though this exception will probably never ever occur in any real implementation of some methods, because you would be hard pressed to find a scenario how this method could fail.

    For example, ResultSet.clearWarnings is declared to possibly throw SQLException, but how can you ever trigger this error? In real life, without a specially mocked JDBC driver, you can't. So Java forces you to catch SQLException, but you will never be able to test the error handler. The error handler is basically stillborn dead code.

    On the other hand, SQLException is very generic. The same type of exception is used to indicate e.g. ...

    - a syntax error in your SQL statement

    - a problem with the actual data (duplicate key etc.)

    - a temporary problem (deadlock, record locked etc.)

    - a network problem

    - an IO problem 

    - a desastrous crash of the DBMS 

    Adequate handling of this different error types is rather difficult, so it probably won't happen.



  • @ammoQ said:

    That't because a overwritten method may not throw exceptions that the corresponding method of the superclass did not specify. But when you define an interface, you have only a very vague idea which execptions the actual classes implementing said interface might need to throw. For that reason, in JDBC, each and every method is specified to possibly throw SQLException, even though this exception will probably never ever occur in any real implementation of some methods, because you would be hard pressed to find a scenario how this method could fail.
     

    That's a good point. I've been frustrated by the inability to deal intelligently with SQL Exceptions in the past. Usually, the strategy I employed to avoid wasting too much time is to just log it verbosely and fail hard. This often meant I couldn't handle dropped database connections vs integrity constraint violations in the database intelligently. IIRC, the Java documentation always just refers you back to the driver implementation for error codes and washes its hands of the matter entirely, and usually the driver error code documentation is non-portable, nightmarishly convoluted, or non-existant. 

    Also, I absolutely do not care whether I am eaten by XKCD-style raptors for my empty catch blocks. Sometimes it is the right thing to do, and the comment provides a suitable explanation. Logging is a great policy that I always follow, but my logger may not have been instantiated by that point, or the error could be a problem with the logger itself, or the specification may dictate that this situation should not be logged, or the exception may exist and be checked purely for flow control convenience (e.g. ParseException) making logging irrelevant.

    Sometimes there are good reasons to not.do.this.ever, but I find that programmers that unduely focus on absolutes are often too rigid to even consider when something provided might be useful in a context outside their experience. It takes decades or more in a specific area to really be confident in any absolutes you try to fit into your design philosophy. I prefer critical thinking.



  • @brazzy said:

    @VGR said:

    Yike. If you're doing that, you aren't using exceptions correctly. It appears you're trying to force them all to propagate to the top, the way C# would.

    What if there's not really anything very useful I can do about those exceptions deep down in the application and I want them to propagate to somewhere near the top where I can handle them generically? 

    Okay, you got me there. When exactly would you want to handle all those exceptions in the same way? And if you really do have a reason do that (which is unlikely), I would think you'd just want to catch Exception.

    @brazzy said:

    I very much doubt I am supposed to scatter code all over my application that rewraps exceptions and have nearly every method in the app declare that it "throws MyAppException". If there were no checked exceptions, It would have pretty much the same effect except for the need to rewrap exceptions and declare something generic (neither of which achieves anything useful).

    Yeah, actually, that's exactly what you're supposed to do. What do you think ParserConfigurationException is doing? Probably wrapping an IOException or ClassNotFoundException. Why do you think Java added the "cause" property to the Throwable class?

    But you're right that you're not supposed to have nearly every method in the app declare that it throws MyAppException. The application is where you're supposed to catch the exceptions and present the user with something more useful than "Got exception: " + exception.

    @brazzy said:
    @VGR said:

    Now, here's the thing about RuntimeExceptions. You do not have to guess which RuntimeExceptions will be thrown, because in Java, RuntimeExceptions are those exceptions you are never supposed to catch. RuntimeExceptions are problems which the programmer can and should prevent.

    For instance, if you get an IllegalArgumentException, your code is broken. Do not catch the problem and sweep it under the rug; debug it and fix the problem.

    Do you have much real world programming experience? That sounds like a nice theory, but in reality, you do not have control over how other programmers whose code you use design their exceptions. And there is no perfection and some bugs end up in production code, and clients do NOT appreciate losing data when an application crashes because a programmer thinks that catching a RuntimeException is "sweeping the problem under the rug".

    Does twenty years count as "much real world programming experience"? In reality, if other people's code is throwing exceptions, then either you violated the contract of the API you were calling, or there is a bug in that code and you should be giving the author of that code hell until they fix it. Sure, sometimes a bad third-party API forces you to catch RuntimeExceptions, but it just means they're inexperienced and unprofessional. I do not assume those attributes of other code by default.

    In reality, a customer's data will be lost regardless of whether the runtime exception is caught. In reality, catching runtime exceptions and adopting a "move along, nothing to see here" policy will make things worse: the program won't be behaving properly, and the errant behavior may go unnoticed for weeks or months, because regular users won't be sure if it's a problem at all. And the reality is that catching and logging the exception without doing anything else is of almost no value. In reality, no one regularly checks the logs of deployed programs unless they're looking for a problem.

    Search the javadoc of a collection class like ArrayList for a concept called "fail-fast." The idea is to promote robustness by exposing incorrect code as early as possible.

    A program isn't robust or correct just because it hides the symptoms.



  • @ammoQ said:

    That't because a overwritten method may not throw exceptions that the corresponding method of the superclass did not specify. But when you define an interface, you have only a very vague idea which execptions the actual classes implementing said interface might need to throw.

    I think that's the point of both exception chaining and exception subclassing. The general exception class that the interface method throws represents a category of exceptions. Is this really any different from IOException?

    @ammoQ said:

    On the other hand, SQLException is very generic. The same type of exception is used to indicate e.g. ...

    - a syntax error in your SQL statement

    SQLSyntaxErrorException.

    @ammoQ said:

    - a problem with the actual data (duplicate key etc.)

    SQLDataException and SQLIntegrityConstraintViolationException.

    @ammoQ said:

    - a temporary problem (deadlock, record locked etc.)

    SQLTransientException and its subclasses.

    @ammoQ said:

    - a network problem

    - an IO problem 

    SQLTransientConnectionException.

    @ammoQ said:

    - a desastrous crash of the DBMS 

    SQLTimeoutException.

    To be fair, many of the above were introduced in Java 1.6. But to be fair to me, Java 1.6 has been out for quite a while, and I'm pretty sure the same information was always available by calling getCause() or getSQLState() on an SQLException (though I never did get ahold of a document that lists those state strings).



  • @VGR said:

    To be fair, many of the above were introduced in Java 1.6.

    "many" = "all". ;-) But it's a good thing to know that they finally did it right! Thanks for the info.


    But to be fair to me, Java 1.6 has been out for quite a while

    Drivers that use those new Exceptions only work with Java 1.6 or higher. For that reason, depending on the DBS used, such drivers may be available or not.


    and I'm pretty sure the same information was always available by calling getCause()

    Maybe, maybe not. getCause returns a Throwable, which can be pretty much anything. If you are lucky, it's e.g. an IO exception when appropriate.

     

    or getSQLState() on an SQLException (though I never did get ahold of a document that lists those state strings).

     

    Neither me, seems pretty useless. 



  • Gaah, completely forgot about this thread. Anyways: 

    @Nether said:

    Also, I absolutely do not care whether I am eaten by XKCD-style raptors for my empty catch blocks. Sometimes it is the right thing to do, and the comment provides a suitable explanation.

    I disagree. The comment is useless to someone who just knows that some part of the application fails silently, and who has no idea where to start looking. 

    @Nether said:

    Logging is a great policy that I always follow, but my logger may not have been instantiated by that point, or the error could be a problem with the logger itself

     All the more reason to make some attempt at giving information to someone who's diagnosing the problem. This is what System.err is for. If you're in code that's handling a redirected System.err, then I guess you're out of luck, though.

     @Nether said:

    , or the specification may dictate that this situation should not be logged,

    That's what "debug" log levels are for. 

     @Nether said:

    or the exception may exist and be checked purely for flow control convenience (e.g. ParseException) making logging irrelevant

    Not sure what this means. 

    The examples you cite are rather different from the statement I was replying to, which read "But if you don't care about catching and handling an error, who cares?".

    @Nether said:

    Sometimes there are good reasons to not.do.this.ever, but I find that programmers that unduely focus on absolutes are often too rigid to even consider when something provided might be useful in a context outside their experience. It takes decades or more in a specific area to really be confident in any absolutes you try to fit into your design philosophy. I prefer critical thinking.

    I find that people who turn arguments about concrete points into philosophical debates are rarely concerned with critical thinking.

     



  • @VGR said:

    @brazzy said:

    What if there's not really anything very useful I can do about those exceptions deep down in the application and I *want* them to propagate to somewhere near the top where I can handle them generically? 

    Okay, you got me there. When exactly would you want to handle all those exceptions in the same way? And if you really do have a reason do that (which is unlikely), I would think you'd just want to catch Exception.

     

    When I can't do anything useful about those exceptions, what am I supposed to do? Log the exception, return an error code to the client / show and error dialog to the user, and get the app into a stable state. Since this is generic behaviour, I want to do it in one place only.

    And of course I'd be catching Exception, but that still leaves me with methods that either declare lots of different checked exceptions or "throws Exception", neither of which is desirable.  

    @VGR said:

    @brazzy said:

    I very much doubt I am supposed to scatter code all over my application that rewraps exceptions and have nearly every method in the app declare that it "throws MyAppException". If there were no checked exceptions, It would have pretty much the same effect except for the need to rewrap exceptions and declare something generic (neither of which achieves anything useful).

    Yeah, actually, that's exactly what you're supposed to do. What do you think ParserConfigurationException is doing? Probably wrapping an IOException or ClassNotFoundException. Why do you think Java added the "cause" property to the Throwable class?

    What is gained by wrapping an IOException into a ParserConfigurationException? Nothing. Maybe someone thinks I'm supposed to that. I think they're wrong. The "cause" property is a band-aid to the problem of wrapped exceptions losing stack trace information - it would be unnecessary if you didn't wrap the exception in the first place.

     @VGR said:

    But you're right that you're not supposed to have nearly every method in the app declare that it throws MyAppException. The application is where you're supposed to catch the exceptions and present the user with something more useful than "Got exception: " + exception.

    In my experience, the occasions where you can do anything more useful other than beautifying it a bit and adding context information are few and far between.

    @VGR said:
    Does twenty years count as "much real world programming experience"? In reality, if other people's code is throwing exceptions, then either you violated the contract of the API you were calling, or there is a bug in that code and you should be giving the author of that code hell until they fix it.

    Certainly the problem should be fixed, but that does not mean you have to let the program crash. 

     @VGR said:

    In reality, a customer's data will be lost regardless of whether the runtime exception is caught.

    Some data may be lost, but that does not mean there's no point in trying.

    @VGR said:

    In reality, catching runtime exceptions and adopting a "move along, nothing to see here" policy will make things worse:

    False dichtomy. 

    @VGR said:

    the program won't be behaving properly, and the errant behavior may go unnoticed for weeks or months, because regular users won't be sure if it's a problem at all.

    So your idea of quality software engineering is making the users suffer the worst possible consequences of errors in the hope that this increases the likelyhood of bug reports? 

    @VGR said:

    And the reality is that catching and logging the exception without doing anything else is of almost no value. In reality, no one regularly checks the logs of deployed programs unless they're looking for a problem.

    But users who get an error dialog and the chance to save their data are much happier than users who have their app crash. And if the error prevents them from doing something they want, they're just as likely to file a bug report. 



  •  @VGR said:

    the program won't be behaving properly, and the errant behavior may go unnoticed for weeks or months, because regular users won't be sure if it's a problem at all.

    @Brazzy said:

    So your idea of quality software engineering is making the users suffer the worst possible consequences of errors in the hope that this increases the likelyhood of bug reports? 

     In an ecommerce application i'm working on at the moment, our PaymentGateway throws a 'ProviderNotAvailableException' should it be... well.. not available. The underlying Exception is an IOException, because of the third party crappy API. Our PaymentGateway captures the IOException and has to regex into the IOException description field to figure out if it is a configuration error, or the provider being down. So wrapping exceptions in this case makes good sense as we are Abstracting some logic out from the PaymentGateway Client.

     This allows us to catch the PaymentGatewayException and deal with it gracefully (placing the message into an offline processing queue, which is picked up when the provider comes back up online, as we don't want to loose sales,.. in this case, an error has occured, it has been logged but the application can continue on with no loss of functionality to the end user, we simple process the order at a later time in the day.

    So If we did get an IOException from the PaymentGateway  it probably means the system is totaly screwed and we can't be sure what the hell is going on so all bets are off and the system is going down for some pretty rapid maintaince while the QA / Operations teams get slapped around for allowing a bad build / configuration to be propped out. In the later case, it is better to the tell the user 'please come back later, serious error' log the fatal error and have an ops member woken up at 3am to come in and fix it, than letting the user continue on thinking that they have placed an order and it's comming next day when actually the system is so screwed we didin't even record the details let alone the payment information... Of course the user will get a friendly message saying 'sorry', but at the same time they cannot continue any further.

     

     



  • @Grovesy said:

    So If we did get an IOException from the PaymentGateway  it probably means the system is totaly screwed and we can't be sure what the hell is going on so all bets are off and the system is going down for some pretty rapid maintaince while the QA / Operations teams get slapped around for allowing a bad build / configuration to be propped out. In the later case, it is better to the tell the user 'please come back later, serious error' log the fatal error and have an ops member woken up at 3am to come in and fix it, than letting the user continue on thinking that they have placed an order and it's comming next day when actually the system is so screwed we didin't even record the details let alone the payment information... Of course the user will get a friendly message saying 'sorry', but at the same time they cannot continue any further.

    Couldn't an IOException also indicate a transient network glitch? I'd give the user the option to try submitting the order again (*and* alert the operations team if the error persists). Of course, it should be made  absolutely clear to the user whether the order has been successfully sbmitted or not.

    In any case, it depends on the kind of application. In a webapp where users place one order at a time and orders are relatively simple, failing fast and hard is acceptable. But in the case of, say, a word processor, all possible efforts should be made to give the user a chance to save their data (possibly multiple documents).



  • @brazzy said:

    What is gained by wrapping an IOException into a ParserConfigurationException? Nothing. Maybe someone thinks I'm supposed to that. I think they're wrong. The "cause" property is a band-aid to the problem of wrapped exceptions losing stack trace information - it would be unnecessary if you didn't wrap the exception in the first place.

    1. It provides abstraction by keeping implementation details internal. If I'm writing a parser, callers have no business knowing whether I'm using raw socket I/O, RMI, or JMS to do whatever communication I'm doing. They only need to know that the call failed, especially when the code us running in a deployed environment. For someone who's debugging, the underlying cause is clearly visible in the "cause" portion of the stack trace.
    2. It lets calling code catch one exception (or at least, fewer exceptions) instead of catching an exception for every type of technology that might have been used internally. If my parser were using reflection internally, it really wouldn't make sense to propagate reflection exceptions to the caller.


  • @VGR said:

    @brazzy said:

    What is gained by wrapping an IOException into a ParserConfigurationException? Nothing. Maybe someone thinks I'm supposed to that. I think they're wrong. The "cause" property is a band-aid to the problem of wrapped exceptions losing stack trace information - it would be unnecessary if you didn't wrap the exception in the first place.

    1. It provides abstraction by keeping implementation details internal. If I'm writing a parser, callers have no business knowing whether I'm using raw socket I/O, RMI, or JMS to do whatever communication I'm doing. They only need to know that the call failed, especially when the code us running in a deployed environment. For someone who's debugging, the underlying cause is clearly visible in the "cause" portion of the stack trace.
    2. It lets calling code catch one exception (or at least, fewer exceptions) instead of catching an exception for every type of technology that might have been used internally. If my parser were using reflection internally, it really wouldn't make sense to propagate reflection exceptions to the caller.

     

    If callers really had "no business" knowing the underlying problem, there should not be a "cause" property. I think what you really mean is that callers should not care and not have to make any provisions for the underlying technical problem. But that's exactly the point I was trying to make about checked exceptions: if there were only unchecked exceptions, you would need to special throws statements and have the same effect without any repackaging.



  • @brazzy said:

    @VGR said:

    @brazzy said:

    What is gained by wrapping an IOException into a ParserConfigurationException? Nothing. Maybe someone thinks I'm supposed to that. I think they're wrong. The "cause" property is a band-aid to the problem of wrapped exceptions losing stack trace information - it would be unnecessary if you didn't wrap the exception in the first place.

    1. It provides abstraction by keeping implementation details internal. If I'm writing a parser, callers have no business knowing whether I'm using raw socket I/O, RMI, or JMS to do whatever communication I'm doing. They only need to know that the call failed, especially when the code us running in a deployed environment. For someone who's debugging, the underlying cause is clearly visible in the "cause" portion of the stack trace.
    2. It lets calling code catch one exception (or at least, fewer exceptions) instead of catching an exception for every type of technology that might have been used internally. If my parser were using reflection internally, it really wouldn't make sense to propagate reflection exceptions to the caller.

     

    If callers really had "no business" knowing the underlying problem, there should not be a "cause" property. I think what you really mean is that callers should not care and not have to make any provisions for the underlying technical problem. But that's exactly the point I was trying to make about checked exceptions: if there were only unchecked exceptions, you would need to special throws statements and have the same effect without any repackaging.

     To throw something else into the mix, if we went with 'Inversion control', I would supply an instance of a class that implements IParserCommunication to the Parser, at which point you could argue that the Parser should not wrap any SocketException / FileAccessException (or any exception) comming out of of the IParserCommunication instance.

     

    Anyhow, sorry being a bit thick here, could you elaborate on 'if there were only unchecked exceptions, you would need to special throws statements and have the same effect without any repackaging' ?



  • @Grovesy said:

    Anyhow, sorry being a bit thick here, could you elaborate on 'if there were only unchecked exceptions, you would need to special throws statements and have the same effect without any repackaging' ?
     

    My bad for the content-mangling typo. It was supposed to say if there were only unchecked exceptions, you would need no special throws statements and have the same effect without any repackaging'

    If all exceptions were unchecked, you could freely choose where in the call hierarchy to catch them without ugly method signatures or repackaging. Checked exceptions force you to either do error handling (possibly only the pointless "repackaging" type or error handling) close to where the exception is thrown, or to have "throws" statements all over the place. IMO this is more than a disadvantage than a benefit.

     



  • @brazzy said:

    If all exceptions were unchecked, you could freely choose where in the call hierarchy to catch them without ugly method signatures or repackaging. Checked exceptions force you to either do error handling (possibly only the pointless "repackaging" type or error handling) close to where the exception is thrown, or to have "throws" statements all over the place. IMO this is more than a disadvantage than a benefit/

     

    As a C# developer I don't get the option (all exceptions are unchecked), but yes you are free to catch the exception anywhere up the stack...

    In terms of repackaging it all depends on the design of your application, but say in an SOA architecture you probably don't want SQL Exceptions popping out from your services (sure have it in the call stack). I think repackaging has a value in the right situations, my rule of thumb is, 'repackage if you can add extra value and the extra abstraction will improve the maintainability of the application. I find standards such as 'all exceptions must be repackaged', pointless and cause more complication.

     

     

     

     

      



  • @brazzy said:

    It forces you to either scatter Exception handling code around (which defeats the point of exceptions) or pollute your method signatures with lists of "throws" clauses that get longer the farther up the call hierarchy you are:

    public void mainAppMethod()
    throws IOException, SQLException, RemoteException, InterruptedException, NoSuchMethodException, InstatiationException, ParserConfigurationException, TransformerException, UserException, ...
    {
    }

    As others have said, this shouldn't happen. With a proper exception hierachy, the higher level code you are dealing with, the more general an exception could be thrown.

    e.g. consider an application which compiles reports on health issues different countries faces.. you might have the following call hierarchy while accessing information on a particular demographic:

    main application -> report builder -> environment information -> demographic -> database access

    Now lets assume we have an SQL access problem reading this data. Does the main application need to know that perhaps the query passed to the database had the wrong syntax? No. All the main app needs to know is whether the report builder worked.
    Does the report builder need to know? No, all it cares about is whether environment information loaded correctly. etc etc..

    As you would hopefully see, the demographic code is responsible for getting the demographic information from the database, so only it should care about why this problem occured. If this exception cannot be recovered from, then it should be logged, and the exception passed up the chain, but as a more general exception - perhaps a DemographicNotFound exception, or something else indicating a 'useful' problem with the demographic which the attempted load occured on. Would this DemographicNotFound exception be useful for the main app? probably not, but perhaps it might be useful for the report builder, so it could be passed up the chain. Then again, maybe you would catch it and handle it.. or throw a new InvalidEnvironment (or similar exception)..

    The point is that you do not want to pass every low level exception up to your high level classes. From my experience, Exceptions are very common. If you are passing them all the way up to your main app, then chances are that your main app doesn't actually do very much.



  • @The Enterpriser said:

    PUKE
     

     Wow. You need to learn linebreaks.



  • How many of those 2,751 posts of yours have been constructive... from looking at other threads you have participated in I would guess 'not many'.

    I need to learn the forum intricacies. The forum needs to learn formatting consistancy.



  • @The Enterpriser said:

    I need to learn the forum intricacies. The forum needs to learn formatting consistancy.
     

    Nope, just linebreaks.



  • Of my 8 posts (9 including this one) on this site, I have been directed to 3 completely different text input pages. One seems to only accept BB forum code, one accepts only html, and this one which seems to be be richtext/html. For a new user, it is not immediately clear that the formatting rules for each type of reply are different. I'm not going to lambast the forum software because (a) it is a free service and (b) others have already done that for me - however I will say that criticizing a new user for assuming that the same formatting will be applied for replies made on the same forums, shows a certain level of immaturity.

     



  • @The Enterpriser said:

    criticizing a new user for assuming that the same formatting will be applied for replies made on the same forums, shows a certain level of immaturity.
     

    Or you could have taken it as constructive criticism like many other new users do. If your feelings get hurt this easily, then this might not be the place for you.

    Seriously, we all know the forum software is a pain, but if linebreaks don't work for you, then you have other issues.

     

    Also, I notice you keep mentioning my post count. Do you have some sort of inferiority complex about your post count that is making you keep bringing this up? Certainly I have not held it over YOUR head...



  • I am fine with constructive criticism, I just don't see any here - or in your other posts.

    Constructive criticism in this case probably would have included an explanation of how to insert linebreaks, somehow I get the feeling that you weren't actually trying to help me, but rather boost your ego.

    Regarding the post count thing, I have noticed a trend on internet forums in that each forum tends to have a select few people who believe that quantity of posts is a good substitute for quality of posts. I have been under the impression that you continue this trend - if I am mistaken, then my sincere apologies and I look forward to reading the posts which prove me wrong. To date, of about 30 posts I have read from you, all appear to have been jibes at other users without contributing to the topic at hand. Perhaps I have been unlucky in the posts which I have read and the other 2,740 of them were both on topic and of value - once again, if this is the case then I am sorry for having judged you from what I have read.

    I don't really feel the need for any ongoing flamewars with you however, so we can either draw the line here, or you can have one more passing shot at me then we can ignore eachother - both work for me.


Log in to reply