5 ms·
The author is painting a pretty bad picure of C# error handling that isn't close to reality. In reality, you would never call uint.Parse and let the exception
by Khao 11y ago
The author is painting a pretty bad picure of C# error handling that isn't close to reality.
In reality, you would never call uint.Parse and let the exception bubble up, you'd call uint.TryParse and handle the logic for failure in the method. There is almost always a way to write your code so it doesn't throw exceptions. I'm working on a pretty large C# codebase for a SaaS website and by doing "find in all files" the keyword "catch" I came up with 174 references. For hundreds of thousands of lines of code, we have had to manually catch and handle exceptions only 174 times.
- vitalyd 11y agouint.Parse vs TryParse misses the point. It's very true that doing proper error handling in C# requires more diligence and attention. I know people like to harp on checked exceptions in java, but if used properly, they at least help with the discoverability aspect. The fact that you have 174 catch blocks in a very large codebase only reinforces the blog's point, which is you may be missing error handling blocks or you just have very general handlers.
- Khao 11y agoWe don't really do catch-all blocks and our app is monitored on New Relic where we almost always have a 0% error rate (rarely we get <1%, most often related to a new commit that we can fix right away) The only places where we need good exception handling is when doing I/O (network and filesystem). If you have proper layers to handle those things (with queuing/retrying/logging) you end up with a large codebase with very little places where you have to handle exceptions. Anything that is user-input we use TryParse and we do proper validation on the data before doing anything with it. This method is makes it easier to read because you know what the intent is better than doing parse/catch exception in my opinion.
- vitalyd 11y agoOh, I agree that TryParse is much better than Parse for cases where parsing is expected to fail. But that doesn't detract from having better error handling capabilities in places where it is needed (e.g. i/o). A lot of the .NET i/o APIs will throw 4-5 different types of exceptions, and as the article states, you need to cross reference docs to see which exceptions are possible on certain calls. It's easy to forget or miss because compiler will not care.
- wvenable 11y agoYou don't need to know the types of exceptions that are possible on certain calls. All you need to know is what exceptions you can handle. They are not strongly related.
- vitalyd 11y agoThe ones you can handle is a subset of possibly thrown ones, which means you need to know the superset before deciding which ones to handle. You're just describing the handling strategy: pass on it or handle it. It doesn't obviate the need to know what's possible there.
- wvenable 11y agoAs an example, imagine you're building an application that you know uses sockets. And it's in the requirements that your application must be able recover and re-attempt set of operations. So you look into what kinds of network and socket exceptions exist in your platform, framework, and libraries. From there you decide which ones you should trap and attempt to retry. At no point do you need to know exactly what methods trigger what exceptions. Yes, you do need to know the superset of all exceptions. But that's no different than knowing the superset of all methods or all classes. My point is, a mapping of methods to exceptions is unnecessary. Interestingly enough, you might end up handling exceptions which can never be triggered by your application. But this isn't a bad thing, as this can make your application more robust in the face of change.
- vitalyd 11y ago>As an example, imagine you're building an application that you know uses sockets. And it's in the requirements that your application must be able recover and re-attempt set of operations. So you look into what kinds of network and socket exceptions exist in your platform, framework, and libraries. From there you decide which ones you should trap and attempt to retry. You need to decide where you're going to handle them, and this depends on how much context is required to handle them appropriately. Sometimes this may require doing it right at the point where the method is invoked that triggers the exception. Even if you decide to not handle the exception, you may still want to know the exceptions so you can rollback/adjust state/invariants before letting the exception continue unwinding.
- darklajid 11y agoStandard example for exceptions you have to handle: IO. You can't work around it. Want to open a file? That might throw (file doesn't exist/is inaccessible). Want to write? That might throw. Now, we can argue if you can ignore that, in a controlled environment, and get away with it most of the time.. But that's not what the article is about. He compares exhaustive error handling between the two languages.
- verinus 11y agoimho the author paints a very accurate picture of c#. exception handling remains a mystery to many programmers and is a constant source of errors. error handling in general is hard to do; to have good, what i would call, "error partitioning"- catching errors/exceptions where they can be fixed is difficult- regardless of exceptions. perhaps you got your error handling right and don't need more catch clauses, but if I was you I would investigate :)
- WorldWideWayne 11y agoBad programmers write bad code in general, so basing your opinion of C#'s error handling system on their use of it seems unwarranted. Exception handling does not remain a mystery to many programmers, just many bad programmers. Aside from that, the author is a contributor to Rust so I suspect there could be some small amount of bias here. > ...catching errors/exceptions where they can be fixed is difficult... What's difficult? When your program is about to do something like say open a file - if you don't want an exception to be raised from that code, you wrap that code in a try...catch. In the catch block, you take corrective action. The very simple bottom line with error handling in .NET apps is that you handle/log/notify the user at process and thread entry-points like main and AppDomain.UnhandledException. Other than that, you use a try...catch block.
- vitalyd 11y agoError handling is one of the harder aspects of software engineering, IMHO. For starters, those code paths are less tested than others. See this, for example: https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-yuan.pdf https://www.usenix.org/system/files/conference/osdi14/osdi14...
- kibwen 11y agoIt's a bit of a reach to sling accusations of bias. The Rust project makes it trivial for people to contribute, so anyone with even a passing interest in the language can become a "contributor to Rust" in seconds. If you try and disqualify all of the 1,000+ Rust contributors from writing blog posts about the language, then you most likely also disqualify everyone qualified to write about the language from writing about the language. :P