The Exception to the Exception
-
I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code. Here is my example to end all examples why you do need to catch exceptions sometimes in low level code: We have a component for importing millions of records of data from a delimited text file, process it and store it in cleaned-up form in a database. Now, data in delimited text files is "quite" clean but very occasionally it is not, and we want the import to stop and indicate WHICH column. So we can fix the import data, or the thing which generates it. Let's say that's a date column and we have Convert.ToDateTime() and there are 10 date columns in that structure - it will throw an exception allright which bubbles up but will be the unhelpful
String '184' was not recognized as a valid DateTime
. So - catch the exception, add row and column info and then re-throw. Really, anyone who sees this as wrong must be working with mickey-mouse applications where you never have to sift through millions of records to find the one datum which is wrong. Isn't it? Out of this "purity" of exception handling we get abominations like the SQL Server error message "String or binary data would be truncated." (I know it's finally handled as of SQL Server 2019, but it's been around for decades.)
Exception handling is an alternative to solving the source of the problem or finding an alternative solution. For example, "cleaning" data at the source and adding to a suspense file is usually preferable to throwing exceptions in the back end.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
-
nepdev wrote:
catch the exception, add row and column info and then re-throw.
So really, you are not actually "handling" the exception in the lower level code, you are in fact repackaging it and letting the higher level code deal with it. I think the definition of "handled" would usually be that it is dealt with and the higher level code never knows about it. Now, if your example was, we "handle" the exception at the lower level by logging it and let the processing continue, that might be a wee bit better. ;)
Latest Article:
SVG Grids: Squares, Triangles, Hexagons with scrolling, sprites and simple animation examples -
I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code. Here is my example to end all examples why you do need to catch exceptions sometimes in low level code: We have a component for importing millions of records of data from a delimited text file, process it and store it in cleaned-up form in a database. Now, data in delimited text files is "quite" clean but very occasionally it is not, and we want the import to stop and indicate WHICH column. So we can fix the import data, or the thing which generates it. Let's say that's a date column and we have Convert.ToDateTime() and there are 10 date columns in that structure - it will throw an exception allright which bubbles up but will be the unhelpful
String '184' was not recognized as a valid DateTime
. So - catch the exception, add row and column info and then re-throw. Really, anyone who sees this as wrong must be working with mickey-mouse applications where you never have to sift through millions of records to find the one datum which is wrong. Isn't it? Out of this "purity" of exception handling we get abominations like the SQL Server error message "String or binary data would be truncated." (I know it's finally handled as of SQL Server 2019, but it's been around for decades.)
nepdev wrote:
importing millions of records of data from a delimited text file,
You are dealing with a doomed data format: even if you have complete control over creating, and managing, the deli8mited text file. The question of when, where, to handle errors in this case is like asking if a pig would look better with lipstick before, or after, if flies.
«The mind is not a vessel to be filled but a fire to be kindled» Plutarch
-
I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code. Here is my example to end all examples why you do need to catch exceptions sometimes in low level code: We have a component for importing millions of records of data from a delimited text file, process it and store it in cleaned-up form in a database. Now, data in delimited text files is "quite" clean but very occasionally it is not, and we want the import to stop and indicate WHICH column. So we can fix the import data, or the thing which generates it. Let's say that's a date column and we have Convert.ToDateTime() and there are 10 date columns in that structure - it will throw an exception allright which bubbles up but will be the unhelpful
String '184' was not recognized as a valid DateTime
. So - catch the exception, add row and column info and then re-throw. Really, anyone who sees this as wrong must be working with mickey-mouse applications where you never have to sift through millions of records to find the one datum which is wrong. Isn't it? Out of this "purity" of exception handling we get abominations like the SQL Server error message "String or binary data would be truncated." (I know it's finally handled as of SQL Server 2019, but it's been around for decades.)
oh, sure front end says they have a date check except their date check does not include sanity check so might go through fine till hits server which say, uhm, this is 01/01/1803, and I am setup to only allow values above last year, so error - "invalid date"
-
I agree. No method knows how deep it is going to be. Catch an Exception, add detail, and rethrow as necessary if you can't handle it. Additionally, don't try to validate every value if you're just going to pass it on to another method anyway. Having a whole stack of methods checking and re-checking a value is a waste of time.
I feel a contradiction between your first and third lines. Checking input is a requirement in my workplace (financials). I think everybody here more than once burned itself when said procedure got called from other procedure than the original caller procedure in the design. Which leads to the "do one thing" theory - was it dissected into a chain of procedures just to reach purity? Aesthetics?
-
Yes, adding detail and rethrowing is not "handling".
Adding detail *is* important at the lower level exception. Even if it can't be "fixed" at the lower level, at least provide the detail to indicate where the error really is. I've seen so many cases where staff has to stop and sift through files or tables to get to the one record that caused the problem. Staff work is expensive. If the some key data is logged (or rethrown) and the program can move on, then it will save plenty of time. I think he's complaining that people/tutorials advocate for simply coding a "No Can Do" exception message with no context about where to find the problem.
-
I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code. Here is my example to end all examples why you do need to catch exceptions sometimes in low level code: We have a component for importing millions of records of data from a delimited text file, process it and store it in cleaned-up form in a database. Now, data in delimited text files is "quite" clean but very occasionally it is not, and we want the import to stop and indicate WHICH column. So we can fix the import data, or the thing which generates it. Let's say that's a date column and we have Convert.ToDateTime() and there are 10 date columns in that structure - it will throw an exception allright which bubbles up but will be the unhelpful
String '184' was not recognized as a valid DateTime
. So - catch the exception, add row and column info and then re-throw. Really, anyone who sees this as wrong must be working with mickey-mouse applications where you never have to sift through millions of records to find the one datum which is wrong. Isn't it? Out of this "purity" of exception handling we get abominations like the SQL Server error message "String or binary data would be truncated." (I know it's finally handled as of SQL Server 2019, but it's been around for decades.)
No This is why we have DateTime.TryParse. Exceptions are expensive to throw and catch because they have to stop and construct a stack trace. You most definitely should _not_ just "catch the exception ... and then re-throw" if this is a common enough occurrence. On the other hand, if you don't know for sure that this is a possible outcome and the date-time parsing is not under your control, I totally understand catching & re-throwing with more context. But if _you're_ the one doing `DateTime.Parse` willy-nilly on a string, YATA.
------------------------------------------------ If you say that getting the money is the most important thing You will spend your life completely wasting your time You will be doing things you don't like doing In order to go on living That is, to go on doing things you don't like doing Which is stupid. - Alan Watts https://www.youtube.com/watch?v=-gXTZM\_uPMY
-
Adding detail *is* important at the lower level exception. Even if it can't be "fixed" at the lower level, at least provide the detail to indicate where the error really is. I've seen so many cases where staff has to stop and sift through files or tables to get to the one record that caused the problem. Staff work is expensive. If the some key data is logged (or rethrown) and the program can move on, then it will save plenty of time. I think he's complaining that people/tutorials advocate for simply coding a "No Can Do" exception message with no context about where to find the problem.
-
I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code. Here is my example to end all examples why you do need to catch exceptions sometimes in low level code: We have a component for importing millions of records of data from a delimited text file, process it and store it in cleaned-up form in a database. Now, data in delimited text files is "quite" clean but very occasionally it is not, and we want the import to stop and indicate WHICH column. So we can fix the import data, or the thing which generates it. Let's say that's a date column and we have Convert.ToDateTime() and there are 10 date columns in that structure - it will throw an exception allright which bubbles up but will be the unhelpful
String '184' was not recognized as a valid DateTime
. So - catch the exception, add row and column info and then re-throw. Really, anyone who sees this as wrong must be working with mickey-mouse applications where you never have to sift through millions of records to find the one datum which is wrong. Isn't it? Out of this "purity" of exception handling we get abominations like the SQL Server error message "String or binary data would be truncated." (I know it's finally handled as of SQL Server 2019, but it's been around for decades.)
It also depends on the size of your transaction. If all million rows must commit as one transaction, then you should let the exception bubble up to the level controlling the transaction. Same if the scope of the transaction is at the row level. Skip the transaction for this row, log/capture for replay and move to the next.
-
I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code. Here is my example to end all examples why you do need to catch exceptions sometimes in low level code: We have a component for importing millions of records of data from a delimited text file, process it and store it in cleaned-up form in a database. Now, data in delimited text files is "quite" clean but very occasionally it is not, and we want the import to stop and indicate WHICH column. So we can fix the import data, or the thing which generates it. Let's say that's a date column and we have Convert.ToDateTime() and there are 10 date columns in that structure - it will throw an exception allright which bubbles up but will be the unhelpful
String '184' was not recognized as a valid DateTime
. So - catch the exception, add row and column info and then re-throw. Really, anyone who sees this as wrong must be working with mickey-mouse applications where you never have to sift through millions of records to find the one datum which is wrong. Isn't it? Out of this "purity" of exception handling we get abominations like the SQL Server error message "String or binary data would be truncated." (I know it's finally handled as of SQL Server 2019, but it's been around for decades.)
Yes, in situations where clear, concise information about success and failure is important, capture errors at a lower level. I like to accumulate them, not stopping at error, but storing just enough information to give a complete analysis at the end, but also assessing the weight of errors as I go to just give up when they are too many to continue. Within the report of successes and failures, I supply an option to undo the storage of the data in case they want to fix their data and then try again cleanly.
-
I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code. Here is my example to end all examples why you do need to catch exceptions sometimes in low level code: We have a component for importing millions of records of data from a delimited text file, process it and store it in cleaned-up form in a database. Now, data in delimited text files is "quite" clean but very occasionally it is not, and we want the import to stop and indicate WHICH column. So we can fix the import data, or the thing which generates it. Let's say that's a date column and we have Convert.ToDateTime() and there are 10 date columns in that structure - it will throw an exception allright which bubbles up but will be the unhelpful
String '184' was not recognized as a valid DateTime
. So - catch the exception, add row and column info and then re-throw. Really, anyone who sees this as wrong must be working with mickey-mouse applications where you never have to sift through millions of records to find the one datum which is wrong. Isn't it? Out of this "purity" of exception handling we get abominations like the SQL Server error message "String or binary data would be truncated." (I know it's finally handled as of SQL Server 2019, but it's been around for decades.)
I think Exceptions should be handled where they can be handled. Input data should always be validated - on any level. Not doing this in the low level code is the cause of the majority of the security bugs. By example: buffer overflow, caused by the high level part (wrong data in the parameters), not checked and not handled in the low level code, and voila, we have a security problem.