When should I handle exceptions and when should they be thrown? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
When programming, I find myself having a hard time thinking about how my program should work, when an exception could be thrown.
Take the following example:
public void AddComponent(IEntityComponent component)
{
if (component == null)
{
// Should I throw an ArgumentNullException or should I just return?
}
if (ContainsComponentOfType(component.GetType()))
{
// Should I return here? Or should I throw an ArgumentException?
}
// Finally, we know we can add the component to the entity
components.Add(component);
}
public bool ContainsComponentOfType(Type componentType)
{
if (componentType == null)
{
// Should I throw an exception here? Should I return false?
}
return components.Any(c => c.GetType() == componentType);
}
Note that the above code will be used by people creating a game with my engine.

The policy can vary from zero tolerance (throwing exceptions at any point where they can be thrown) to lenient (where we forgive caller as far as we can do).
The common practice is DoAction (AddComponent in your case) be strict and TryDoAction (TryAddComponent) be lenient.
Zero tolerance version:
// Strict: we are quite sure in the arguments;
// that's why it's an exceptional case (error in the code!) if arguments are invalid
// and we fail to add
public void AddComponent(IEntityComponent component) {
// Contract: here we validate the input arguments
// Since we sure in them we apply zero tolerance policy:
// if contract is't met throw corresponding exception
// we want not null component
if (component == null)
throw new ArgumentException(nameof(component));
// which contains at least one item of the required type
if (ContainsComponentOfType(component.GetType()))
throw new ArgumentException("Component must contain...", nameof(component));
// Finally, we know we can add the component to the entity
components.Add(component);
}
Lenient implementation
// Lenient: we have arguments from the (unknown) source in which we are not sure
// we want just to try adding (and get true / false) if we succeed or not
public bool TryAddComponent(IEntityComponent component) {
// Contract: we validate the input arguments from unknown source
// if validation fails we should not throw any exception (it's not an
// exceptional case to get incorrect data from unreliable source) but
// let the caller know that we don't succeed
// We can't add if component is null
if (component == null)
return false;
// We have nothing to add if component doesn't contain required items
if (ContainsComponentOfType(component.GetType()))
return false;
// Finally, we know we can add the component to the entity
components.Add(component);
return true;
}
// Do we really want to expose it?
// ContainsComponentOfType is an implementation detail which we keep private
private bool ContainsComponentOfType(Type componentType) {
// Since it's a private method we can omit the check
return components.Any(c => c.GetType() == componentType);
}
Usage: since you are building an engine both cases (strict and lenient) can appear
MyClass loader = new MyClass();
...
// Cloud Database must not be corrupted; if it is, we want to know it immediatly
loader.AddComponent(componentFromCloud);
...
// Local file can contain any data: it can be corrupted, user can try cheating etc.
if (!loader.TryAddComponent(componentFromLocalFile)) {
// Let user know that saved data failed to be loaded
}

It depends on what you developing and how should it be used and who use it ...
In your case which is developing game engine the best practice is to throw exceptions and forward theme to end-user(developer who use your engine to develop the game) and let the developer handle the exceptions and do proper work that he/she want.
Always try to check all possible exceptions and give useful information about the exception and thew ways to fix the mistake that raise the exception. general exception handling is for unknown and unwanted exceptions that you don't know anything about theme.

It depends on what an error is to you and what an exception is, just because your code detects that something is not as it should and it can't continue you should throw an exception.
An exception, as its name implies, happens when something exceptional and not controlled or controllable by your code happens (i.e. network connection goes down, failed to save a file because other program has it locked, a null reference you have not controlled, etc.).
Throwing exceptions tends to be costly for a computer, as it has to include a stack of what has happened, where and information on the state of the call stack, just because of that, you want to avoid exceptions as much as possible.
As it is expected that your code might not be able to run from start to finish in a set of controled conditions you take into consideration, it is a good practice to control the flow and return values that indicate that the process has not run as it was expected to, but in this case, due to some expected error which you have controlled has happened and inform that error right away.
To sum up:
Avoid throwing exceptions for flow control of your methods, as they are costly and cause innecessary slowness on systems that consume your program.
Only throw the exceptions you have not covered in your code or that you can't control (i.e another program the user is running grabs a file you want to use and you did not consider this possibility).
Control as much error as you see necessary and inform the user with sensible information on what has happened in order for him to be able to solve it on his own (if he's capable to) so he can continue using and consuming your application.

Related

When to use exception or when to use message? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am wondering what is the best way to warn about a data that a user has to provide is missing or wrong.
Exceptions, for me, are when there are something exceptional that I can't control, for example, if i try to write a file, there is no permissions or the hard drive is full. If I am querying database, the database is down or the LAN connections doesn't work... etc.
But if it is because a user doesn't provide a needed information or it is incorrect, this is something that I have control over it, so from some point of view, it is not an exception, because it depends on me. But if I don't use exceptions, to warn the user, I have to show a dialog, so the code it is much more complex if I have considerate all the possibilities.
For example, with exceptions I could have this code:
try
{
if(esData1Correct() == false) throw new Exception("Data1 incorrect");
if(esData2Correct() == false) throw new Exception("Data2 incorrect");
if(esData3Correct() == false) throw new Exception("Data3 incorrect");
// All is correct, I continue with the code.
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
However, if I want to use dialogs, the code that I should use, or the code that I think I would have to use is something like that:
if(esData1Correct() == false)
{
MessageBox.Show("Data1 is incorrect.");
}
else if(esData2Correct() == false)
{
MessageBox.Show("Data2 is incorrect.")
}
else if(esData3Correct() == false)
{
MessageBox.Show("Data3 is incorrect.")
}
else
{
// All is correct, so I can continue with my code.
}
So which code is more correct, to use exceptions or messages to warn the user the information is not correct? Are there another better options?
Thanks.
So which code is more correct, to use exceptions or messsages to warn
the user the information is not correct? Are there another better
options?
Neither is more correct and they both show the message to the user with or without the exceptions; mission accomplished. Indeed, you wouldn't warn the user with an exception per say so it's transparent to them anyway unless you plan to dump the stack trace to the UI (don't!!). There are things to consider when using exceptions and you certainly don't want to use them everywhere for everything but it's not wrong to use them for validation failures. Read on for more.
Exceptions are meant for exceptional conditions but what constitutes an exceptional condition varies. Linq's First, for example, will throw an exception if the source or predicate is null, the source is empty, or there's no element that matches the predicate. They could have just returned null but they chose to instead push the responsibility onto the caller to get it right. To me, that's a reasonable use of exceptions where it wasn't exactly necessary; a collection not containing an element that matches a predicate happens all the time so it's not exactly exceptional. And it's not uncommon to see ArgumentExceptions and ArgumentNullExceptions used in similar cases as yours; that's probably how I'd do it absent a more sophisticated approach.
But, first thing's first. I know this is an example but there are some pain-points that need to be addressed before worrying about which approach is more appropriate.
The following is objectively stinky:
try
{
if(esData1Correct() == false) throw new Exception("Data1 incorrect");
if(esData2Correct() == false) throw new Exception("Data2 incorrect");
if(esData3Correct() == false) throw new Exception("Data3 incorrect");
//All is corerct, I continue with the code.
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
Here, the code is using exceptions as control flow. You know something is wrong and can handle it at that point but instead throw and catch an exception to show the message; not good.
Also, don't throw or catch System.Exception. Exceptions, if used, should be specific enough to do something meaningful about it based on the context. Again, it's a small example but this sort of thing is everywhere in naive code.
Having said that, the first example would change and would not catch the ArgumentException if thrown. Let the caller catch the errors as they're the ones creating the exceptional condition; in other words, pull the validation out. The caller should also worry about what to do about it. As it is now, the validation code is tightly coupled to a message box which makes it difficult to reuse.
public Foo Bar(...)
{
// A better way may be to validate them all and return a message
// that aggregates all incorrect data back...
if(!esData1Correct()) throw new ArgumentException("Data1 incorrect");
if(!esData2Correct()) throw new ArgumentException("Data2 incorrect");
if(!esData3Correct()) throw new ArgumentException("Data3 incorrect");
// more ?
}
Given we're willing to remove the coupling to the message box, the second example doesn't really do what we want so instead create a ValidationResult class that can help you build a meaningful message to the user.
I prefer second option, since it uses less resources, and is less complex.
Exception throwing should be used when you want to delegate exception handling to client-module which triggers your code and thus knows more about context in which your code is executed. There is not much sense in handling exception inside same method which throws it. You are right about that - in this example you know everything about what went wrong, and there is no need for exceptions, you just detect error and notify user about it, and that's all.
The rule is generally: Exceptions should be exceptional.
A few examples:
var username = input.Text;
if (string.IsEmptyOrNull())
{
// Give the user a chance to correct the input, this should not be an exception!
}
However, in an API, you might have a method that accepts a user object parameter:
var user = db.usernames.where(x => x.Id == user.Id).FirstOrDefault();
If the input is supposedly already validated, but suddenly can't be found this is an exception. Something really weird happened! But if your query is an attempt to validate it should be treated as a valid query with no results:
var user = db.usernames.Where(x => x.username == user.username).FirstOrDefault();
if (user == null)
{
// return useful error, this is not an exception
}
It depends, mostly you handle the common conditions that are likely to happen (such as database connection in your example) by using simple if statement. Other situations that might occur and you think your code won't cover all of them, use Exceptions, this way you ensure that you catch the error trace.
Some other cases might need both if and Exception.
example :
try
{
if(!string.IsNullOrEmpty(someString))
{
someClass.Run(someString);
}
}
catch(Exception ex)
{
// Log exception
}
as the example above (sorry couldn't think of a real-world case). We used try/catch to catch any unhandled errors, while in the same time, we already validating some known conditions in the try block.
So, it depends on which part you're dealing with in your code. But in all cases, you're supposed to try handling all other errors. You have always to keep avoiding exceptions in your code as much as possible.
You're the judge on your code, choose whatever you see fits best your code.
Here is A good reference for Best practices for exceptions

What's the best practice to structure exception messages? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
When something goes wrong in your program, you can throw an exception in your code with a message that describes a problem. Typical example:
throw new Exception("Houston we have a problem");
Is it a good practice to pass a hardcoded string into an exception constructor? Maybe I should hold all of exception messages in a one place. Please tell me what's the best practice to solve a problem of exception message structuring.
As Tim mentioned in the comments already localization can be a problem if the messages are shown to users.
What my approach on this topic is, and what I really like to suggest is the following.
Try to make it generic.
Makea a constants class holding your exception Messages with meaningfull constants names like this:
public static const String IN_VARIABLE_MISSING = "An expected value is missing. Please try again";
This will give you the ability to actually re-use the exception wherever it is needed. ( Also you only need to edit it at one place and have it updated everywhere ) You can build a wrapper which will handle the localization. But there are so many options for that topic, that I will not elaborate too much.
So you then can throw an exception like this:
throw new Exception(IN_VARIABLE_MISSING);
If this is software which will be used commercial I would also recommend to write an own Exception which extends the standard Exception.
Why?
You can create an exception that will take your message and an number for example and will automatically build an unique key for you like this:
IN-MODULE-NUMBER-IDENTIFICATION
You see where that could be handy? Excactly in localization and in faster finding of where it happened and why it happened.
You can modify it to write IN at the beginning for Internal errors. VA for validation errors. Then the class/project where it happened and then a number or whatever you want.
This system will also give you the ability to use another string for that key depending on the locale the user is using.
TL;DR Make it reusable!
Is it a good practice to pass a hardcoded string into an exception constructor?
Yes and No.
No in the sense that this code:
throw new Exception("Houston we have a problem");
is much harder for the caller to deal with. That's because what the exception means is identified only by the text of the message; therefore a caller wanting to catch exceptions from your code (for example, so as not to crash but continue running if possible) has to make string comparisons to figure out what the problem was.
e.g.
try
{
someService.DoSomething(sessionId)
}
catch(Exception ex)
{
if (ex.Message.Contains("Houston"))
{
//this indicates that someService couldn't connect to the database
}
else if(ex.Message.Contains("is on fire"))
{
//someService detected that the network is exploded
}
else{
//we can only handle the two previous cases, all else is passed on}
throw;
}
As you can see this gets messy fast, and if someone changes the text....
Now this code, on the other hand:
throw new SomethingSpecificWentWrongException(sessionId);
where SomethingSpecificWentWrongException might look like this:
public class SomethingSpecificWentWrongException: Exception
{
public int SessionId {get;protected set;}
public SomethingSpecificWentWrongException(int sessionId):
base($"Something specific went horribly wrong with session {sessionId}")
{
SessionId=sessionId;
}
}
can easily be handled by the caller:
try
{
someService.DoSomething(sessionId)
}
catch(SomethingSpecificWentWrongException ex)
{
//do whatever it is you do to recover from this
}
catch(SomethingElseSpecificWentWrongException wex)
{
//recover from this
}
else
{
throw;
}
You'll notice that there is a hard-coded-ish string here but it's owned by the custom exception class itself, not by the code that decides to throw the exception; this makes a big difference because it means you can guarantee that wherever this exception is used the message is predictable (in terms of logging, etc).
So not only is it easier to reason about, it's a lot more maintainable than hard-coding strings provided by the throwing code.

C# - How to structure error handling in code properly [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I am fairly new to programming and I want to know what is the proper way to structure your error handling. I have searched the internet but I have failed to find something solid about the structure of ALL your try/catch/finally statements, and how they interact with each other.
I want to present my idea of how I think I should structure my error handling in code and I would like to invite everyone check if this is correct. A big bonus would be to back it up with some other research, a common practice of some sort.
So my way of doing this would be to put try statements pretty much everywhere! (I hope I haven't raged everyone by saying this). PS - I also understand about catching different types of exceptions, I am only catching of type 'Exception' just for explanation purposes.
So for example:
I start on Main in a normal console application and then I create an
instance of A.
I then call a member function on it called AMethod1 (a.AMethod1).
A.AMethod1 creates an instance of class B and then calls BMethod1
(b.BMethod1).
This is how I would go about error handling it:
public class Program
{
static void Main (string[] args)
{
//I do not place simple code like below inside the try statement,
//because it is unnecessary and will slow the process down.
//Is this correct?
const int importantNumber = 45;
string name;
IRepositoryFactory repoFactory;
A a;
//And then I put code in 'try' where I feel it may go wrong.
try
{
a = new A();
a.AMethod1();
//Some other code
}
catch (Exception ex)
{
HandleError(ex);
}
}
}
// End of scope of Program! The functions below belong to their relative
// classes.
public void AMethod1()
{
try
{
B b = new B();
b.BMethod1();
}
catch (Exception ex)
{
//Preserving the original exception and giving more detailed feedback.
//Is this correct?
//Alternative - you still could do a normal 'throw' like in BMethod1.
throw new Exception("Something failed", ex);
}
}
public void BMethod1()
{
try
{
//some code
}
catch (Exception ex)
{
throw; //So I don't lose stack trace - Is this correct?
}
}
In summary:
I put all code in try statements (except declarations like shown in
above code)
On the client level (at the start of the call stack) I
catch the error and handle it.
Going down the call stack, I just
throw the Exception so I don't break the stack information.
I would really appreciate some resources that explains how programmers are meant to structure their error handling. Please don't forget to read the comments within the code please.
Here are some good rules of thumb:
If you are going to log the error at the level in question, use exception handling
If there is some way to solve the exception, use exception handling
Otherwise, don't add any exception handling at that level
The exception to the rules above is the UI should ALWAYS (okay, maybe not always, but I can't think of an exception to this rule right off hand) have exception handling.
In general, if you are throwing the same error, as you have in your code, it is a sign you should not handle the exception. End of story.
NOTE: When I say "at that level", I mean in the individual class or method. Unless the exception handling is adding value, don't include it. It always adds value at the user interface level, as a user does not have to see your dirty laundry, a message saying "oops, laundry day" is enough.
In my personal experience most of the exceptions are related to null object reference. I tend to follow null object pattern to avoid lots of check for null values. And also while doing a value conversion I always use tryparse so that i dont stand a chance of null issues. all in all this subject could be discussed from many perspective. if you could be a bit more specific it will be easy to answer.
stackoverflow really isn't an opinion site. It's geared heavily towards specific answers to specific questions.
But you should know that try...catch does have some overhead associated with it. Putting it "everywhere" will hurt the performance of your code.
Just use it to wrap code that is subject to unexpected errors, such as writing to disk, for example.
Also note that the "correct" way depends on what you are doing with those errors. Are you logging them, reporting them to the user, propagating them to the caller? It just depends.

Correct way to document bubbled exceptions in C#? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Below is a simplified example of a setup I have. My issue is an exception is thrown at a low level which will then bubble up. However, classes at a higher level do not know what horrors await them when they use the lower level class functions. By this I mean developers will come along and use Class3.DoWork3() without any exception handling for the dreaded 'MyCustomException'.
Am I approaching this all wrong? I don't want to catch and throw the same exception multiple times (I have no need to do any kind of clean up for example in Class2).
public class Class1
{
<exception cref="MyCustomException">description</exception>
public void DoWork1()
{
throw new MyCustomException("I have failed you class1.");
}
}
public class Class2
{
public void DoWork2()
{
var classOne = new Class1();
// Here I can see that DoWork1() will throw a 'MyCustomException'
classOne.DoWork1();
}
}
public class Class3
{
public void DoWork3()
{
var classTwo = new Class2();
// I can no longer see that Class2.DoWork2() will throw a 'MyCustomException'
classTwo.DoWork2();
}
}
In order to clear up some confusion which seems to have been generated in the comments I will put the two solutions which I am considering at present:
Tag DoWork2 with the same MyCustomException comment as Class1
Throw a different exception within DoWork2 and tag it with this
new exception. This option seems the most robust as it would allow a
more detailed log (e.g. where exactly the code fell over in it's
execution path). This way does seem a little over the top for
simplistic scenarios which is why I wonder if (1) is an acceptable
solution to this problem?
One of the major limitations with exception handling in .NET and Java is that there's no standardized means by which code can distinguish between an exception of some type which is thrown from a method for reasons that method expects, versus an exception of that same type which is thrown by a nested method, for reasons the outer method did not expect. If the purpose of a method is to call some user-supplied delegate, the only ways I know of to reliably distinguish between exceptions which are thrown by the called delegate and those which occurred in the process of calling it are either to pass the method an identity token which it will include in any exceptions it throws directly, or else have the method as a matter of policy wrap exceptions that occur while invoking the user-supplied callback. Neither method is terribly elegant.
Because there is no standardized way to identify exceptions which indicate that an operation failed "cleanly" without side-effects, from those which indicate that a more serious problem exists, I would suggest that code shouldn't rely upon "serious" exceptions to prevent "contagious" data corruption. Instead, any time an exception might cause an object to be left in a corrupt state, the object should be explicitly invalidated, to prevent corrupt data from being read from it and copied elsewhere (possibly overwriting what would have been the only good copy). In situations where the corrupted object isn't needed and stack unwinding would cause it to be invalidated, there is no problem. In situations where the object that was invalidated turns out to be essential for system operation, the program should be forcibly shut down and invalidating the object will make that happen more reliably than would throwing a "serious" exception.
Unfortunately, neither C# nor VB.NET provides a very nice pattern for guarding objects in this fashion. VB.NET has somewhat better exception-handling abilities than C#, and the correct pattern (taking action in a finally block based upon what exception was thrown, but without catching the exception) can be implemented, albeit awkwardly, in that language. In C# the only way to find out what exception occurs within a try block is to catch and rethrow, an action which has some side-effects.
There is an excellent interview with Anders Hejlsberg titled The Trouble with Checked Exceptions. (Anders led the team that designed the C# programming language.)
You are falling into the exception aggregation trap. You should probably not be asking "what exceptions could possibly be thrown by lower level systems?" The answer, in many cases, would be a list containing hundreds of unique exceptions.
Instead, you should ask yourself "how can I provide useful information to the developer?" You should document the exceptions that your code is explicitly throwing or, in rare cases, relevant exceptions that are very likely to occur and that the caller may be specifically interested in. The developer who calls your code can determine the necessity of handling those errors or passing that information along to the callers of their code - or simply doing nothing with it. Exceptions are exceptional, after all, and at a certain level it doesn't really matter which database error was thrown - the steps taken in response are the same (e.g. stabilize the environment if possible, write to the error log and terminate execution).

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

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).

Categories

Resources