-
[Discussion] When NOT to use Structured Exception Handling
Structured Exception Handling (SEH) is a good and efficient way to handle errors. But there are many shortcomings with the SEH which the unstructured counterpart addresses very well. Everyone keeps on recommending using SEH over unstructured exception handling (UEH). Yet they fail to address ways to counter situations which the UEH addresses very well. I feel that it is just a futile attempt by Java type thinkers to superimpose their thinking on us VB programmers.
MSDN says:
Quote:
Originally Posted by MSDN
Structured exception handling is significantly more versatile, robust, and flexible than unstructured. If possible, use structured exception handling.
But in my real life situations I find just the opposite. Apart from very specific exceptional situations, I don’t see how SEH does better than UEH. I couldn’t find one instance where you would get into a situation which is handled in a better way using SEH as compared to UEH.
Here are some specific situations which I find UEH addresses much better than the SEH. (I will put the summary in this first post, and any code examples etc. in the later ones):
- When you do not care much about the error. Your primary concern is that your program should not stop. When it is one line of code, it doesn’t matter much. But imagine the complexity when it is 10 - 15 lines or more.
Typical situations include memory cleanup routines, demo applications etc. - When you want to jump back to the same line or the next line that caused the error, usually after you have corrected the problem with the error in the error handler routine.
Typical situations include complex mathematical or logical problems, implement a Retry/Ignore/Cancel mechanism etc. - Debugging complex code. Situations where you have long running code (maybe in a loop), but it errors out unexpectedly somewhere. You are having trouble spotting the line or specific case that is causing the error. You want to step into it from where it errored out, or simply break on the same line where the error occurred.
A feature to temporarily disable all error handlers should have been handy. I liked the “Break on All Errors” feature in VB6. But it seems like they have removed it from .NET onwards. So what I do now is to temporarily put a “Resume” statement in the error handler code and put a breakpoint there; or maybe simply comment out the “On Error GoTo xxx” line. Sadly I can’t seem to do anything with the SEH in this situation, and it’s a pain in the *** debugging such code, especially when your procedure contains a lot of try…catch blocks.
More suggestions are welcome. I'll include them in this list if they fit here :)
-
Re: When NOT to use Structured Exception Handling
To be honest, there are valid counter points to all 3 of your points listed here.
1) You should care about ever error. Programs should not cause errors, so when they happen that means something was done incorrectly, or something is not stable on the system. Ignoring errors will never get you far.
2) you should never be jumping anywhere in code. You are talking about goto and it just produces spaghetti code. If you have some code that needs to run in a loop, and the given operation inside the loop can possibly cause exceptions to occur, then you can put SEH inside the loop, not outside the loop. This would give you the chance in your code to quit the loop based on certain error conditions, or continue processing to the next iteration of the loop. You could also split a given piece of code out into its own routine, so that you can call the routine in a loop, and handle individual exceptions in the given routine. No need to be jumping around in code via On Error GoTo type statements. This is very bad practice.
3) The only thing I can say about this is you must not be structuring your code in a way that makes it easy to debug. I am not sure if you are just saying your exceptions are bubbling up and you can't tell where they originated from (which is what a stack trace is for).
So I don't really consider an article telling people to NOT use SEH, even quoting MS who is saying you SHOULD use SEH, to be a good thing to be in the codebank.
I am open for discussion on this topic, but I think this really just belongs in the VB.NET forum for discussion. What do you think?
-
Re: When NOT to use Structured Exception Handling
Please move it to the VB.NET forums.
I'll provide situations in support of my answers:
1. When you do not care much about the error.
Statements
vb.net Code:
Private Sub CleanUpUEH()
''unstructured error handling is intentional
''cleanup and reclaim whatever memory we can, ignore if we can't
On Error Resume Next
Connection1.Close()
Connection2.Close()
Connection1 = Nothing
Connection2 = Nothing
DataSet1 = Nothing
DataSet2 = Nothing
DbAdapter1 = Nothing
DbAdapter2 = Nothing
Transaction1 = Nothing
Transaction2 = Nothing
''I need to reach this line in all situations, giving each one of the above a try once
TaskProgress = 100
End Sub
Private Sub CleanUpSEH()
Try
Connection1.Close()
Catch ex As Exception
Finally
Try
Connection2.Close()
Catch ex As Exception
Finally
Try
Connection1 = Nothing
Catch ex As Exception
Finally
Try
Connection2 = Nothing
Catch ex As Exception
Finally
Try
DataSet1 = Nothing
Catch ex As Exception
Finally
Try
Connection2 = Nothing
Catch ex As Exception
Finally
Try
DataSet1 = Nothing
Catch ex As Exception
Finally
Try
Connection2 = Nothing
Catch ex As Exception
Finally
Try
DataSet1 = Nothing
Catch ex As Exception
Finally
Try
DataSet2 = Nothing
Catch ex As Exception
Finally
Try
DbAdapter1 = Nothing
Catch ex As Exception
Finally
End Try
Try
DbAdapter2 = Nothing
Catch ex As Exception
Finally
Try
Transaction1 = Nothing
Catch ex As Exception
Finally
Try
Transaction2 = Nothing
Catch ex As Exception
End Try
End Try
End Try
End Try
End Try
End Try
End Try
End Try
End Try
End Try
End Try
End Try
End Try
''I need to reach this line in all situations, giving each one of the above a try once
TaskProgress = 100
End Sub
-
Re: When NOT to use Structured Exception Handling
In your UEH you are just being lazy and saying, try to do all these things, but if something craps out, i don't care.
That is just bad programming, I'm not trying to pick on you, but it is.
You aren't even calling dispose on any of those objects either. So any unmanaged memory that may have been allocated because of your use of those object, you don't free that memory, and you may be holding locks onto things because of it.
Your SEH example is just poor.
I could write the same code (but better because it will actually clean up the objects propery and dispose of them) just like this:
Code:
Private Sub CleanUpSEHProperly()
CloseDBConnection(Connection1)
CloseDBConnection(Connection2)
DestroyDisposableObject(Connection1)
DestroyDisposableObject(Connection2)
DestroyDisposableObject(DataSet1)
DestroyDisposableObject(DataSet2)
DestroyDisposableObject(DBAdapter1)
DestroyDisposableObject(DBAdapter2)
DestroyDisposableObject(Transaction1)
DestroyDisposableObject(Transaction2)
End Sub
Private Sub CloseDBConnection(ByVal myConnection As Data.SqlClient.SqlConnection)
'IF NOT DONE YET, CLOSE DB CONNECTIONS
Try
If myConnection IsNot Nothing AndAlso _
myConnection.State <> ConnectionState.Closed Then
myConnection.Close()
End If
Catch ex As Exception
'HANDLE ERROR, MAYBE LOG EXCEPTION HERE
End Try
End Sub
Private Sub DestroyDisposableObject(ByVal myObject As IDisposable)
Try
myObject.Dispose()
Catch ex As Exception
'HANDLE ERROR, MAYBE LOG EXCEPTION HERE
Finally
myObject = Nothing
End Try
End Sub
-
Re: When NOT to use Structured Exception Handling
Both systems will work for many situations. There is not a functional advantage to one over the other (assuming that the items being deleted don't have any unmanaged issues) that I can see. However, that is not to say that there is not a reason to choose one over the other.
After all, GOTO works just as well as If statements, and has the same underlying code, yet I would never choose GOTO. Since the two are functionally equivalent, on what do I base my aversion to GOTO? One could simply answer: Clarity, but it goes far deeper than that. We don't write code simply to function, but to maintain, as well. If routines are written that cannot be maintained, are they actually useful? I would argue that in such a case they are only useful if they are utterly static and immutable, which is seldom the case with code. After all, it is hard to even re-use any non-trivial code that can't be maintained, because if it can't be maintained, it generally can't be comprehended sufficiently to know under which conditions it will work. This would argue that the way we code, indeed the very languages we use, as well as how we use them, are founded as much or more on clarity than on simple functionality.
With that understanding, SEH has value beyond its functionality. I would expect that we code largely by recognizing patterns in code and replicating those patterns. Every study of 'human intelligence' seems to end up in the same place: We are only really good at pattern recognition, and wherever we think we are being intelligent, we have actually just found a new way to apply our superior capacity for pattern recognition. Most higher level languages try to encapsulate code to facilitate recognition. The crime of GOTO is that it breaks the continuity of the code, making the pattern hard to recognize. UEH would do the same thing. The fact that an error will be ignored is not encoded into the pattern, whereas with SEH, the error handling is intrinsic to the pattern.
Just speculation, but not necessarily wrong, either.
-
Re: When NOT to use Structured Exception Handling
Sorry.. my internet connection went off while I was posting.
Actually those statements I mentioned in the example are just indicative. What I meant out of them is that "they are some statements that might cause errors". Keeping in view that memory is cheap and abundantly available now, we don't care too much about a few objects that are left in the memory while our program is running as that will be automatically reclaimed anyway when our applications closes.
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Pradeep1210
Sorry.. my internet connection went off while I was posting.
Actually those statements I mentioned in the example are just indicative. What I meant out of them is that "they are some statements that might cause errors". Keeping in view that memory is cheap and abundantly available now, we don't care too much about a few objects that are left in the memory while our program is running as that will be automatically reclaimed anyway when our applications closes.
What you are saying here is that instead of writing good code, you are fine with writing bad code, because you don't think there will be much of an impact on the application, so it is ok to cut corners and be lazy about this part of your application.
Everyone wants to spend time writing the application itself, but never to write the proper error handling and other parts that make the application work correctly. They just want straight processing and want to assume everything will work all the time, and when it doesn't well who cares.
Just like all the people I see posting on here "my app works on my computer, but it doesn't work on anyone elses". Because people just write an app, assume it will always work just because it does on 1 computer, and think they are done.
Writing code is like painting or any other art. Some people are good at it naturally, some people need to learn a lot before they are any good, practice will always make you better.
Someone can paint a crappy painting and call it art, just like someone can write crappy code and call it a program. Just because it may work, is never an indication it was written well. As shaggy says maintenance and life cycle is very important to a program. Just because you CAN do something in code, doesn't mean its the best way to do it. UEH is really ONLY in the VB language now because SEH didn't exist in VB before .NET, and lots of code needed to be easily ported over to .NET from VB6. It is legacy...
Also if you were to go on a job interview for a dev job, and they asked you to write out some error handling code, and you gave them either of your SEH or UEH examples from your post, I don't think you would be hearing back from them.
-
Re: When NOT to use Structured Exception Handling
there's two points I want to touch upon here....
First #3:
Quote:
Debugging complex code. Situations where you have long running code (maybe in a loop), but it errors out unexpectedly somewhere. You are having trouble spotting the line or specific case that is causing the error. You want to step into it from where it errored out, or simply break on the same line where the error occurred.
A feature to temporarily disable all error handlers should have been handy. I liked the “Break on All Errors” feature in VB6. But it seems like they have removed it from .NET onwards. So what I do now is to temporarily put a “Resume” statement in the error handler code and put a breakpoint there; or maybe simply comment out the “On Error GoTo xxx” line. Sadly I can’t seem to do anything with the SEH in this situation, and it’s a pain in the *** debugging such code, especially when your procedure contains a lot of try…catch blocks.
Ctrl+alt+E = brings up an Exceptions dialog box.... It's that second entry you are interested in "Common Language Runtime Exception" ... first checkbox under the "Thrown" column... if it's checked, works like VB6's Break on all Errors.... when un-checked works like "Break on Unhandled Errors" ... if you also uncheck the second column, it isn't going to stop for no-one (works like it would for the end user).
Next #2:
Quote:
When you want to jump back to the same line or the next line that caused the error, usually after you have corrected the problem with the error in the error handler routine.
Typical situations include complex mathematical or logical problems, implement a Retry/Ignore/Cancel mechanism etc.
On one hand I agree... I wish there was a "Retry" command I could use at the bottom of my Catch to-rerun the Try block.... but there isn't.... so you have to settle for a loop of some kind, where you check a flag.... and the last thing in your try should be the flipping of that flag to exit the loop.
-tg
-
Re: When NOT to use Structured Exception Handling
Am I just going crazy or did Microsoft initially have a "Retry" in VB.Net?
I have a vague recollection of seeing it when they were doing the very first round of .Net roadshows, ie you'd have Try...Catch...Retry...Finally
Just doing a little googling finds this on microsoft.com where someone is bemoaning the fact that VB.Net has Retry but C# doesn't.
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
keystone_paul
Am I just going crazy or did Microsoft initially have a "Retry" in VB.Net?
I have a vague recollection of seeing it when they were doing the very first round of .Net roadshows, ie you'd have Try...Catch...Retry...Finally
Just doing a little googling finds
this on microsoft.com where someone is bemoaning the fact that VB.Net has Retry but C# doesn't.
If they did, it was likely only in the VB7 beta, I don't think it ever made it to RTM even in .NET 1.0, because if it had, it likely wouldn't have gotten dropped due to compatibility issues. I started using .NET from VB6 when 2003 came out, so I am not sure what beta or versions of 2002 may have had that feature.
-
Re: When NOT to use Structured Exception Handling
Yeah it may well have been a beta release of the very first .Net.
Despite playing with the first versions I didn't really switch to .Net in anger till 2005 so I wasn't sure if it was something that was around and then ditched.
-
Re: When NOT to use Structured Exception Handling
Only very few keywords have ever been actually dropped from the language, and I think most of them were around from the original BASIC versions and very early Basic procedural programming.
Hell, even REM still exists for commenting
-
Re: When NOT to use Structured Exception Handling
Keystone - no you aren't crazy - I remember seeing the samething too... but then the first time I tried it, it wasn't there.... so I thought maybe I imagined it... I have a feeling it was breiefly in some beta version of 1.0... and for what ever reason dropped.....
-tg
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
kleinma
1) You should care about ever error. Programs should not cause errors, so when they happen that means something was done incorrectly, or something is not stable on the system. Ignoring errors will never get you far.
That adds a lot of code that is unnecessary for us depending on specific situation. As coders, we are not decision makers. If we are told to suppress errors, we must suppress errors. So, what happens when we “intentionally” want to suppress any error that is raised? The reason could be anything ranging from business to technical.
Quote:
Originally Posted by
kleinma
2) you should never be jumping anywhere in code. You are talking about goto and it just produces spaghetti code. If you have some code that needs to run in a loop, and the given operation inside the loop can possibly cause exceptions to occur, then you can put SEH inside the loop, not outside the loop. This would give you the chance in your code to quit the loop based on certain error conditions, or continue processing to the next iteration of the loop. You could also split a given piece of code out into its own routine, so that you can call the routine in a loop, and handle individual exceptions in the given routine. No need to be jumping around in code via On Error GoTo type statements. This is very bad practice.
No, I’m not talking about GOTO. I’m talking about resuming from error. An error handler mechanism should provide some way to locate and optionally jump back to the same line that produced the error, and possibly resume processing from there after I have done the necessary error handling. If the mechanism provides no way, it is not robust. If the mechanism wants me to think the same way its designers thought, it is not flexible either.
Take a situation where I have a long mathematical problem, spawning many lines of code. A divide by zero may occur at any line. All I want to do in such case is that reset the divisor to 1 and continue from same line again until I have achieved my aim. And what happens if I want the user to give me a new divisor and continue when a divide by zero error occurs??
Quote:
Originally Posted by
kleinma
3) The only thing I can say about this is you must not be structuring your code in a way that makes it easy to debug. I am not sure if you are just saying your exceptions are bubbling up and you can't tell where they originated from (which is what a stack trace is for).
Yes, I mean the same. But I want it to break on the same line where the error occurs, so that I can examine everything in detail at that point to understand the root of the problem – all variable values, all objects, all data etc that might be related to that situation. Situation becomes complex when the error doesn’t always occur at the same point (depending on class data).
Quote:
Originally Posted by
kleinma
So I don't really consider an article telling people to NOT use SEH, even quoting MS who is saying you SHOULD use SEH, to be a good thing to be in the codebank.
My sole point of quoting MS was that the statement is misleading. Which code should we call versatile, robust & flexible? One that allows whatever you want to do, the way you want to do (whether it is considered right or wrong practice by others is a different issue altogether); or the one that does not provide ANY way of doing what you want to do?
-
Re: When NOT to use Structured Exception Handling
"Take a situation where I have a long mathematical problem, spawning many lines of code. A divide by zero may occur at any line. All I want to do in such case is that reset the divisor to 1 and continue from same line again until I have achieved my aim. And what happens if I want the user to give me a new divisor and continue when a divide by zero error occurs??"
Use what I call Offensive programming, rather defensive..... CHECK the values first... if there's a possiblity that a divisor could be 0, check for that value first... if it's 0, slap the user on the hand and tell them to enter something reasonable. Validate the data first. If there's a chance bad data could get through, then rather than reacting to it, be proactive, and don't let it in the front door in the first place. Exceptions are expensive processing wise.... if there's something you can do to prevent the exceptions in the first place, do so.
"If we are told to suppress errors, we must suppress errors." - I can't even begin to think of what kind of .........[remark suppressed]......... would think that ignoring errors is a valid business decision.... I don't even want to think the problems something like that could cause down the road. That's just insane.... probably a good thing I don't work there... if I did, it wouldn't be for very long.
-tg
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Pradeep1210
That adds a lot of code that is unnecessary for us depending on specific situation. As coders, we are not decision makers. If we are told to suppress errors, we must suppress errors. So, what happens when we “intentionally” want to suppress any error that is raised? The reason could be anything ranging from business to technical.
the point is that errors should not be happening at all, and when they do you should be handling them. I don't write code that tries to convert a string into an integer value, and just wrap it in a try/catch block to HOPE it succeeds but not care if it fails. That is why I use things like integer.tryparse() which will not produce an error when a parse fails, and will not require a try/catch block in the first place. If you are not the decision maker, then whoever your decision maker is, isn't a very good software developer. To just say something like "well who cares if my app is eating up another 10MB of memory with objects it isn't using, it will all go away when i close the app". That is just plain BAD PROGRAMMING. I can't say anything else about it, but just not caring how bad your code is, is bad programming.
Quote:
No, I’m not talking about GOTO. I’m talking about resuming from error. An error handler mechanism should provide some way to locate and optionally jump back to the same line that produced the error, and possibly resume processing from there after I have done the necessary error handling. If the mechanism provides no way, it is not robust. If the mechanism wants me to think the same way its designers thought, it is not flexible either.
Take a situation where I have a long mathematical problem, spawning many lines of code. A divide by zero may occur at any line. All I want to do in such case is that reset the divisor to 1 and continue from same line again until I have achieved my aim. And what happens if I want the user to give me a new divisor and continue when a divide by zero error occurs??
divide by 0 in a complicated math routine should only happen if
a) you didn't validate user inputs prior to using them in your math
b) your math routine is not implemented properly
Even if you did have a routine that does a complex math routine, and could divide by 0, I would simply put that code in its own function, and wrap the function in exception handling.
You say you are not talking about GoTo, but what do you think "on error resume next" is? It is really just a goto.
Quote:
Yes, I mean the same. But I want it to break on the same line where the error occurs, so that I can examine everything in detail at that point to understand the root of the problem – all variable values, all objects, all data etc that might be related to that situation. Situation becomes complex when the error doesn’t always occur at the same point (depending on class data).
You can do this with the stack trace... next time you have an error that bubbles up several exception handlers, so where its being caught is NOT the same routine where the exception occurred, then pull up the stack trace window, and you can step through each line of code that got you to the handler, all the way back to the exception, since class data should not have changed during the bubble up of the exception (unless you did this yourself in code) then the class data is still there for you to debug and look at, and see the values of your data.
Quote:
My sole point of quoting MS was that the statement is misleading. Which code should we call versatile, robust & flexible? One that allows whatever you want to do, the way you want to do (whether it is considered right or wrong practice by others is a different issue altogether); or the one that does not provide ANY way of doing what you want to do?
as shaggy said, versatile, robust, and flexible is not ALWAYS solely in a features capability, but also in its logic flow and maintainability.
All you have really said here is "to use try/catch blocks requires more code for me to write than on error resume next, since on error resume next is only 1 line of code and I don't care what errors out." You also state that you have a hard time finding why an exception occurred, yet you don't care about catching and handling them at all, so that seems somewhat contradictory to me too. Perhaps you are talking about different scenarios on UEH usage, but either way, try/catch does everything you could need it to do, and as I showed you in my example code, you don't need that giant mess of nested try/catch blocks to correctly dispose and clean up objects.
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Shaggy Hiker
Both systems will work for many situations. There is not a functional advantage to one over the other (assuming that the items being deleted don't have any unmanaged issues) that I can see. However, that is not to say that there is not a reason to choose one over the other.
After all, GOTO works just as well as If statements, and has the same underlying code, yet I would never choose GOTO. Since the two are functionally equivalent, on what do I base my aversion to GOTO? One could simply answer: Clarity, but it goes far deeper than that. We don't write code simply to function, but to maintain, as well. If routines are written that cannot be maintained, are they actually useful? I would argue that in such a case they are only useful if they are utterly static and immutable, which is seldom the case with code. After all, it is hard to even re-use any non-trivial code that can't be maintained, because if it can't be maintained, it generally can't be comprehended sufficiently to know under which conditions it will work. This would argue that the way we code, indeed the very languages we use, as well as how we use them, are founded as much or more on clarity than on simple functionality.
…
Just speculation, but not necessarily wrong, either.
There are situations where a GOTO is much more beneficial (cleaner) than putting a lot of nested IFs. But since we are not discussing GOTO here, but exception handling, we will not go more into this (maybe start another thread for this).
Quote:
Originally Posted by
kleinma
What you are saying here is that instead of writing good code, you are fine with writing bad code, because you don't think there will be much of an impact on the application, so it is ok to cut corners and be lazy about this part of your application.
Everyone wants to spend time writing the application itself, but never to write the proper error handling and other parts that make the application work correctly. They just want straight processing and want to assume everything will work all the time, and when it doesn't well who cares.
…
In a project lifecycle, it is not necessary that the same person that wrote the initial code is also maintaining that code. What do you do of a badly written code that you are given to maintain now. You can’t complain that you can’t work on that, because it is badly written. That gives a bad impression about you on your bosses, since the person who originally wrote the code had a good reputation in the organization.
Usually we code how our bosses want us to code. We are not trying to cut corners or be lazy. It is usually that you are not given enough time to write error handlers. If your boss has given some unrealistic deadline to the client, you must confirm that deadline or lose business. Whether you use SEH or UEH is immaterial to him. SEH usually involves more lines of code, planning and testing than UEH where you can get away with maybe possibly bad working code. If the SEH inspite of all goods can’t bring you business, it’s a waste.
Quote:
Originally Posted by
techgnome
there's two points I want to touch upon here....
First #3:
Ctrl+alt+E = brings up an Exceptions dialog box.... It's that second entry you are interested in "Common Language Runtime Exception" ... first checkbox under the "Thrown" column... if it's checked, works like VB6's Break on all Errors.... when un-checked works like "Break on Unhandled Errors" ... if you also uncheck the second column, it isn't going to stop for no-one (works like it would for the end user).
That’s a great thing you pointed out. :thumb:
I had been long looking for this feature but was unable to find. I wonder why it is not there on the mouse right click or menu (I mean why it is hidden in a shortcut). :)
Quote:
Originally Posted by
techgnome
Next #2:
On one hand I agree... I wish there was a "Retry" command I could use at the bottom of my Catch to-rerun the Try block.... but there isn't.... so you have to settle for a loop of some kind, where you check a flag.... and the last thing in your try should be the flipping of that flag to exit the loop.
Nice to see at-least someone agrees with me to some extent. I knew from the beginning that this topic would face sharp criticism. But if it can clear my doubts (probably help some others like me too), I’m ready for it.
Quote:
Originally Posted by
keystone_paul
Am I just going crazy or did Microsoft initially have a "Retry" in VB.Net?
I have a vague recollection of seeing it when they were doing the very first round of .Net roadshows, ie you'd have Try...Catch...Retry...Finally
Just doing a little googling finds
this on microsoft.com where someone is bemoaning the fact that VB.Net has Retry but C# doesn't.
I think they could not implement that properly in the SEH and finally removed it. And now they want to justify themselves by saying that SEH is superior to UEH without quoting adequate reasons for some of those missing features in SEH, that UEH has.
-
Re: When NOT to use Structured Exception Handling
Pradeed, I think maybe you just need to explore SEH a bit more... I think you are missing a few key concepts. I don't see a single place where UEH is better or has any advantage over SEH.
Here, I just wrote some code that will try to open a text file, if it fails, it tries again, but only 3 times, if it fails after 3 times, it will give up. This uses SEH, no goto or on error statements are needed. The logic is simple and easy to follow.
Code:
Dim attempts As Integer = 0
Do
Try
attempts += 1
Dim x As String = My.Computer.FileSystem.ReadAllText("something.Txt")
' exit the loop if no errors
Exit Do
Catch ex As Exception When attempts = 3
Exit Do 'only when failed 3 times
Catch ex As Exception
' process the error here and implicitly re-enter the loop
End Try
Loop
-
Re: When NOT to use Structured Exception Handling
Pradeep1210, I'm noticing that you're actually preferring to use very outdated methodology in .Net, why is this? Do you just not want to learn the better ways of programming these days?
Even I have never used things like 'On Error Resume Next 'or even 'GoTo' since vb4
I think you're just looking for a good argument to keep using your lazy code and calling it good.
Quote:
Originally Posted by
kleinma
Pradeed, I think maybe you just need to explore SEH a bit more... I think you are missing a few key concepts. I don't see a single place where UEH is better or has any advantage over SEH.
Here, I just wrote some code that will try to open a text file, if it fails, it tries again, but only 3 times, if it fails after 3 times, it will give up. This uses SEH, no goto or on error statements are needed. The logic is simple and easy to follow.
Code:
Dim attempts As Integer = 0
Do
Try
attempts += 1
Dim x As String = My.Computer.FileSystem.ReadAllText("something.Txt")
' exit the loop if no errors
Exit Do
Catch ex As Exception When attempts = 3
Exit Do 'only when failed 3 times
Catch ex As Exception
' process the error here and implicitly re-enter the loop
End Try
Loop
Now try it without using an "Exit" keyword...
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
JuggaloBrotha
Now try it without using an "Exit" keyword...
Code:
Dim attempts As Integer = 0
Dim SuccessOrGiveUp As Boolean = False
Do Until SuccessOrGiveUp
Try
attempts += 1
Dim x As String = My.Computer.FileSystem.ReadAllText("something.Txt")
' exit the loop if no errors
SuccessOrGiveUp = True
Catch ex As Exception When attempts = 3
SuccessOrGiveUp = True
Catch ex As Exception
' process the error here and implicitly re-enter the loop
End Try
Loop
-
Re: When NOT to use Structured Exception Handling
How would Retry work? My understanding is that if you have a situation where A calls B which calls C which calls D, and you wrap A in a Try...Catch block, and D throws an exception, then the exception would bubble back up the stack, unwinding each call until the exception is caught in A. If A then had a Retry statement, what would have to be retried? Surely it would retry the line that raised the exception down in D, which would only be possible if the stack had never been unwound. It seems to me that to do that would requite D to know something about the sequence of calls that were used to reach it, so that it would know that state had to be retained. Since local variables are created on the stack, and there is the GC for non-local variables unwinding is relatively easy. If you had to retain the state for B-D, that wouldn't be so easy.
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
kleinma
Pradeed, I think maybe you just need to explore SEH a bit more... I think you are missing a few key concepts. I don't see a single place where UEH is better or has any advantage over SEH.
Here, I just wrote some code that will try to open a text file, if it fails, it tries again, but only 3 times, if it fails after 3 times, it will give up. This uses SEH, no goto or on error statements are needed. The logic is simple and easy to follow.
…
Quote:
Originally Posted by
JuggaloBrotha
Pradeep1210, I'm noticing that you're actually preferring to use very outdated methodology in .Net, why is this? Do you just not want to learn the better ways of programming these days?
Even I have never used things like 'On Error Resume Next 'or even 'GoTo' since vb4
I think you're just looking for a good argument to keep using your lazy code and calling it good.
Now try it without using an "Exit" keyword...
At workplace there has seldom been a chance that I or any of my colleagues coding in .NET initiated any code that involves UEH or GOTO. (It’s all legacy code wherever it is.). We all go by the blind belief what others including MS say – “Use SEH.” And I do that in practice too. But I’m never satisfied with what others say until I believe in that too.
Why I feel SEH is inferior to UEH is – Why are there things in UEH that are absent in SEH? And why does everyone still recommend SEH inspite of that?
This is what I meant with my divisor example:
vb.net Code:
Private Function Calculate(ByVal dividend As Integer, ByVal divisor As Integer)
On Error GoTo ErrH
Dim result As Integer
Do While result <> 100
'calculation1
'calculation2
'calculation3
'calculation4
'calculation5
'calculation6
'calculation7
'calculation8
'calculation9
'calculation10
'calculation11
'calculation12
'calculation13
'calculation14
'calculation15
'calculation16
'calculation17
'calculation18
'calculation19
'calculation20
Loop
Return result
ErrH:
If Err.Number = 11
divisor = InputBox("Divisor was Zero. Enter new Divisor:")
Resume
Else
'other handler
End If
End Function
Each calcualtexx is a mathematical statement, and a divide by zero error might occur. Divisor changes at each step. This is UEH. What will be the equivalent SEH? Do I put each one in a try...catch? Or create a one line function for each one?
-
Re: When NOT to use Structured Exception Handling
I wouldn't use exception handling at all in that case. While it is quicker to write the code to use exception handling, the situation is not exceptional. Some systems take noticeable time to throw even a single exception. Therefore, using exception handling in place of testing for invalid conditions with an If statement, will have a noticeable negative impact on performance.
-
Re: When NOT to use Structured Exception Handling
I think you are coming up with bad coding examples to showcase why you think bad exception handling is good.
That example doesn't do any justice to your cause because you are trying to do math calculations with values you didn't sanitize before using them. Any decent coder is going to check to see if that passed in value, especially if it came from user input, is 0 before using it as a divisor...
If anything, you would throw a DivideByZero exception, which you could catch in the calling code. If you wanted to keep having them enter something, then you would just use the simple loop logic I showed above to continute to prompt them for a new divisor. Using that method you would never do 1 line of math that would actually result in the divide by 0 error occuring.
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Shaggy Hiker
How would Retry work? My understanding is that if you have a situation where A calls B which calls C which calls D, and you wrap A in a Try...Catch block, and D throws an exception, then the exception would bubble back up the stack, unwinding each call until the exception is caught in A. If A then had a Retry statement, what would have to be retried? Surely it would retry the line that raised the exception down in D, which would only be possible if the stack had never been unwound. It seems to me that to do that would requite D to know something about the sequence of calls that were used to reach it, so that it would know that state had to be retained. Since local variables are created on the stack, and there is the GC for non-local variables unwinding is relatively easy. If you had to retain the state for B-D, that wouldn't be so easy.
I've thought about that too.... I'd imagine that the ReTry would Re-Try the Try block..... a sort of "do-over" .... a sort of variation of Resume (which would re-try the line that errored). If not the whole Try block, then it could re-try the point at which the stack came back out into the current block.... so if a called b and b called c and c throws an error that comes all the way back to A.... it would re-try at the call back into B..... ReTry Next could then work the same as Resume Next ...... I'm not sure how viable any of that is though.....
-tg
-
Re: When NOT to use Structured Exception Handling
No... I'm not trying to come up with bad coding examples to showcase anything. All I'm trying to come up with is valid situations where we want to jump back to offending code.
The input parameter divisor is not Zero. However during execution of the loop, it might somewhere become Zero. I want to reset it there itself to some other number and continue from there.
If I do that in calling function, how do I skip those lines before that line that caused the Divide by Zero, when I call it again?
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Shaggy Hiker
I wouldn't use exception handling at all in that case. While it is quicker to write the code to use exception handling, the situation is not exceptional. Some systems take noticeable time to throw even a single exception. Therefore, using exception handling in place of testing for invalid conditions with an If statement, will have a noticeable negative impact on performance.
Basically the equivalent (without any exception handling) would be something like this:
vb.net Code:
Private Function Calculate(ByVal dividend As Integer, ByVal divisor As Integer)
Dim result As Integer
Do While result <> 100
If divisor <> 0 Then
'calculation1
Else
divisor = InputBox("Enter new Divisor:")
'calculation1
End If
If divisor <> 0 Then
'calculation2
Else
divisor = InputBox("Enter new Divisor:")
'calculation2
End If
If divisor <> 0 Then
'calculation3
Else
divisor = InputBox("Enter new Divisor:")
'calculation3
End If
If divisor <> 0 Then
'calculation4
Else
divisor = InputBox("Enter new Divisor:")
'calculation4
End If
If divisor <> 0 Then
'calculation5
Else
divisor = InputBox("Enter new Divisor:")
'calculation5
End If
If divisor <> 0 Then
'calculation6
Else
divisor = InputBox("Enter new Divisor:")
'calculation6
End If
If divisor <> 0 Then
'calculation7
Else
divisor = InputBox("Enter new Divisor:")
'calculation7
End If
If divisor <> 0 Then
'calculation8
Else
divisor = InputBox("Enter new Divisor:")
'calculation8
End If
If divisor <> 0 Then
'calculation9
Else
divisor = InputBox("Enter new Divisor:")
'calculation9
End If
If divisor <> 0 Then
'calculation10
Else
divisor = InputBox("Enter new Divisor:")
'calculation10
End If
'and so on ....
Loop
Return result
End Function
-
Re: When NOT to use Structured Exception Handling
@Pradeep: I'd still be using an If statement, because the cost of an exception is too high to be desirable if there is ANY other option.
@TG: The only way I can see Re-Try working would be if there were no function calls in the block. You can come up with plenty of more plausible examples, but in the situation that I described, with A->B->C->D, what would happen if B showed a form prior to calling C? The catch block would see the error as being the call to B, so I would expect a re-try to re-show the form, which could get ugly. Thus, the only place I think the re-try could start would be at the line of code in D that raised the exception.
Worse, if D trapped exceptions and re-threw them, what would a Re-try mean for an exception handler in A? Does it restart at the point in D where the exception was thrown?
I can barely remember how On Error Goto worked, but I seem to remember that it didn't propagate errors back out of the sub it was in. It should be the same as A retrying the call to B, with all the problems that could create.
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Pradeep1210
Basically the equivalent (without any exception handling) would be something like this:
vb.net Code:
Private Function Calculate(ByVal dividend As Integer, ByVal divisor As Integer)
Dim result As Integer
Do While result <> 100
If divisor <> 0 Then
'calculation1
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation2
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation3
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation4
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation5
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation6
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation7
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation8
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation9
Else
divisor = InputBox("Enter new Divisor:")
End If
If divisor <> 0 Then
'calculation10
Else
divisor = InputBox("Enter new Divisor:")
End If
'and so on ....
Loop
Return result
End Function
Yes, in general, though I dislike InputBox, and if divisor was really just a single variable there would be more efficient ways to write the thing.
There are many more lines of code there, but the performance will be sufficiently better that it really can't be avoided. Exceptions are the one thing that I am aware of which can negatively impact perceived performance in business apps. In high performance games, and the like, Exception handling in that fashion is out of the question, since it can drop frame rates below 1fps.
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Pradeep1210
Basically the equivalent (without any exception handling) would be something like this:
vb.net Code:
Private Function Calculate(ByVal dividend As Integer, ByVal divisor As Integer)
Dim result As Integer
Do While result <> 100
If divisor <> 0 Then
'calculation1
Else
divisor = InputBox("Enter new Divisor:")
'calculation1
End If
If divisor <> 0 Then
'calculation2
Else
divisor = InputBox("Enter new Divisor:")
'calculation2
End If
If divisor <> 0 Then
'calculation3
Else
divisor = InputBox("Enter new Divisor:")
'calculation3
End If
If divisor <> 0 Then
'calculation4
Else
divisor = InputBox("Enter new Divisor:")
'calculation4
End If
If divisor <> 0 Then
'calculation5
Else
divisor = InputBox("Enter new Divisor:")
'calculation5
End If
If divisor <> 0 Then
'calculation6
Else
divisor = InputBox("Enter new Divisor:")
'calculation6
End If
If divisor <> 0 Then
'calculation7
Else
divisor = InputBox("Enter new Divisor:")
'calculation7
End If
If divisor <> 0 Then
'calculation8
Else
divisor = InputBox("Enter new Divisor:")
'calculation8
End If
If divisor <> 0 Then
'calculation9
Else
divisor = InputBox("Enter new Divisor:")
'calculation9
End If
If divisor <> 0 Then
'calculation10
Else
divisor = InputBox("Enter new Divisor:")
'calculation10
End If
'and so on ....
Loop
Return result
End Function
This is why some of us are having a hard time taking your arguements seriously... that's way over the top....
Code:
Private Sub CheckDivisor(ByRef divisor as Integer) As Integer
If divisor = 0 Then
divisor = InputBox("Enter new Divisor:")
End If
End Sub
Private Function Calculate(ByVal dividend As Integer, ByVal divisor As Integer)
Dim result As Integer
Do While result <> 100
CheckDivisor(divisor)
'calculation1
CheckDivisor(divisor)
'calculation2
CheckDivisor(divisor)
'calculation3
CheckDivisor(divisor)
'calculation4
CheckDivisor(divisor)
'calculation5
CheckDivisor(divisor)
'calculation6
CheckDivisor(divisor)
'calculation7
CheckDivisor(divisor)
'calculation8
CheckDivisor(divisor)
'calculation9
CheckDivisor(divisor)
'calculation10
...
See how much simpler that was?
-tg
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Shaggy Hiker
@Pradeep: I'd still be using an If statement, because the cost of an exception is too high to be desirable if there is ANY other option.
@TG: The only way I can see Re-Try working would be if there were no function calls in the block. You can come up with plenty of more plausible examples, but in the situation that I described, with A->B->C->D, what would happen if B showed a form prior to calling C? The catch block would see the error as being the call to B, so I would expect a re-try to re-show the form, which could get ugly. Thus, the only place I think the re-try could start would be at the line of code in D that raised the exception.
Worse, if D trapped exceptions and re-threw them, what would a Re-try mean for an exception handler in A? Does it restart at the point in D where the exception was thrown?
I can barely remember how On Error Goto worked, but I seem to remember that it didn't propagate errors back out of the sub it was in. It should be the same as A retrying the call to B, with all the problems that could create.
I don't discount that there's issues to work out with it.... I'm just saying, it's an item on my wishlist.... and all of the points you raised are valid, and could be exactly why it was quietly dropped.
-tg
-
Re: When NOT to use Structured Exception Handling
the code doesn't even make sense logically, since you are altering the divisor in the midst of doing 20 calculations using that divisor, how is that ever going to produce any kind of output of use to you? Especially if your defense here is that the divisor is being altered as part of the routine. I fail to see any real world scenario for any code like that...
besides, I would still just implement something like this (which by the way restarts the entire calculation when divide by 0 occurs, not just pick up where it failed with a totally new divisor:
Code:
Private Function Calculate(ByVal dividend As Integer, ByVal divisor As Integer) As Integer
Dim result As Integer = 0
Try
'calculation1
'calculation2
'calculation3
'calculation4
'calculation5
'calculation6
'calculation7
'calculation8
'calculation9
'calculation10
'calculation11
'calculation12
'calculation13
'calculation14
'calculation15
'calculation16
'calculation17
'calculation18
'calculation19
'calculation20
Return result
Catch ex As DivideByZeroException
Throw ex
End Try
End Function
CALLING CODE
Code:
Private Sub DoCalculations()
Dim UserCancelOrSuccess As Boolean = False
Dim myDividend As Integer = 100
Dim myDivisor As Integer = 0
Do Until UserCancelOrSuccess
Try
Calculate(myDividend, myDivisor)
UserCancelOrSuccess = True
Catch ex As DivideByZeroException
'PROMPT USER FOR NEW DIVISOR WITH A DIALOG (NOT INPUTBOX FOR THE LOVE OF ALL THINGS HOLY)
'IF A NEW DIVISOR IS GIVEN, THEN WE WILL TRY THE OPERATION AGAIN, YOU CAN EVEN VALIDATE
'THE DIVISOR IN THIS DIALOG TO PREVENT AN ENTRY OF 0 TO START WITH
'IF USER CANCELLED THE DIALOG, CANCEL THE OPERATION
If dlgGetNewDivisor.ShowDialog() = DialogResult.OK Then
myDivisor = dlgGetNewDivisor.Divisor
Else
UserCancelOrSuccess = True
End If
End Try
Loop
End Sub
-
Re: When NOT to use Structured Exception Handling
And you would need the CheckDivisor call before each statement? In the normal course of the routine the divisor may become zero once in say 1000 times, but we are checking for it after each line?
-
Re: When NOT to use Structured Exception Handling
Code:
Private Function Calculate(ByVal dividend As Integer, ByVal divisor As Integer) As Integer
Dim result As Integer = 0
Try
'calculation1
'calculation2
'calculation3
'calculation4
'calculation5
'calculation6
'calculation7
'calculation8
'calculation9
'calculation10
'calculation11
'calculation12
'calculation13
'calculation14
'calculation15
'calculation16
'calculation17
'calculation18
'calculation19
'calculation20
Return result
Catch ex As DivideByZeroException
''Don't want to throw ex
''If error occurred at calcualtion9
''We want to set divisor = 1
''And retry calculation9
''What do we do??
End Try
End Function
-
Re: When NOT to use Structured Exception Handling
show me 1 real world example where it would make any sense at all to do 20 compounding math calculations (which modify the end result variable AND the divisor variable that was passed into the routine in the first place) and when divide by 0 occurs, you will reset the divisor to 1 and keep going.
It doesn't make any sense, it will produce unexpected results...
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Pradeep1210
Each calcualtexx is a mathematical statement, and a divide by zero error might occur. Divisor changes at each step.
I just wanted to add this: no it won't. Or rather, if it does, you have coded it lazily. There is absolutely no reason whatsoever that you get a divide by zero error. The check for a zero denominator is so basic and simplistic, that not putting a check in is either laziness or you aren't paying attention (or making the all too common programmers mantra 'that can't happen').
Edit: here's my 'real world' example: calculating the intervals on a chart axis. You know the minimum, you know the maximum. The user enters 10.0 for the maximum, and 10.0 for the minimum...Oh noes! Oh noes! It's actually the programmers job to handle this gracefully. It's simplicity to check for this occurrence and prevent an actual error. But what then? Well, things become more complicated - this is where programmers (in my opinion) stick their heads in the sand/switch off their brain (if it was switched on to begin with). They now have to think of a logical and reasonable way of handling of that situation, and what the user expects. Programmers are not users, so almost always get it wrong - they have to think about non-programming issues - and when they've come up with the the user expectation, they have to write extensive code to handle this one div0 error. All because the user (sic) messed up!
[ I know the answer to this, but if anyone says 'throw a message box to the user' I will come through the red pixels of your monitor and slap you ].
-
Re: When NOT to use Structured Exception Handling
Quote:
Originally Posted by
kleinma
show me 1 real world example where it would make any sense at all to do 20 compounding math calculations (which modify the end result variable AND the divisor variable that was passed into the routine in the first place) and when divide by 0 occurs, you will reset the divisor to 1 and keep going.
It doesn't make any sense, it will produce unexpected results...
Here is another example that is more close to real world.
vb.net Code:
Try
'Sub1()
'Sub2()
'Sub3()
'Sub4()
'Sub5()
'success/failure of each of these Subs depends on
'some external process doing some work in realtime.
Catch ex As Exception
'ask user if he wants to Retry/Ignore/Cancel
'Retry=Try that Sub again
'Ignore=Try the next Sub
'Cancel=Get out of here
'so if exception occurred in Sub3, we don’t want to retry Sub1 & Sub2 in any case.
End Try
Quote:
Originally Posted by
SJWhiteley
I just wanted to add this: no it won't. Or rather, if it does, you have coded it lazily. There is absolutely no reason whatsoever that you get a divide by zero error. The check for a zero denominator is so basic and simplistic, that not putting a check in is either laziness or you aren't paying attention (or making the all too common programmers mantra 'that can't happen').
Nah.. I’ve not coded lazily. Nor I’m not assuming “that can’t happen” because I’m trying to handle the same “that can’t happen”. It can happen but once in a blue moon (i.e. exceptional case). Since it is an exceptional case, I obviously won’t put a check at each statement.
The point I have been trying to bring out is how to handle a set of exceptions that might occur with all statements within a block. Then provide a common solution and resume from that point again, until our goal is achieved. I pointed out one in this case (divide by zero), but it could be many others that might occur at each step. We even know of the action to be taken in each case, but want to continue after we have taken the required action. SEH provides NO way to do that but is still called superior. UEH provides ways to do that but is still called inferior.
-
Re: When NOT to use Structured Exception Handling
You can certainly come up with a real world example where it would be quicker to write a single line. The question I raised earlier was whether it was BETTER to write a single line. There is never an advantage to the running of the program, it is only a question of aesthetics. In the previous case, you'd have to assume that you have no control over the code in the subs (either you didn't write them or you are working in a system where you can't alter them), since the code is less than ideal as it stands. However, if you DO assume that you have no means to alter the subs, or alter the fact that they ARE subs, then it comes down to whether it is easier to write one line or write several.
In the short term, I would say that one line is easier. In the long term, I would say it is not easier for two reasons:
1) I don't have faith that On Error style error handling will remain a part of the language, which would cause downstream trouble.
2) I don't have faith that learning On Error style error handling will continue to be a part of the experiences of VB programmers, so you will be writing a construct that does not communicate well.
3) And as a bonus: While a contrived example can be identified where it is easier to not use SEH while also leaving the code fairly comprehensible, those examples are contrived. After all, you need to have a situation where:
a: You can re-run the same item with a reasonable chance for success without needing to ask the user to make a choice.
b: You can't change the code to prevent the exceptional situation in the first place.
If the first one is not true, then SEH will work just as well, and will ultimately be cleaner. If the second one is not true, then the whole question is moot.
-
Re: When NOT to use Structured Exception Handling
Ok, here we go.
For your examples on the math equations, doing 20 calculations in a row is just shotty math at best. Figure a way to simplify most of your equations.
Also, implement a structural test to see if you'll ever get a division by 0, or any error involving 0's
Example:
Lets say I am doing vectors, right? We do some work out, and the ending equation ends up like so:
Dim Answer As Double = Math.Sqrt((x ^ 2) + ( y ^ 2))
That is the magnitude. What you actually should do to prevent errors here, is to do this:
Dim z As Double = (x ^ 2) + (y ^ 2)
If z = 0 Then
Throw new ex As DivideByZeroException
Else
'Do math here
End If
I have to agree, most of your examples are just terrible at proving that UEH is better than SEH. The developers of the language are saying SEH is better than UEH, and obviously, things from UEH aren't in SEH. That leaves it up to us to make our code work, and chances are, if we design the code to tolerate errors by using Try, End Try, and Catch statements, typically we can avoid nasty error calls and have the user change any variables submitted.
Quote:
I wouldn't use exception handling at all in that case. While it is quicker to write the code to use exception handling, the situation is not exceptional. Some systems take noticeable time to throw even a single exception. Therefore, using exception handling in place of testing for invalid conditions with an If statement, will have a noticeable negative impact on performance.
This too is a vaild method for catching errors. It does work faster than throwing exceptions on some systems, because its just a simple check.
vb.net Code:
If x = 0 then
'do this
Else
'do something else
End if.
Also, what I do during debugging stages (which this is probably very bad coding, but during alpha stages, when I'm just testing it, it doesn't matter.) is just recall the function inside of itself if there's an error, OR I do a line by line step to see where there could be a problem.
vb.net Code:
Private Function CheckNumbers(ByVal num As Integer)
If num < 0 Then
'Ask user for new number, set it to variable num2
CheckNumbers(num2)
ElseIf num > 0 Then
Messagebox.show("Number > 0")
End If
I hope I kept my post remotely on subject.
-
Re: [Discussion] When NOT to use Structured Exception Handling
While I agree that my examples are not up to the mark in proving that UEH is superior to SEH, the intention is not to prove that either. Just as I said in one of the earlier posts, I don’t use UEH myself unless absolutely necessary, nor do I recommend anyone to use it until they introspect the pros and cons of each approach themselves. The examples I quoted here are all hypothetical situations to depict that there “could be” situations when a programmer needs to jump back to the offending line for whatever reason. They may not have been the best examples in the world and certainly not the way I would have done them in my applications.
I don’t represent MS and need not necessarily follow a sheep heard mentality blindly believing what they say. My only point here is why should they miniaturize the SEH constructs taking away our flexibility and force us to think/program in a particular way; and still say that SEH is more versatile, robust & flexible than UEH. They provide warnings during compilation for bad code (e.g. variable declared without ‘as’ clause etc.), and a simple warning should have sufficed here too. So why do they want to “force us” to code in a good way?? Was the implementation of equivalent constructs on the lines of Resume and Resume Next so hard to implement in the SEH model? :rolleyes:
So close your ears and eyes once and compare the versatility, robustness and flexibility of each approach yourself and decide for yourself which one fits where.
I don’t criticize anyone and I want a healthy friendly discussion on the topic. (Thanks to everyone who is participating in the discussion on this topic.)
Though all my examples are hypothetical, just assume that you are in a situation when you want to jump back to the offending code. What do you do? All the ways suggested by everyone here are just workarounds or alternative ways to handle the problem. No one ever exactly pointed out how to do that, quoting either bad practice, poor example, lazy attitude, situation won’t ever arise etc. etc. as reasons.
Take situation in post #37 as example. Since, we are coding a hypothetical situation, assume we have full control over the code of each sub as well as the calling routine.
We have 5 different procedures (maybe more, don’t go by number). Assume error occurs in Sub3(). We ask the user what to do, and he tells us to retry. How do we code this using pure SEH approach?
-
Re: [Discussion] When NOT to use Structured Exception Handling
I don't think it's Microsoft, specifically, saying 'thou must use structured exception handling!'.
Structured exception handling has been a tried and true method of handling errors before Microsoft was born; it may not have looked like it, but it was.
The issue is the VB never had it - then it did. I can telly you, I was a tough convert to it, but now I have seen the benefits. But, that isn't the mantra...the new mantra is that: 'thy program shall never cause an error!'
I stick by this - If your program causes an exception handler to fire, you have done something wrong (true, there area few areas where you have little choice to use an exception handler - file handling is an example).
There is a prevalence in the programming world to allow exceptions to 'bubble up' to the caller; I believe this promotes laziness and results in pretty crappy programs with obnoxious dialog boxes. It's a viable technique in a very few circumstances. However, if you are only performing mathematical calculations there is absolutely zero reason an error should occur. Zero. None.
But I, like 100.0% of all other people who program, are lazy. If you think you aren't then I hope someone else is scrutinizing ones code. Because I know I'm lazy, and I make mistakes, I have a global exception handler (and, hopefully, a handler for every thread I create). If that handler ever fires, it means I messed up.
Additionally, and exception handler should be used at the absolute smallest level of granularity - it's actually very lazy to just wrap a whole file writing routine in an exception handler. The larger the error handler span, the potentially larger the 'types' of errors that could occur, and the more difficult it is to generate a meaningful error message - thus most programmers don't. We end up with 'object or with variable not set' error message boxes. Arrgh!
Basically, an Unstructured exception handler does the exact opposite of what's required: wrappers large chunks of code (out of necessity, since it's actually more difficult to create fine granularity unstructured error handling); pretty much ignores most errors; allows for sloppy coding because the error handler catches and often continues, hiding the poor coding (You don't use mahogany for your cabinets if you are going to put a pine laminate on top).
-
Re: [Discussion] When NOT to use Structured Exception Handling
The other thing about bubbling up exceptions is the farther an exception gets sent up the stack, the more chance that the app will not be in a recoverable state, and will need to be restarted.
When you handle errors as they happen properly, you can easily recover the app and the user can continue to go about using it.
If you ignore errors with things like resume next, then the app is likely in an unknown state at that point, and when the user continues to work in it, there is much more chance of it breaking down, because objects are in a miscellaneous state of being alive or destroyed or whatever, because half way through a cleanup routine that had on error resume next, it bombed out.
-
Re: [Discussion] When NOT to use Structured Exception Handling
I would say that Resume Next is entirely possible, but I have serious doubts as to whether Resume is EVER safe. At least, I don't believe the compiler can be written to determine whether Resume even makes sense in the current context.
-
Re: [Discussion] When NOT to use Structured Exception Handling
I suppose the whole matter is preference. You can choose to have good code that shouldn't error, or you can code sloppily, and rely on error catchers to solve your problems.
IMHO, I use error catchers in the alpha/beta stages of a program, but by the time I get that program completed, I have a full blown error system that handles any errors that might occur in the program. It's just a matter of taking the time to actually coding it, and it logically helping the program and making sense.
Resume Next is a habit I haven't even looked into, hearing so much can go wrong with using Resume Next, so I missed that boat, and don't plan on joining it.
-
Re: [Discussion] When NOT to use Structured Exception Handling
Though all these suggestions are undoubtedly good, I think we are deviating from the base topic this thread was started in the first place. We were discussing situations where UEH works better than SEH. So we assume we are in a situation where an error will necessarily occur, and we have to choose whether to use SEH or UEH.
@Shaggy: Whether a programming construct is safe or not depends entirely on the programmer coding it and the situation. (what do you think about Do..Loop without condition?) The language should provide the flexibility to the programmer to do whatever he wants to do and leave the rest unto him. If he wants to execute the same line again, the language should provide him some way to execute the same line again. Same thing with Resume Next.
-
Re: [Discussion] When NOT to use Structured Exception Handling
Quote:
Originally Posted by
Pradeep1210
Whether a programming construct is safe or not depends entirely on the programmer coding it and the situation. (what do you think about Do..Loop without condition?) The language should provide the flexibility to the programmer to do whatever he wants to do and leave the rest unto him. If he wants to execute the same line again, the language should provide him some way to execute the same line again. Same thing with Resume Next.
First up, the language does do that. On Error Resume Next is part of the VB language and you can use it if you want to. If you take pride in the code you write though, you'll choose not to. Remember, UEH is a VB thing. SEH is the only option in C++, Java, C# and I'm not sure what other languages and I don't hear any developers from those camps bemoaning the lack of a construct like On Error Resume Next.
Secondly, there seem to be a lot of people posting to this thread who have never had an issue handling any of their real-world exceptions and maintaining the flow they desire using SEH. You seem to be the only one insisting that there are situations where UEH would be better yet you have yet to provide a realistic example. If you're the one insisting that there are situations where UEH would be better yet you can't even come up with a real-world example then the only conclusion I can draw is that either such situations don't exist or that they are so uncommon as to be insignificant. I have never coded in VB6 so I didn't get used to using On Error at all. I've never used it in VB.NET and I've never met a situation where I thought it could offer me something that a Try...Catch block couldn't.