Now I write C# code after the PHP.
In PHP I create a hierarchy of exceptions guided by the recommendations of the Zend Framework(Symfony now use something similar).
In package(for example Order) I create folder Exception, in this folder(translate from php to C#):
namespace Order.Exception
{
interface ExceptionInterface{}
class ApplicationException : System.ApplicationException, ExceptionInterface{}
class OrderNotFoundException : ApplicationException {}
class SomethingHappensException : ApplicationException{}
}
I need a lot of exceptions(relatively) to conveniently express the things from domain.
Is there any have good practices to create hierarchies of exceptions?
Technical details of creation I understand completely. The issue of good practice.
Two quotes from CLR via C#, 4th Edition:
If you want to define an exception type hierarchy, it is highly
recommended that the hierarchy be shallow and wide in order to create
as few base classes as possible. The reason is that base classes act
as a way of treating lots of errors as one error, and this is usually
dangerous.
(...)
There are versioning ramifications here, too. If you define a new
exception type derived from an existing exception type, then all code
that catches the existing base type will now catch your new type as
well. In some scenarios, this may be desired and in some scenarios,
it may not be desired. The problem is that it really depends on how
code that catches the base class responds to the exception type and
types derived from it. Code that never anticipated the new exception
may now behave unpredictably and open security holes. The person
defining the new exception type can’t know about all the places where
the base exception is caught and how it is handled. And so, in
practice, it is impossible to make a good intelligent decision here.
Related
So my question will sound like a discussion but it's not.
I'm looking for sources on the topic but I can't seem to find many.
Here I go, in .Net, it is possible to create a generic exception and catch it, ie.
class MyException<T> : Exception { }
// ...
catch(MyException<int> e) { }
But I notice that I can't find any use of that in the framework or in big libraries.
So my question is, Where can I find information/discussions on that matter, should you use exceptions with generics, should you avoid it?
The reason I'm asking this is because in many scenarios that I've encountered, it feels right from the thrower's perspective to throw an exception with details in it that use a generic but it feels dirty from the catcher's perspective to catch an exception with a generic in it.
Maybe I'm being too zealous about code practices but I'd really like to find some source material on that matter.
I'd say the main reason is that exceptions are not bound to types, they relate more to a failed action/usage so to speak.
There isn't any need for things like ArgumentNullException<string> or an OverflowException<int> and an OveflowException<long>, the non generic versions suffice.
What you are proposing simply doesn't add any value and it just adds more clutter with additional exception types you need to be handling; remember OverflowException<int> and OveflowException<long> would be different types, you'd need to catch both in a method where any of the two can happen.
Also, any performance arguments don't really apply. If you are catching an exception and unwinding the stack, any boxing going on is the least of your worries...
All in all, it just seems like a useless approach.
I have an example for you from a 'big' library: WCF
FaultException<TDetail>
The point of this is that a client of a WCF service may not be written in .Net and so may not understand Exceptions. However, the clients will understand a fault object - but .Net doesn't let you throw any old object so WCF provides a generic FaultException that you can specialise with your fault type. When you throw one of these exceptions, WCF will extract the fault object and serialise it back to the client.
This is a very special case - allowing faults to be returned to non .Net clients while still allowing the .Net developer to use exceptions. I'm not sure what other use case you would have that would require a generic exception but there is a precedent.
Edit:
The above could also be achieved by a single non-generic FaultException class wrapping an arbitrary object in its constructor. But FaultException is generic so that, if the client is a .Net WCF client then WCF will turn it back into a FaultException of the correct type and allow the client to catch the specific type of fault object e.g.
try
{
service.DoSomething();
}
catch(FaultException<FaultType1>)
{}
catch(FaultException<FaultType2>)
{}
This allows client and server to be written in a symmetrical and (somewhat) familiar manner.
When designing an application, you have two options how to design the exceptions (imo):
You either create specific exceptions for specific cases and inherit them from System.Exception or some other child System exceptions.
Or you create a base exception for your application which inherits probably from System.Exception, like MyAppException : System.Exception, and then you inherit all of the custom exceptions from that base exception.
I will not ask which approach is better in general because I do not think there is a clear answer. However, I would like to know which approach is more suitable for which applications, e.g. one is better for a winforms application and the other for a class library.
There is no clear answer. No matter the type of application, there are cases where it is better to throw a "generic" application (possibly containing the specific one as an InnerException), and there are cases where it makes sense to inherit from an existing exception.
It's more important to consider who is going to catch the exceptions and what he should be able to do with them.
When creating Custom Exceptions is it best practice to make a separate class file for each and every Custom Exception, or append the Custom Exceptions to the end of the class file that they relate to, or create a file (eg. CustomExceptions.cs) and add the Custom Exceptions there?
One class per file is always a good rule.
The other basics:
Mark your exception as [Serializable]
Overload all the System.Exception constructors
Don't inherit from System.ApplicationException
Well ... I would say that you should follow the rule of one class per file, except in case if this exception is just for "internal" functionality in your class. Then you can make it declared inside the class. However, if exposed by any means to outside world, separate it from the class. This exposure could also be seen from the actual probability that this exception goes unhanded to the users of your class. In this case, I would also expose it and would not declare it inside.
As others have stated, one class per file rule is ideal. Another way to think of it, if you have a large application consisting of many modules, you will have multiple namespaces and it's important to keep the exceptions that a certain class method (or set of classes/methods) can throw within their respective namespaces. This makes the code more readable and the reasoning behind your custom exceptions easier to decipher for other developers ... Or for you in 6 months when you forgot why you made half of them :)
public class PageNotFoundException : HttpException
{
public PageNotFoundException()
: base(404, "HTTP/1.1 404 Not Found")
{
}
}
The idea is that rather than typing this each time
throw new HttpException(404, "HTTP/1.1 404 Not Found")
I'd rather write
throw new PageNotFoundException();
I was going to add an overload for including the innerException however I will never use this in a try/catch block.
Would you consider this good practice?
i.e. Inheriting from an exception and passing hardcoded information to base(...).
I decided to rewrite my answer to be specific to your actual question, and in a more broad sense that an MVC application isn't the only thing these best-practices apply to.
(1) Answer. This is not good practice. You should use a exception builder method instead that throws HttpException directly.
public static void ThrowPageNotFoundException() {
throw new HttpException((Int32)HttpStatusCode.NotFound, "HTTP/1.1 404 Not Found");
}
(2) DO. Use exception builder methods (eg. the code I provided). This allows for you to avoid the extra performance cost of having your own exception type, and allows for it to be inlined. Members throwing exceptions do not get inlined. This would be the proper substitute for convenience throwing.
(3) DO. Use base class library exceptions whenever possible, and only create a custom exception when there is absolutely no base exception that meets the needed requirements. Creating custom exceptions adds deeper exception hierarchy, which makes debugging harder when it does not need to be, adds extra performance overhead, and also adds extra bloat to your code base.
(4) Do NOT. Throw the base class System.Exception. Use a specific exception type instead.
(5) Do NOT. Create custom exceptions for convenience. This is not a good reason for a custom exception, because exceptions are intrinsically costly.
(6) Do NOT. Create custom exceptions just to have your own exception type.
(7) Do NOT. Throw exceptions that can be avoided by changing the calling code. This would suggest that you have a usability error in the API rather than an actual problem.
Anyone who has read Framework Design Guidelines from the .NET development series will know these practices, and they are very good practices. These are the very practices that the .NET framework was built upon, and MVC as well.
If you are the one throwing the exception in the first place, then yes - it's OK. However, if you catch an HttpException and then try to throw a PageNotFoundException instead, you should put the original exception as the InnerException.
While this is a nice construct in your own code for your own use, one consideration is that it can promote coding by convention which can be dangerous when you're dealing with other/new developers.
In your own libraries, if you are consistent about throwing a PageNotFoundException whenever a 404 HttpException should be thrown, it might make more sense to catch (PageNotFoundException). However, when you start using other libraries that don't have your custom exception, you will miss 404 HttpExceptions thrown by other code. Likewise, if you have other developers contributing at a later date (or even your own additions in the future), the consideration that PageNotFoundExceptions are what's being caught by most of the functionality may be missed and new 404 HttpExceptions could be thrown in the new modules, which would likewise not be caught by copy/pasted calling code.
Basically, constructs like this increase the acclimation time required for working on the project, and should be handled in such a way that this cost is minimized (made sufficiently visible in an easy to find central shared objects library that isn't already too cluttered).
On the other hand, there is certainly value in centralizing the generation of your HttpExceptions if you're what looking for is essentially the factory pattern benefits; it may be worth just going with that instead if that's what you're trying to get out of it (throw ExceptionFactory.NewPageNotFound()).
Essentially, I'd like a special form of an Interface for Exceptions that requires anyone who uses my object to wrap it with specific catch implementations.
Example
I have an object that sends data to another host. I expect that the realistic implementations will require a way to handle the following exceptions:
HostNotFoundException
InvalidUsernameException
AccountExpiredException
DataAlreadyExistsException
Similar to how an Interface or an Abstract class is used to force the creation of methods and properties in derived classes, is there any way I can force a consumer to implement exception handling the way I expect?
On a similar note, I'd also like to force methods (created via Interface or Abstract) to be able to generate certain exceptions. Sure they may be NotImplemented, but I want to tell that developer (who doesn't read documentation) that they should be considered.
Goal
The benefit of this exception checking is to enable more robust error handling. This would be accomplished by the consumer using the object, and the object creator.
Solution?
The only approach I can think of is T4 templates, but that isn't as complete of a solution as I would like. I'd love to see this implemented in the language itself.
You can't force a programmer to do anything except jump through hoops. For example, let's say you have some method called Frob that does something, and can throw FrobinatorException. You expect programmers to write:
try
{
var result = Frob(foo);
}
catch (FrobinatorException)
{
// handle exception here
}
But you find that they don't. So force them to by defining Frob like this:
public FrobResult Frob(FrobyThing foo, Action FrobinatorExceptionHandler);
And then programmers have to write something like:
var result = Frob(
foo,
() => { /* handle FrobinatorException here */; });
Programmers will grumble about having to do that and they'll end up writing this:
var StupidExceptionHandler = new Action(() => {});
var result = Frob(foo, StupidExceptionHandler);
And now you're worse off than you were because the exceptions are being swallowed, which hides bugs. It's better if the programmer just ignores the exception handling altogether. At least that way you know when an error occurs.
There's simply no way to force good exception handling. At least, not in C# as it currently exists. You can make it more convenient to handle exceptions, but doing so often makes it easier to hide exceptions by swallowing them.
If I'm reading your question correctly, it sounds like you're kind of looking for checked exceptions. There's an interesting article from much earlier in the development of C# that discusses this, actually.
From a design perspective, I don't really see how you could "force" the consumer of an interface to handle your exceptions. After all, how would you know it's being handled? Does the method which calls your interface need to wrap that call in a try/catch directly? Or would it be sufficient for the method which calls that method to do so? Or for a global exception handler for the application to do so? It should really be up to the consumer of the interface to determine how/when/where to handle exceptions.
The best approach you can take is to document the potential exceptions in the intellisense comments on the interface. But this brings up an interesting problem which you also mention (if I'm reading you correctly). The problem here is that the documentation is on the interface, not on the implementation. What if one or more implementations throw different exceptions than those which are expected by the interface?
In general, I think the balance to be reached here is still to document potential exceptions on the interface. The four examples you give sound like safe assumptions for an interface to make about its implementations. But that depends on what the interface method is accepting as arguments.
For example, if the whole concept of a "host" or a "username" is entirely encapsulated within the implementation (such as hitting a web service from within some kind of service interface, which could just as easily hit a database or some other source of record in other/later implementations) then exceptions about those pieces of data wouldn't make sense at the interface level. It would be better in that case to create an exception type like "DomainException" or "ImplementationException" or "DataRetrievalException" or something like that and just putting the internal implementation details inside of the exception.
To get back to the main point, however... From the perspective of your interfaces and your objects, you shouldn't be concerned with how exceptions are handled by consumers. All you should do is internally handle any exceptions that make sense to internally handle and throw exceptions that make sense to throw. Anything beyond that creates coupling between the consumer and the component.
Although I partly sympathies with your goal of better error handling, I feel that if you forced consumers of your code to handle exceptions correctly then your colleagues would murder you within 20 minutes of checking it in.
Due to C#'s lack of checked exception you're reduced to documenting your code so consumers know what to expect and under what conditions to expect them.
On a side note there is a great plugin for ReSharper called Exceptional that will identify places in your code where you have either not handled a possible exception, or not documented it so callers may do so instead.