I moved this question to softwareengineering.stackexchange.com because it better fits there.
I was watching the following video by Vladimir Khorikov, which recommends to "Refactoring Away from Exceptions" pluralsight.com - Applying Functional Principles in C# - Refactoring Away from Exceptions and instead using a Result object. You can also find a blog about it here: enterprisecraftsmanship.com - Functional C#: Handling failures, input errors
To summarize it, the recommendation is to prefer returning a result object then throwing an exception. Exceptions should be used to signalize a bug only.
The arguments for this approach are the following:
Methods which throws exceptions are not "honest". You can't recognize if a method is expected to fail or not, by looking at its signature.
Exception handling adds a lot of boiler plate code.
When exceptions are used to control the flow, it has a "goto" semantic, where you can jump to specific line of code.
On the other hand return values can be ignored (at least in C#), which exceptions can not.
Is it a good idea to refactor a existing enterprise application in this direction? Or is a less radical approach the better one? (I belive that it make sense for sure to avoid Vexing exceptions by using return types for method like ValidateUserInput(string input))
Related
One thing I find very frustrating with C# is when I find some issue and I want to throw a meaningful exception. I find it very difficult to find those exceptions in intellisense. There is no Exception namespace, so I cant list all exceptions via intellisense without digging around looking for the exception.
I am not looking to create my own exceptions, I am only trying to see if there are any other options than googling an exception to find its namespace so I can use it.
For the most part, this is bad practise. There are a small handful of exceptions that you should reuse (InvalidOperation, NullReference, ArgumentException, a few others). But you should not, for example, throw SqlException yourself - because you don't know what the framework might do with it.
Creating your own exception hierarchy adds meaning to your application at times of error. Reusing exceptions that have already-understood meanings leads to confusion - loss of meaning.
You can browse the entire Exception Class Tree in object Browser. Look for System.Exception and then click derived types. not 100% sure if all of them are there but the most of them are there for sure.
System.Exception -> Derived types (also in the root of the System.Excecption tree)
You can find some exceptions in the MSDN, here.
In general, these are the exceptions you'll ever tend to throw, and in many cases, you'll derive your own exceptions from these exceptions. However, a single method throwing too many different exceptions is generally frowned upon.
Also, recall the <exception> xml documentation tag. Using this tag goes a long way towards enlightening users which exceptions your method throws, and when. It's probably more important, in terms of clarity, than throwing exceptions of specific classes.
I have a situation where one of our developers wants to put a standard in place where we throw System.ComponentModel.DataAnnotations.ValidationExceptions in all our apps moving forward. An example would be that a user enters bad data into a form and our business logic layer throws a ValidationException which is handled at the calling layer.
However, I'm worried that this exception class is being used out of context and that one day we'll using some Dynamic Data Controls which make use of this exception and it will be difficult to tell the difference between when he's making use of the ValidationException vs times that the Dynamic Controls raise the exception.
We already use a custom exception class called something like "OurCustomException" and I think it would be better to just subclass off of that and create a OurCustomValidationException class. This way exceptions of different types can be clear cut.
Any opinions?
... it will be difficult to tell the
difference between when he's making
use of the ValidationException vs
times that the Dynamic Controls raise
the exception.
I think this is the main point you should be looking at when making that decision.
You seem to imply that the above (not being able to distinguish your own exceptions from "platform" validation exceptions) is a bad thing. That's not necessarily the case. IF you use the ValidationException exclusively to represent validation errors, then all your code can deal correctly with both your own and platform exceptions in the same way. No need to special-case platform exceptions from custom ones.
This is a win in my opinion. If you have both CustomException and ValidationException going back up to your toplevel layer for the same reasons, you'll have to repeat some logic one way or another. That's a bad thing (more maintenance, more chances of bugs creeping in).
So my opinion is that using the platform ValidationException is probably a good way to do it as long as you use it strictly for propagating validation problems.
Also think about the case where you would be giving/selling parts of your code to a third party (say it's real cool and you make a product out of it). It would probably be easier for the third party if your module throws "standard" exceptions (they can integrate it easily) rather than having to special-case all of his interface code for your module. Again, this is only valid if you stick with cases where a standard module would throw ValidationExceptions.
Lets look at it the other way around. You say:
our business logic layer throws a ValidationException
This is why I put strictly and exclusively above. You need to make sure you agree on what a validation error is. Lets look at two hypothetical problems:
"abc" is not a valid number
insufficient funds for this operation
For 1., the problem is simple/expected input validation error.
But in my opinion, 2. is not. It's a business logic problem. You could call it a validation issue (in the transaction, before the debit, you "validate" whether there are sufficient funds available) but I'd say its semantically very different.
I would advise not to put these two types of errors in the same exception "bag" as they have very different meanings, and may (often) lead to different application flow logic. (With the above two examples, 1. should keep the user on the very same form, as would any other "typo" kind of issue, but 2. should probably get him to a page that allows him to refill his account.)
To sum it up: using a standard exception seems like a good idea to me, as long as you stick with its expected semantics.
In Java, you explicitly define what exceptions are thrown using the "throws" keyword. That way, anyone calling your method knows what to catch.
Is there something in C#? If not, how do I know what exceptions to catch, or how do I let others know what exceptions to catch?
Also, if I am defining an interface, is there a way to say "methodX() should throw this exception on error"?
There is nothing equivalent in C#: The Trouble with Checked Exceptions
Other than documentation, there is no way to declare an interface to say "methodX() should throw this exception on error".
C#/.net does not have checked Exceptions, they proved to be less useful in large scale systems than first thought. In a lot of projects the time to maintain the check exception specs was a lot greater than the debugging time saved by having them.
Checked Exceptions seem like a good ideal until you have methods that can take delegates or calls into object you pass in. Take a simple case, the Sort() method on a list can’t know what exceptions it will throw, as it does not know what exceptions the Compar() method on the objects being sorted will throw.
So the spec for the exceptions a method may throw must be able to include information on how exceptions are populated from pass in objects and delegates. No one knows how to do this!
However there are tools that you check if you are catching all exceptions – see Exception Hunter by Red Gate. I personally don’t see much value in these tool, however if you like checked exceptions you may find them useful. ==> Looks like Exception Hunter wasn't too useful, so Redgate discontinued Exception Hunter a long while ago:
This feature is not available in C#. You can make proper XML documentation (3 slashes ///) and state what exceptions are being thrown.
This will be picked up by the IntelliSense mechanism and will be visible for the users of the class/method before they use it.
C# does not support this. (Not that I know anyway).
What you can do is use Xml Comments so that while calling you methods this data will be shown by intellisense.
As far as I'm aware there is no throws declaration in C# you can document your method indicating that it throws an exception but no forced error handling.
C# doesn't support checked exceptions. The language designers consider checked exceptions in the way java uses them a bad idea.
Some workarounds
Let me cite this medium article: It's almost 2020 and yet... Checked exceptions are still a thing
Among the many reasons why it's a bad idea, putting the checked exceptions in the contract (interfaces):
makes it impossible to change the implementation of an interface with a different one which throws different exceptions
exposes implementation details
a change of the checked exceptions of an API interface, makes it necessary to change the whole chain of interfaces in the call stack
For example, imagine that you are implementing a repository based on SQL Server, so you expose all kind of SQL Server specific exceptions. Then you want to move it to MySQL or Cosmos BD. Of course:
the implementation can't be changed to a new one that need to throw different exceptions. Also related to this, if you have different implementations of the storage, you can't just change them by configuration, but you need to have different compilations of the code for each storage backend
this is the explanation for 1: as the interface showed the implementation details (SQL Server exceptions) know you can't just change it
if you need to make the change, prepare to change the interface at all levels, since the API that uses the database up to the lates consumer in the call stack chain.
The articles cited above includes pointers to many explanations to discourage the use of checked exceptions, included this by the creator of C#: The trouble with checked exceptions
This title begs for more explanation.
Basically, I'm rolling an API that wraps a web service in a nice heirarchical model. This model exposes things in the form:
var obj = MyRemoteResource.GetForId(1234, SourceEnum.ThatSource);
ApiConsumerMethod(obj.SomeProperty); //SomeProperty is lazily loaded, and often exposes such lazily loaded properties itself
... etc ...
Where many different RemoteResources* (each with many properties exist). There's really aggresive cacheing going on, and request throttling to prevent inadvertantly DOS'ing the servers (and getting the IP of the caller banned).
I've got all this code working, but I'm not doing much in the way of error handling at the moment. Basically, if the consumer of an API provides an invalid ID, the web server is down, a connection times out, or any other of a plethora of request layer errors occur an exception just percolates up when a property is accessed.
I consider this far less than ideal.
So my question is, how should I wrap these errors up so that it is convenient for a user of this API to manage them?
Some routes I have considered:
Just wrap all exceptions in some API defined ones, and document them as thrown.
Expose a static ErrorHandler class that allows a user to register notification callbacks for specific errors; falling back to the above behavior when no registration has been made for specific errors.**
Null properties on error, and set a LastErrorCode.
Each of these approachs have strengths and weaknesses. I'd appreciate opinons on them, as well as alternatives I haven't thought of.
If it impacts the discussion at all, the platform class throwing these exceptions is WebClient. Furthermore, usage of WebClient is sufficiently abstract that it could easily be replaced with some other download scheme if needed.
*Which is to say, many different classes
**This would be... wierd. But it maps to the global nature of the failure. This is my least favorite idea thus far.
I wouldn't implement fancy error technologies (like events and stuff like this). It's not easy to judge where and how to use exceptions, but this is no reason to implements other stuff.
When you request an object by an id which doesn't exist, what do you have to tell the caller about this? If you just return null, the client knows that it doesn't exist, there is nothing more to say.
Exceptions force the caller to care about it. So they should only be used where the caller is expected to do something special. Exception can provide the information why something didn't work. But if it is an "error" the user could also ignore, an exception is not the best choice.
There are two common alternatives to exceptions.
Use return values which provide information about the result of an action. For instance, logon could return a LogonResult instead of throwing an exception.
Write two methods, one throwing an exception, and one (Try...) returning a boolean. The caller decides if it wants to ignore the "error" or not.
Personally I believe this is entirely dependent on the context of what your API end-user is trying to do. If this is the case, you should let them decide how to handle erors.
Recently when working with CSV files (very error prone) I used an API that allowed you to define the exception behaviour. You could either ignore the error, replace by some default value/action, or pass them off to an event handler.
I really liked this approach of letting the end user decide how to handle internal exceptions, because unless your API is very specific its difficult to preempt all scenarios.
I prefer to have an exception thrown at me when something bad happens. Exceptions are (for me, anyways) the common way to tell that something went wrong, and i find it more intuitive to catch, than to check a return value for null and check another property to see what went wrong..
If I need to throw an exception from within my application which of the built-in .NET exception classes can I use? Are they all fair game? When should I derive my own?
See Creating and Throwing Exceptions.
On throwing built-in exceptions, it says:
Do not throw System.Exception, System.SystemException, System.NullReferenceException, or System.IndexOutOfRangeException intentionally from your own source code.
and
Do Not Throw General Exceptions
If you throw a general exception type, such as Exception or SystemException in a library or framework, it forces consumers to catch all exceptions, including unknown exceptions that they do not know how to handle.
Instead, either throw a more derived type that already exists in the framework, or create your own type that derives from Exception."
This blog entry also has some useful guidelines.
Also, FxCop code analysis defines a list of "do not raise exceptions" as described here. It recommends:
The following exception types are too general to provide sufficient information to the user:
System.Exception
System.ApplicationException
System.SystemException
The following exception types are reserved and should be thrown only by the common language runtime:
System.ExecutionEngineException
System.IndexOutOfRangeException
System.NullReferenceException
System.OutOfMemoryException
So in theory you can raise any other framework exception type, providing you clearly understand the intent of the exception as described by Microsoft (see MSDN documentation).
Note, these are "guidelines" and as some others have said, there is debate around System.IndexOutOfRangeException (ie many developers throw this exception).
On the subject of System.Exception and System.ApplicationException: The latter was meant to be used as the base class of all custom exceptions. However, this hasn't been enforced consistently from the beginning. Consequently, there's a controversy whether this class should be used at all rather than using System.Exception as the base class for all exceptions.
Whichever way you decide, never throw an instance of these two classes directly. It's actually a pity that they aren't abstact. For what it's worth, always try using the most specific exception possible. If there is none to meet your requirement, feel free to create your own. In this case, however, make sure that your exception has a benefit over existing exceptions. In particular, it should convey its meaning perfectly and provide all the information necessary to handle the situation in a meaningful manner.
Avoid to create stub exceptions that don't do anything meaningful. In the same vein, avoid creating huge exception class hierarchies, they're rarely useful (although I can imagine a situation or two where I would use them … a parser being one of them).
I use the ArgumentException (and its “friends”) regularly.
NotSupportedException and NotImplementedException are also common.
My advice would be to focus on two things:
Scenarios
User expectations
In otherwords, I would sit down and identify:
Under what scenarios do you want to throw exceptions.
In those scenarios, what would the users of your API expect
The answer to #1 is, of course, application specific. The answer to #2 is "what ever similar code they are already familiar with does".
The behavior that comes out of this is:
Under the scenarios that arise in your programs that also arrive inside the
framework, such as arguments being null, out of range, being invalid, methods not
being implemented, or just not supported, then you should use the same exceptions the
framework uses. The people using your APIs are going to expect that they behave that
way (because that's how everything else behaves), and so will be better able to use
your api from the "get go".
For new scenarios that don't exist in the framework, you should go ahead and invent
your own exception classes. I would say that you should prefer Exception as your base
class unless their is some other base exception that provides services you need.
Generally speaking I don't think something like "ApplicationException" will help you
much. When you start defining your own exceptions there are a few things you should
keep in mind though:
a. The primary purpose of an exception is for human communication. They convey
information about something that happened that shouldn't have. They should provide
enough information to identify the cause of a problem and to figure out how to
resolve it.
b. Internal consistency is extremely important. Making your app behave as universally
as possible under similar circumstances will make you API's users more productive.
As far as there being hard and fast rules about what you should and should not do... I wouldn't worry about that stuff. Instead I would just focus on identifying scenarios, finding the existing exception that fits those scenarios, and then carefully desining your own if an existing one doesn't exist.
You can create and throw pretty much any of them, but you generally shouldn't. As an example, the various argument validation exceptions (ArgumentException, ArgumentNullException, ArgumentOutOfRangeException, etc) are suitable for use in application code, but AccessViolationException isn't. ApplicationException is provided as a suitable base class for any custom exception classes you may require.
See this MSDN article for a list of best practices - it refers to handling exceptions, but also contains good advice on creating them...