I want to create an abstract class with an common exception handling pattern:
public abstract class Widget
{
public IFoo CreateFoo()
{
try
{
CreateFooUnsafe();
}
catch(Exception ex)
{
throw new WidgetException(ex, moreData, evenMoar);
}
}
protected abstract IFoo CreateFooUnsafe();
}
The intention is to have a standard exception handling pattern across all deriving objects. The abstract CreateFooUnsafe()
method should not be expected to contain any exception handling. Implementations would probably a single line of return new Foo(...)
Wha开发者_StackOverflow中文版t I want to know is whether there are any standard naming conventions associated with this pattern, particularly where exception-throwing code is expected?
The names above seem somewhat appropriate, but not entirely without smell.
This appears to be an example of the template method pattern.
Template method is a pattern which can be expressed in many object-oriented languages by using a public non-virtual function to implement some over-arching behavior, and a protected virtual (or abstract) method to supple the concrete behavior in subclasses.
In your example, you are using the template method to catch all exceptions bubbling out of the inner implementation and wrapping them in a custom exception type. One comment I would make about this specific practice, is that it only makes sense if you can add contextual information that would allow calling code to better handle the exception. Otherwise, it may be better to simply allow the source exceptions to propogate out.
The short answer is no.
There is no convention in the Template Pattern to designate what type and when an exception is thrown. That kind of information is included in some section of the documentation as per MSDN. Using C# and XML comments you can easily generate such documentation.
I'm under the impression that there might be a naming convention in place for the Template Pattern itself sans any referencing to exception handling. As I understand it, naming might look like this:
public abstract class Widget
{
public void PerformAction()
{
this.PerformActionImpl();
}
protected virtual void PerformActionImpl(){}
}
Where Impl is a shorthand for "Implementation". Personally I don't like that naming style so don't use it but I'm sure I've read it somewhere semi authoritative that that is "the" way to do it.
I wouldn't use any of this in your case however as what you really to seem to want to either Factory or AbstractFactory.
..
With regard to your exception query, it seems to me the code is a little inside out tho I disagree with some of the other comments depending on your circumstances.
Wrap and throw is an entirely valid exception handling technique.
The additional context provided by the type of the exception itself may well be enough to route the exception to an appropriate handler. i.e. you've transformed an Exception into a WidgetException which one would expect then has context within your application. So that might well be good enough.
Where you've done the wrapping I do however disagree with.
I would do the catching wrapping and throwing from within the subclass implementation of the virtual method as only that subclass is going to have enough understanding of what it's doing to know whether the Exception is indeed a WidgetException and therefore wrap and throw or something a little more hairy that should propagate.
The code as it stands is making some massive assumptions about the cause of the exception and in that sense rendering any use of a custom exception next to useless. i.e. everything is now a WidgetException.
So while I believe type alone could be enough to contextualise the exception I dont believe the code is making that decision in the right place. I understand the motivation behind the implementation you've chosen as it seems like a really tasty shortcut, "the myth of the all knowing base class" but the mere fact that you declared it as abstract should provide a significant clue that the class is intended to be ignorant by design.
So with respect to the crosscutting concern of exception handling I don't think you should looking so much for a pattern to make your life easier but rather a framework to abstract all the guff away.
For example the Enterprise Library.
There are several different patterns swimming about in the code above. Among other things, it looks a bit like the Abstract Factory pattern, i.e., you've got an abstract class which is implementing a factory method that returns concrete objects which implement a specific interface.
As to whether this sort of exception handling is a good idea or not -- I would tend to agree with the other folks, that I can't typically see a lot of value in this approach. I see what you're trying to do, namely, provide a single sort of exception to handle, much as the CreateFoo() returns a single interface (IFoo). But the only benefit I can think of to that approach is if you provide some interesting and relevant troubleshooting information in the WidgetException (e.g., some database or service connection strings, or some special processing logic around the stack trace). If you're just wrapping the original exception so that your clients can deal with a WidgetException, you haven't really accomplished much: they could just as easily deal with the base Exception type.
精彩评论