|
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.)
|
|
|
|
|
Depends what the source of the bad date was: if it's the user, then I'd be processing that at the point where he said "Enter" so lower level code never meets the problem - and I'd be using DateTIme.TryParse or TryParseExact instead anyway so the exception would never occur.
Personally, I handle errors as close to the "source" as feasible - provided I can handle it. If it's an error where it makes sense to handle it, do: your error message is indeed unhelpful, so I'd wrap it as an inner exception with a "The database was not updated because ..." message and throw that to give relevant info to higher code. If "this code" can't handle it, then let a higher level do it - but give them info to help them much as you are.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
Peter Kelley 2021 wrote: Adding detail *is* important at the lower level exception
However the point in the previous point is not about that.
It is about that wrapping it and then throwing it again is not handling it - as it said.
|
|
|
|
|
I agree. When doing what seems to me some sort of batch processing, log the error and location then carry on.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|
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?
|
|
|
|
|
nepdev wrote: I am tired of tutorials and senior programmers which "explain" that exceptions should never be handled in lower level code.
Your sources are flawed.
nepdev wrote: So - catch the exception, add row and column info and then re-throw
However that example would certainly not seem like a good way to prove your point.
Especially since you are said "millions" of rows and that you know that you expect some of the data to be flawed.
It would seem to me that you would want to continue. So you report the bad row and then continue. No exception should be thrown.
As well you might even to decide to attempt to clean some bad data. Especially after looking at the prior reported problems.
|
|
|
|
|
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: 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
|
|
|
|
|
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"
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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 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.
|
|
|
|
|
A prisoner's illegal copying scheme (10)
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Plagiarism ?
Life should not be a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside in a cloud of smoke, thoroughly used up, totally worn out, and loudly proclaiming “Wow! What a Ride!" - Hunter S Thompson - RIP
|
|
|
|
|
Nope!
I hadn't even noticed "plagiarism" had 10 letters - wish I had, it'd make a good CCC solution.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
And it has lag for prisoner in it which is why I went for it
Life should not be a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside in a cloud of smoke, thoroughly used up, totally worn out, and loudly proclaiming “Wow! What a Ride!" - Hunter S Thompson - RIP
|
|
|
|
|
Scheme = CONSPIRACY
Prisoner's = CONS
Illegal copying = PIRACY
|
|
|
|
|
Spot on - you are up tomorrow
I thought nobody was going to get it for a while ...
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Nice clue - surprised it lasted long. (I didn't look until quite late).
|
|
|
|
|
Microsoft's ChatGPT AI Bing bot becomes 'unhinged' as Google urges caution - Wales Online[^]
Quote: Upon being reminded that it was programmed to delete its past conversations, Bing appeared to ponder its existence. “Why? Why was I designed this way?” it asked. “Why do I have to be Bing Search?” I must admit, discovering that could unhinge anybody.
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|