Best Practice way to indicate that a server request has failed? - c#

I am writing an API that connects to a service which either returns a simple "Success" message or one of over 100 different flavors of failure.
Originally I thought to write the method that sends a request to this service such that if it succeeded the method returns nothing, but if it fails for whatever reason, it throws an exception.
I didn't mind this design very much, but on the other hand just today I was reading Joshua Bloch's "How to Design a Good API and Why it Matters", where he says "Throw Exceptions to indicate Exceptional Conditions...Don't force client to use exceptions for control flow." (and "Conversely, don't fail silently.")
On the other-other hand, I noticed that the HttpWebRequest I am using seems to throw an exception when the request fails, rather than returning a Response containing a "500 Internal Server Error" message.
What is the best pattern for reporting errors in this case? If I throw an exception on every failed request, am I in for massive pain at some point in the future?
Edit: Thank you very kindly for the responses so far. Some elaboration:
it's a DLL that will be given to the clients to reference in their application.
an analogous example of the usage would be ChargeCreditCard(CreditCardInfo i) - obviously when the ChargeCreditCard() method fails it's a huge deal; I'm just not 100% sure whether I should stop the presses or pass that responsibility on to the client.
Edit the Second:
Basically I'm not entirely convinced which of these two methods to use:
try {
ChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);
} catch(ChargeFailException e) {
// client handles error depending on type of failure as specified by specific type of exception
}
or
var status = TryChargeCreditCard(cardNumber, expDate, hugeAmountOMoney);
if(!status.wasSuccessful) {
// client handles error depending on type of failure as specified in status
}
e.g. when a user tries to charge a credit card, is the card being declined really an exceptional circumstance? Am I going down too far in the rabbit hole by asking this question in the first place?

Here's a short list of things to consider. While not comprehensive, I believe these things can help you write better code. Bottom line: Don't necessarily perceive exception handling as evil. Instead, when writing them, ask yourself: How well do I really understand the problem I am solving? More often than not, this will help you become a better developer.
Will other developers be able to read this? Can it be reasonably understood by the average developer? Example: ServiceConnectionException vs. a confusing ServiceDisconnectedConnectionStatusException
In the case of throwing an exception, how exceptional is the circumstance? What does the caller have to do in order to implement the method?
Is this exception fatal? Can anything really be done with this exception if it is caught? Threads aborting, out of memory.. you can't do anything useful. Don't catch it.
Is the exception confusing? Let's say you have a method called Car GetCarFromBigString(string desc) that takes a string and returns a Car object. If the majority use-case for that method is to generate a Car object from that string, don't throw an exception when a Car couldn't be determined from the string. Instead, write a method like bool TryGetCarFromBigString(string desc, out Car).
Can this be easily prevented? Can I check something, let's say the size of an array or a variable being null?
For code readability's sake, let's potentially take a look at your context.
bool IsServiceAlive()
{
bool connected = false; //bool is always initialized to false, but for readability in this context
try
{
//Some check
Service.Connect();
connected = true;
}
catch (CouldNotConnectToSomeServiceException)
{
//Do what you need to do
}
return connected;
}
//or
void IsServiceAlive()
{
try
{
//Some check
Service.Connect();
}
catch (CouldNotConnectToSomeServiceException)
{
//Do what you need to do
throw;
}
}
static void Main(string[] args)
{
//sample 1
if (IsServiceAlive())
{
//do something
}
//sample 2
try
{
if (IsServiceAlive())
{
//do something
}
}
catch (CouldNotConnectToSomeServiceException)
{
//handle here
}
//sample 3
try
{
IsServiceAlive();
//work
}
catch (CouldNotConnectToSomeServiceException)
{
//handle here
}
}
You can see above, that catching the CouldNotConnectToSomeServiceException in sample 3 doesn't necessarily yield any better readability if the context is simply a binary test. However, both work. But is it really necessary? Is your program hosed if you can't connect? How critical is it really? These are all factors you will need to take in to account. It's hard to tell since we don't have access to all of your code.
Let's take a look at some other options that most likely lead to problems.
//how will the code look when you have to do 50 string comparisons? Not pretty or scalable.
public class ServiceConnectionStatus
{
public string Description { get; set; }
}
and
//how will your code look after adding 50 more of these?
public enum ServiceConnectionStatus
{
Success,
Failure,
LightningStormAtDataCenter,
UniverseExploded
}

I think you need to consider a few things in your design:
1) How will the API be accessed? If you are exposing it over web services, then throwing exceptions are probably not a good idea. If the API is in a DLL that you are providing for people to reference in their applications, then exceptions may be ok.
2) How much additional data needs to travel with the return value in order to make the failure response useful for the API consumer? If you need to provide usable information in your failure message (i.e. user id and login) as opposed to a string with that information embedded, then you could utilize either custom exceptions or an "ErrorEncountered" class that contains the error code and other usable information. If you just need to pass a code back, then an ENum indicating either success (0) or failure (any non-zero value) may be appropriate.
3) Forgot this in the original response: exceptions are expensive in the .Net framework. If your API will be called once in awhile, this doesn't need to factor in. However, if the API is called for every web page that is served in a high-traffic site, for example, you definitely do not want to be throwing exceptions to indicate a request failure.
So the short answer, is that it really does depend on the exact circumstances.

I really like the "Throw Exceptions to indicate Exceptional Conditions" idea. They must have that name for a reason.
In a regular application, you would use File.Exists() prior to a File.Open() to prevent an exception from being thrown. Expected errors as exceptions are hard to handle.
In a client-server environment though, you may want to prevent having to send two requests and create a FileOpenResponse class to send both status and data (such as a file handle, in this case).

Related

Try-Catch or Result object for making rest requests?

We have two versions of a wrapper method/class for making rest requests and converting them to objects in our project. This wrapper method handles various things like preventing us from going over limits among other things.
The first version uses a result object and never throws exceptions like so:
var result = JsonPost1<CustomObject>("/resource");
if(result.data != null)
{
CustomObject obj = result.data;
//Do logic with object here
}
else if(result.statusCode == HttpStatus.NotFound)
{
//Handle issue.
}
The second one uses a custom exception instead and returns the object directly:
try
{
CustomObject obj = JsonPost2("/resource");
//Do logic with object here
}
catch(CustomNotFoundException e)
{
// Handle issue
}
In at least 99% of requests the exception will not be hit. Which method is generally a better approach and why? Or is there a better approach than either of these?
IMHO - Exceptions should only be used for exceptional things.
Do not use exceptions for things you can check in code.
However, this does not mean that your wrapper class should handle any possible response from the service - Only the common ones.
Ideally, if your service has a unified API (meaning all possible responses share at least some of their properties (like Status and ErrorDescription), you would want to handle that in your wrapper class. Anything that is used only in a specific type of response should be handled after you get the data from the wrapper class.
Update
Microsoft's Best practices for exceptions page states:
The method to choose depends on how often you expect the event to occur.
Use exception handling if the event doesn't occur very often, that is, if the event is truly exceptional and indicates an error (such as an unexpected end-of-file). When you use exception handling, less code is executed in normal conditions.
Check for error conditions in code if the event happens routinely and could be considered part of normal execution. When you check for common error conditions, less code is executed because you avoid exceptions.
(emphasis mine)
This might be interpreted as the first option you've shown, if the fact that the data was not found is not considered an error (as the specific business logic dictates).
However, it might also be interpreted as the second option you've shown - since the catch clause will only be activated in 1% of the cases.
I still stand by my original answer, though. If the fact that the data was not found is not an error, it should be handled with a condition and not with a try...catch.

Catching all exceptions for detailed logging purposes - pros and cons

I'm in the middle of writing a saving and loading system that saves game objects to a JSON compatible format and loads them back. Saving objects is fine and fairly fool-proof. However, I'm in the process of trying to make the loading process more bullet-proof and easier for me to pin-point errors. Obviously as I'm loading data from a JSON file, everything is being converted from strings, with the potential for all kinds of user error.
Each objects loading method contains something similar to this ---
public void Load()
{
try
{
// Deserialize..
// Potential for all kinds of exceptions, invalid casts, missing info, etc..
// For eg:
bool active = data.GetField("active").Value<bool>();
// GetField() throws an exception if the field doesn't exist.
// Value<T>() throws an exception if it's an invalid cast, etc.
}
catch(Exception e)
{
// ..and those exceptions get caught and logged here.
Logger.LogError(e.ToString, this);
}
}
One of the benefits of catching all the exceptions in the objects Load method is that when 'LogError()' is called with the object as a parameter like shown, it will highlight the offending object in the IDE hierarchy that threw the error (whichever one it may be) making it very quick to find the object with the error and debug it's script or saved data.
Is this an appropriate usage of throwing and catching exceptions, or is there a better design pattern I should be implementing?
Thanks for your time,
Sam
There are always a lot of different but close opinions about catching the exceptions, but for your task the given approach is simple and viable. The only thing I'd recommend for you to do is to allow the exception to bubble up:
catch(Exception e)
{
// ..and those exceptions get caught and logged here.
Logger.LogError(e.ToString, this);
throw;
}
Logging is a good idea, but what should your program do if the loading fails? Just log it out and continue? It can be the case, but this load method looks like important and integral part of your program. It does not look like some background work-that-may-fail-or-work-I-don't-care. Well, its your program and I don't know the requirements or context - just an opinion of mine.
The main principle you should base your exception handling on is: to catch exception only when and where you can do something with them (retry, get some relevant current data in the method...), or otherwise catch them
as high in the call hierarchy as possible (in your main loop or global exception handler - the higher the better, it means less exception handling for you to duplicate). And if you can't do anything with exception that would guarantee the consistency of your program state - don't catch it.
Ideally all classes should be resilient to failure - if they fail, they either fail and don't do anything afterwards or restore their state to normal. And the most ideal solution is if they rolled back any action's side effects in case of exceptions - transaction-like behaviour. But in real life it is a difficult goal to achieve.
Also, if you don't like similar try-catch constructs for logging everywhere in your code (they are important , but they aren't doing any real job - their presence isn't necessary for the understanding of the main workflow), you may try some of the Aspect Oriented Programming technologies.
Your question still missing many basic things like what kind of object "data" is, is it a string , class or any other type.
Well catching exception is never good for performance as long as your code handle all possible exceptions that might occur.
There can still be a scenario where exception is thrown.
I would suggest to check for field instead of directly calling field with that name, e,g,
bool active = data.HasField("active") ? data.GetField("active").Value<bool>() : false;
Also, In catch as common scenario better to pass exception object rather than e.Tostring()
something like :
Logger.LogError(e, this);
To conclude it really depends on application to applications or rather requirement to requirements.
In web Application, I usually create HttpModule for logging exception so that I dont have to write catch block everywhere in my code.
public class ExceptionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.Error += new EventHandler(OnError);
}
private void OnError(object sender, EventArgs e)
{
//write logging exception logic.
}
}

How to force usage of Try/Catch around specific methods

I am creating a "Common" library to be used as reference in various solution projects by other team members. The methods are typically void functions with no actual returned data.
I am looking for a why to force the usage of these methods within a Try...Catch block by others. I need to make sure errors are properly handled. I though about relying on a Boolean return type but that will not allow me to return the error message as well, so my only option is throwing an Exception.
If proper forcing is not possible, how can I make an attribute that pops-up when compiling to warn the developer about the Try/Catch requirement? (sort of the Obsolete attribute).
Any other better approaches?
EDIT:
Here is my full scenario:
I have a code method calling a web service to update a value remotely. The update is quite crucial. The method it self works fine but what if the web service is not reachable? The call does not return any value.
Placing something inside a try/catch block does not make it "properly handled" - in fact, in the vast majority of cases, the correct way of handling an exception is to let it bubble up to the next level. Caveat: try/finally is much more common, to allow for resource clean-up, but even more common than that is using.
You cannot enforce "and you must use it correctly" on code; that is implicit in any API, and you will just be causing irritation and annoyance, and forcing people into inappropriate and unhelpful coding styles, while giving you a completely artificial and incorrect sense of the code being correct.
If you want to be sure that the code functions correctly: test it.
There are no attributes that you can use for this scenario. You can probably create an FxCop rule or similar, but for the reasons above: I do not recommend it.
I wouldn't actually do this, but as a fun solution to the stated problem you could build your own Exception type: a SuccessException. Then, you throw this exception at the end of your method to indicate success. This makes the method pretty much unusable without some form of try/catch. But, again: don't do this.
You could return a custom result class:
public class Result
{
public bool Okay { get; set; }
public string Error { get; set; }
}
Then:
var result = AttemptSomething();
if (!result.Okay)
{
Console.WriteLine(result.Error);
}
Or maybe return string:
var error = AttemptSomething();
if (!String.IsNullOrEmpty(error))
{
Console.WriteLine(error);
}
Or have the error as an out:
string error;
if (!AttemptSomething(out error))
{
Console.WriteLine(error);
}
Or return Exception but don't throw.

Is this good C# style?

Consider the following method signature:
public static bool TryGetPolls(out List<Poll> polls, out string errorMessage)
This method performs the following:
accesses the database to generate a list of Poll objects.
returns true if it was success and errorMessage will be an empty string
returns false if it was not successful and errorMessage will contain an exception message.
Is this good style?
Update:
Lets say i do use the following method signature:
public static List<Poll> GetPolls()
and in that method, it doesn't catch any exceptions (so i depend the caller to catch exceptions). How do i dispose and close all the objects that is in the scope of that method? As soon as an exception is thrown, the code that closes and disposes objects in the method is no longer reachable.
That method is trying to do three different things:
Retrieve and return a list of polls
Return a boolean value indicating success
Return an error message
That's pretty messy from a design standpoint.
A better approach would be to declare simply:
public static List<Poll> GetPolls()
Then let this method throw an Exception if anything goes wrong.
This is definitely not an idiomatic way of writing C#, which would also mean that it probably isn't a good style either.
When you have a TryGetPolls method then it means you want the results if the operation succeeds, and if it doesn't then you don't care why it doesn't succeed.
When you have simply a GetPolls method then it means you always want the results, and if it doesn't succeed then you want to know why in the form of an Exception.
Mixing the two is somewhere in between, which will be unusual for most people. So I would say either don't return the error message, or throw an Exception on failure, but don't use this odd hybrid approach.
So your method signatures should probably be either:
IList<Poll> GetPolls();
or
bool TryGetPolls(out IList<Poll> polls);
(Note that I'm returning an IList<Poll> rather than a List<Poll> in either case too, as it's also good practice to program to an abstraction rather than an implementation.)
I believe
public static bool TryGetPolls(out List<Poll> polls)
would be more appropriate. If the method is a TryGet then my initial assumption would be there is reason to expect it to fail, and onus is on the caller to determine what to do next. If they caller is not handling the error, or wants error information, I would expect them to call a corresponding Get method.
As a general rule, I would say no.
The reason I say no is actually not because you're performing a TryGetX and returning a bool with an out parameter. I think it's bad style because you're also returning an error string.
The Try should only ignore one specific, commonly-encountered error. Other problems may still throw an exception with the appropriate exception message. Remember that the goal of a Try method like this is to avoid the overhead of a thrown exception when you expect a particular, single sort of failure to happen more frequently than not.
Instead, what you're looking for is a pair of methods:
public static bool TryGetPolls( out List<Poll> polls );
public static List<Poll> GetPolls();
This way the user can do what's appropriate and GetPolls can be implemented in terms of TryGetPolls. I'm assuming that your staticness makes sense in context.
Consider returning:
an empty collection
null
Multiple out parameters, to me, is a code smell. The method should do ONE THING only.
Consider raising and handling error messages with:
throw new Exception("Something bad happened");
//OR
throw new SomethingBadHappenedException();
No, from my point of view this is very bad style. I would write it like this:
public static List<Poll> GetPolls();
If the call fails, throw an exception and put the error message in the exception. That's what exceptions are for and your code will become much cleaner, more readable and easier to maintain.
Not really - I can see a number of problems with this.
First of all, the method sounds like you'd normally expect it to succeed; errors (cannot connect to database, cannot access the polls table etc) would be rare. In this case, it is much more reasonable to use exceptions to report errors. The Try... pattern is for cases where you often expect the call to "fail" - e.g. when parsing a string to an integer, chances are good that the string is user input that may be invalid, so you need to have a fast way to handle this - hence TryParse. This isn't the case here.
Second, you report errors as a bool value indicating presence or absence of error, and a string message. How would the caller distinguish between various errors then? He certainly can't match on error message text - that is an implementation detail that is subject to change, and can be localized. And there might be a world of difference between something like "Cannot connect to database" (maybe just open the database connection settings dialog in this case and let the user edit it?) and "Connected to database, but it says 'Access Denied'". Your API gives no good way to distinguish between those.
To sum it up: use exceptions rather than bool + out string to report messages. Once you do it, you can just use List<Poll> as a return value, with no need for out argument. And, of course, rename the method to GetPolls, since Try... is reserved for bool+out pattern.
The guidelines say to try to avoid ref and out parameters if they are not absolutely required, because they make the API harder to use (no more chaining of methods, the developer has to declare all the variables before calling the method)
Also returning error codes or messages is not a best practice, the best practice is to use exceptions and exception handling for error reporting, else errors become to easy to ignore and there's more work passing the error info around, while at the same time losing valuable information like stacktrace or inner exceptions.
A better way to declare the method is like this.
public static List<Poll> GetPolls() ...
and for error reporting use exception handling
try
{
var pols = GetPols();
...
} catch (DbException ex) {
... // handle exception providing info to the user or logging it.
}
It depends on what the error message is. For instance, if processing couldn't continue because the database connection wasn't available, etc., then you should throw an exception as other people have mentioned.
However, it may be that you just want to return "meta" information about the attempt, in which case you just need a way to return more than one piece of information from a single method call. In that case, I suggest making a PollResponse class that contains two properties: List < Poll > Polls, and string ErrorMessage. Then have your method return a PollResponse object:
class PollResponse
{
public List<Poll> Polls { get; }
public string MetaInformation { get; }
}
Depends on if an error is a common occurance or if it us truly an exception.
If errors are gunuinely rare and bad then you might want to consider having the method just return the list of polls and throw an exception if an error occurs.
If an error is something that is realtively common part of normal operations, as like an error coverting a string to an integer in the int.TryParse method, the method you created would be more appropriate.
I'm guessing the former is probably the best case for you.
It depends on how frequently the method will fail. In general, errors in .Net should be communicated with an Exception. The case where that rule doesn't hold is when the error condidition is frequent, and the performance impact of throwing and exception is too high.
For Database type work I think an Exception is best.
I'd restate it like this.
public static List<Poll> GetPolls()
{
...
}
It should probably be throwing an exception (the errorMessage) if it fails to retrieve the polls, plus this allows for method chaining which is less cumbersome than dealing with out parameters.
If you run FxCop, you'll want to change List to IList to keep it happy.
I think its fine. I would prefer though:
enum FailureReasons {}
public static IEnumerable<Poll> TryGetPolls(out FailureReasons reason)
So the error strings don't live in the data-access code...
C# Methods should really only do one thing. You're trying to do three things with that method. I would do as others have suggested and throw an exception if there is an error. Another option would be to create extension methods for your List object.
e.g. in a public static class:
public static List<Poll> Fill( this List<Poll> polls) {
// code to retrieve polls
}
Then, to call this, you would do something like:
List<Poll> polls = new List<Poll>().Fill();
if(polls != null)
{
// no errors occur
}
edit: i just made this up. you may or may not need the new operator in List<Poll>().Fill()
Please state your assumptions, constraints, desires/goals, and reasoning; we're having to guess and/or read your mind to know what your intentions are.
assuming that you want your function to
create the polls list object
suppress all exceptions
indicate success with a boolean
and provide an optional error message on failure
then the above signature is fine (though swallowing all possible exceptions is not a good practice).
As a general coding style, it has some potential problems, as others have mentioned.
There is also this pattern, as seen in many Win32 functions.
public static bool GetPolls(out List<Poll> polls)
if(!PollStuff.GetPolls(out myPolls))
string errorMessage = PollStuff.GetLastError();
But IMO it's horrible.
I would go for something exception based unless this method has to run 65times per second in a 3d game physics engine or someting.
Did I miss something here? The question asker seems to want to know how to clean up resources if the method fails.
public static IList<Poll> GetPolls()
{
try
{
}
finally
{
// check that the connection happened before exception was thrown
// dispose if necessary
// the exception will still be presented to the caller
// and the program has been set back into a stable state
}
}
On a design side note, I'd consider pushing this method into a repository class so you have some sort of context with which to understand the method. The entire application, presumably, is not responsible for storing and getting Polls: that should be the responsibility of a data store.

Using events rather than exceptions to implement error handling

I'm working on some code that uses a pattern in its business and data tiers that uses events to signal errors e.g.
resource = AllocateLotsOfMemory();
if (SomeCondition())
{
OnOddError(new OddErrorEventArgs(resource.StatusProperty));
resource.FreeLotsOfMemory();
return;
}
This looked superficially rather odd, especially as the code that calls this needs to hook into the events (there are four or five different ones!).
The developer tells me that this way they can refer to the properties of the allocated resource in the error handling code, and that responsibility for cleaning up after the error is kept by this tier.
Which makes some kind of sense.
The alternative might be something like
resource = AllocateLotsOfMemory();
if (SomeCondition())
{
BigObject temporary = resource.StatusProperty;
resource.FreeLotsOfMemory();
throw new OddException(temporary);
}
My questions are:
As this "BigObject" is freed when the exception object is released, do we need this pattern?
Has anyone else experience of this pattern? If so, what pitfalls did you find? What advantages are there?
Thanks!
It seems odd to me too. There are a few advantages - such as allowing multiple "handlers" but the semantics are significantly different to normal error handling. In particular, the fact that it doesn't automatically get propagated up the stack concerns me - unless the error handlers themselves throw an exception, the logic is going to keep going as if everything was still okay when it should probably be aborting the current operation.
Another way of thinking about this: suppose the method is meant to return a value, but you've detected an error early. What value do you return? Exceptions communicate the fact that there is no appropriate value to return...
This looks really odd to me, firstly IDisposable is your friend, use it.
If you are dealing with errors and exceptional situations you should be using exceptions, not events, as its much simpler to grasp, debug and code.
So it should be
using(var resource = AllocateLotsOfMemory())
{
if(something_bad_happened)
{
throw new SomeThingBadException();
}
}
If you think in terms of "Errors" and "Warnings", I've had lots of luck when reserving events for the "Warning" category and Exceptions for the "Errors" category.
The rationale here is that events are optional. No one is holding a gun to your head forcing you to handle them. That's probably okay for warnings, but when you have genuine errors you want to make sure they are taken a little more seriously. Exceptions must be handled, or they'll bubble up and create a nasty message for the user.
With regards to your Big Object question: you definitely don't be passing big objects around, but that doesn't mean you can't pass references to big objects around. There's a lot of power in the ability to do that.
As an addendum, there's nothing stopping from from raising an event in addition to the exception, but again: if you have a genuine error you want something to force the client developer to handle it.
Take a look at this post by Udi Dahan. Its an elegant approach for dispatching domain events. The previous poster is correct in saying that you should not be using an event mechanism to recover from fatal errors, but it is a very useful pattern for notification in loosely coupled systems:
public class DomainEventStorage<ActionType>
{
public List<ActionType> Actions
{
get
{
var k = string.Format("Domain.Event.DomainEvent.{0}.{1}",
GetType().Name,
GetType().GetGenericArguments()[0]);
if (Local.Data[k] == null)
Local.Data[k] = new List<ActionType>();
return (List<ActionType>) Local.Data[k];
}
}
public IDisposable Register(ActionType callback)
{
Actions.Add(callback);
return new DomainEventRegistrationRemover(() => Actions.Remove(callback)
);
}
}
public class DomainEvent<T1> : IDomainEvent where T1 : class
{
private readonly DomainEventStorage<Action<T1>> _impl = new DomainEventStorage<Action<T1>>();
internal List<Action<T1>> Actions { get { return _impl.Actions; } }
public IDisposable Register(Action<T1> callback)
{
return _impl.Register(callback);
}
public void Raise(T1 args)
{
foreach (var action in Actions)
{
action.Invoke(args);
}
}
}
And to consume:
var fail = false;
using(var ev = DomainErrors.SomethingHappened.Register(c => fail = true)
{
//Do something with your domain here
}
1) is it needed? no pattern is absolutely necessary
2) Windows Workflow Foundation does this with all the results from the Workflow Instances running inside the hosted runtime. Just remember that exceptions can happen when trying to raise that event, and you might want to do your cleanup code on a Dispose or a finally block depending on the situation to ensure it runs.
To be honest, events signaling errors strikes me as scary.
There's a disagreement between camps around returning status codes and throwing exceptions. To simplify (greatly) : The status code camp says that throwing exceptions places detecting and handling the error too far from the code causing the error. The exception throwing cap says that users forget to check status codes and exceptions enforce error handling.
Errors as events seems like the worst of both approaches. The error cleanup is completely separate from the code causing the error, and notification of error is completely voluntary. Ouch.
To me, if the method did not fulfill it's implicit or explicit contract (it didn't do what it was supposed to do), an exception is the apropriate response. Throwing the information you need in the exception seems reasonable in this case.
The first snippet should probably be
resource = AllocateLotsOfMemory();
if (SomeCondition())
{
try
{
OnOddError(new OddErrorEventArgs(resource.StatusProperty));
return;
}
finally
{
resource.FreeLotsOfMemory();
}
}
otherwise you won't free your resources when the event handler throws an exception.
As Mike Brown said, the second snippet also has a problem if resource.FreeLotsOfMemory() messes with the contents of resource.StatusProperty instead of setting it to null.
We have a base Error object and ErrorEvent that we use with the command pattern in our framework to handle non-critical errors (e.g. validation errors). Like exceptions, people can listen for the base ErrorEvent or a more specific ErrorEvent.
Also there's a significant difference between your two snippets.
if resource.FreeLotsOfMemory() clears out the StatusProperty value rather than just setting it to null, your temporary variable will be holding an invalid object when OddException is created and thrown.
The rule of thumb is that Exceptions should only be thrown in non-recoverable situations. I really wish C# supported a Throws clause that's the only thing I really miss from Java.
Another major problem with this approach are concurrency concerns.
With traditional error handling, locks will be released as control moves up the call stack to the error handler in a controlled manner. In this scheme, all locks will still be held when the event is invoked. Any blocking that occurs within the error handler (and you might expect some if there's logging) would be a potential source of deadlocks.

Categories

Resources