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.
The community reviewed whether to reopen this question 9 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have this debate with my colleague about this piece of code:
var y = null;
if (x.parent != null)
y = x.parent.somefield;
My point of view is that in the place where the code is, x.parent should not POSSIBLY be null. And when it is null, we have a serious problem and I want to know it! Hence, the null check should not be there and let the down stream exception happen.
My colleague says this is defensive programming. And the null check makes sure the code doesn't break the application.
My question is, is this defensive programming? Or a bad practice?
Note: the point is not who is right. I'm trying to learn from this example.
It looks like your colleague is misunderstanding "defensive programming" and/or exceptions.
Defensive Programming
Defensive programming is about protecting against certain kinds of errors.
In this case x.parent == null is an error because your method needs to use x.parent.SomeField. And if parent were null, then the value of SomeField would clearly be invalid. Any calculation with or task performed using an invalid value would yield erroneous and unpredictable results.
So you need to protect against this possibility. A very good way to protect is by throwing a NullPointerException if you discover that x.parent == null. The exception will stop you from getting an invalid value from SomeField. It will stop you doing any calculations or performing any tasks with the invalid value. And it will abort all current work up until the the error is suitably resolved.
Note the exception is not the error; an invalid value in parent that is the actual error. The exception is in fact a protection mechanism. Exceptions are a defensive programming technique, they're not something to be avoided.
Since C# already throws an exception, you don't actually have to do anything. In fact it turns out that your colleague's effort "in the name of defensive programming", is actually undoing built-in defensive programming provided by the language.
Exceptions
I've noticed many programmers are unduly paranoid about exceptions. An exception itself isn't an error, it's simply reporting the error.
Your colleague says: "the null check makes sure the code doesn't break the application". This suggests he believes that exceptions break applications. They generally don't "break" an entire application.
Exceptions could break an application if poor exception handling puts the application in an inconsistent state. (But this is even more likely if errors are hidden.) They can also break an application if an exception 'escapes' a thread. (Escaping the main thread obviously implies your program has terminated rather ungracefully. But even escaping a child thread is bad enough that the best option for an operating system is to GPF the application.)
Exceptions will however break (abort) the current operation. And this is something they must do. Because if you code a method called DoSomething which calls DoStep1; an error in DoStep1 means that DoSomething cannot do its job properly. There is no point in going on to call DoStep2.
However, if at some point you can fully resolve a particular error, then by all means: do so. But note the emphasis on "fully resolve"; this doesn't mean just hide the error. Also, just logging the error is usually insufficient to resolve it. It means getting to the point where: if another method calls your method and uses it correctly, the 'resolved error' will not negatively affect the caller's ability to do its job properly. (No matter what that caller may be.)
Perhaps the best example of fully resolving an error is in the main processing loop of an application. Its job is to: wait for a message in the queue, pull the next message off the queue and call appropriate code to process the message. If an exception was raised and not resolved before getting back to the main message loop, it needs to be resolved. Otherwise the exception will escape the main thread and the application will be terminated.
Many languages provide a default exception handler (with a mechanism for the programmer to override/intercept it) in their standard framework. The default handler will usually just show an error message to the user and then swallow the exception.
Why? Because provided you haven't implemented poor exception handling, your program will be in a consistent state. The current message was aborted, and the next message can be processed as if nothing is wrong. You can of course override this handler to:
Write to log file.
Send call-stack information for troubleshooting.
Ignore certain classes of exception. (E.g. Abort could imply you don't even need to tell the user, perhaps because you previously displayed a message.)
etc.
Exception Handling
If you can resolve the error without an exception first being raised, then it is cleaner to do so. However, sometimes the error cannot be resolved where it first appears, or cannot be detected in advance. In these cases an exception should be raised/thrown to report the error, and you resolve it by implementing an exception handler (catch block in C#).
NOTE: Exception handlers server two distinct purposes: First they provide you a place to perform clean-up (or rollback code) specifically because there was an error/exception. Second, they provide a place to resolve an error and to swallow the exception. NB: It's very important in the former case that the exception be re-raised/thrown because it has not been resolved.
In a comment about throwing an exception and handling it, you said: "I wanted to do that but I was told it creates exception handling code everywhere."
This is another misconception. As per the previous side-note you only need exception handling where:
You can resolve an error, in which case you're done.
Or where you need to implement rollback code.
The concern may be due to flawed cause-and-effect analysis. You don't need rollback code just because you're throwing exceptions. There are many other reasons that exceptions can be thrown. Rollback code is required because the method needs to perform clean-up if an error occurs. In other words the exception handling code would be required in any case. This suggests the best defence against excessive exception handling is to design in such a way that the need for clean-up on errors is reduced.
So don't "not throw exceptions" to avoid excessive exception handling. I agree excessive exception handling is bad (see design consideration above). But it is far worse to not rollback when you should because you didn't even know there was an error.
Interesting question. From my point of view, whether or not to include the check is a matter of how well the data is validated, where does it come from and what can happen when the check fails.
"x.parent should not POSSIBLY be null" is a serious assumption. You need to be very sure of it to play safe, of course there is the classic "it will never happen"....... until it happens, that's why I think it's interesting to review the possibilities.
I see two different things to think about.
Where does the data comes from?
If it comes from another method in the same class, or from some related class, since you have more or less full control about it, it's logical to relax your defenses, as you can reasonably assume that it's very unlikely to have bad data to begin with, or if it happens it's reasonably easy to catch the bug early during debugging/testing and even place some unit tests for it.
The opposite case would be if it's data entered by the user, or read from a file, or from a URL, anything external generally speaking. Since you cannot control what the program is dealing with: by all means, validate it as thoroughly as you can before using it in any way, as you're exposed to bogus/missing/incomplete/incorrect/malicious information that may cause problems down the path.
An intermediate case can be when the input comes from another layer/tier within the same system. It's more difficult to decide whether to do a full validation or take it for granted, since it's another piece of internal software, but might be replaced or modified independently at a later time. My preference goes towards validating again when crossing boundaries.
What to do with the validation?
Using an if (as in your sample) to simply skip over some assignment or usage may be fine for some cases. For instance, if the user is entering some data and this just shows a tooltip or other minor info, it's possibly safe to skip. But if the piece of code does something important, that in turn fills some mandatory condition or executes some other process, it's not the right approach as it will cause problems for the next code run. The thing is, when you skip over some code, it must be safe to do so, without any side effects or unwanted consequences, otherwise you would be hiding some error, and that's quite difficult to debug in later development stages.
Abort the current process gracefully is a good choice for early validations, when the failure is totally expected and you know precisely how to respond to it. An example could be a missing required field, the process gets interrupted and a message is shown to the user asking for the missing info. It's not OK to simply ignore the error, but also not serious enough to throw an exception that disrupts the normal program flow. Of course, you may still use an exception, depending on your architecture, but in any case catch it and recover gracefully.
Throw an exception is always a choice when the "impossible" really happened. It's in those cases where you cannot possibly provide a reasonable response for either continuing with some variation or cancel just the current process, it may be due to a bug or bad input somewhere, but the important thing is that you want to know it and have all the details about it, so the best possible way is to make it to blow up as loudly as possible, so that the exception bubbles up and reaches a global handler that interrupts everything, saves to a log file/DB/whatever, sends a crash report to you and finds a way to resume execution, if that's feasible or safe. At least if your app crashes, do so in the most graceful way, and leave traces for further analysis.
As always, it depends on the situation. But just using an if to avoid coding an exception handler is for sure a bad practice. It must always be there, and then some code may rely on it - whether appropriate or not - if it's not critical to fail.
I wouldn't call it defensive programming at all - I'd call it "la la la I can't hear you" programming :) Because the code appears to be effectively ignoring a potential error condition.
Obviously we don't have any idea of what comes next in your code, but since you didn't include an else clause, I can only assume that your code just carries on even in the case that x.parent is actually null.
Bear in mind that "should not possibly be null" and "is absolutely, positively guaranteed to never be null" are not necessarily the same thing; so in that case it could lead to an exception further down the line when you try to de-reference y.
The question is then - what is more acceptable within the context of the problem you are trying to solve (the "domain") and that kind of depends on what you intend to do with ylater on.
If y being null after this code is not a problem (let's say you do a defensive check later on for y!=null) then that's OK - although personally I don't like that style - you end up defensively checking every single de-reference because you can never be quite sure if you're a null reference away from crashing...
If y cannot be null after the code because it will cause an exception or missing data later on, then it's simply a bad idea to continue when you know that an invariant is not correct.
In short, I'd say this is NOT a defensive programming. I agree with those who thinks this code hides the system error instead of exposing and fixing. This code violates the 'fail fast' principle.
This is true if and only if x.parent is a mandatory non-null property (which seems to be obvious from the context.) However, if x.parent is an optional property (i.e. can reasonably have a null value) then this code can be allright depending on your business logic expressed.
I'm always considering usage of empty values (0, "", empty objects) instead of nulls which require tons of irrelevant if statements.
After some years of thinking about this issue, I use the following "defensive" programming style - 95% of my methods return string as a success / failed result.
I return string.Empty for success, and informative text string if failed. While returning the error text, I write it to log at the same time.
public string Divide(int numA, int numB, out double division)
{
division = 0;
if (numB == 0)
return Log.Write(Level.Error, "Divide - numB-[{0}] not valid.", numB);
division = numA / numB;
return string.Empty;
}
Then I use it:
private string Process(int numA, int numB)
{
double division = 0;
string result = string.Empty;
if (!string.IsNullOrEmpty(result = Divide(numA, numB, out divide))
return result;
return SendResult(division);
}
When you have Log monitoring system, it lets the system show go on, but notifies the administration.
Related
Usually, when I work with files and directories and I want to check that a path of a a directory or a file exists, I just use something like that:
if (Directory.Exists(path))
{
//Something...
}
However, if I understood this answer correctly, it is recommended to allow the exception still be thrown, meaning that rather than using if, use try.. catch.
Is that a general approach when working with files and directories or there are times that it is preferable using if(Directory.Exists... or something of that sort?
NOTE: After seeing the first responses, just wanted to clarify that the cases when certain directory/path might not exist is an expected and normal behavior.
You nearly always have to catch exceptions, especially for I/O errors, somewhere, lest the program simply be killed when one occurs.
In many scenarios, it makes sense to also first check for valid input (e.g. Directory.Exists()). This allows you to efficiently and in a user-friendly way report and respond to obvious user-error scenarios.
But you have no guarantee that the directory won't be deleted between the time you execute that call and the time you try to access it in some way. Or that if the directory is on a remote share, the network won't fail. Or that you won't have some other kind of I/O error.
There are a few exceptions that just aren't worth catching. Unexpected OutOfMemoryException for example (as opposed to some data structure simply getting too large), or other types of internal .NET failures. The likelihood of recovering from those types of errors is minimal. But for anything else, you at some point should be catching exceptions that could happen. Sometimes this simply means a top-level catch (Exception e), where you will log the exception in some way before exiting the program cleanly.
(I will note that exceptions that are uncaught and which cause the application to be terminated will generally get logged in the system event log. So as long as users are comfortable inspecting the log and retrieving exception information from there, then there's no need to catch all exceptions…just those you know what to do with).
100% depends on what you want to achieve.
If a path is invalid and you want to inform it to the user, you can choose between returning a success value or throwing an exception by what's more suitable for your code architecture.
In other cases, where something can go wrong without the user being responsible for it, or needing to be informed, you usually let exceptions get thrown and handle them in catch blocks in the appropriate places.
The thing to remember is that you can always perform an if check and throw an exception of your own in case of invalid state, rather than letting the invalid state cause an exception by itself. The main difference there is in the data thrown with the exception (stack trace, message, etc), but can also be expressed in performance (you wouldn't want to try a high-cost operation if you can first perform a low-cost check to make sure it will succeed). Try-catch blocks add a BIT of an overhead as well, but I wouldn't consider that to be significant.
The questions to ask are:
Does invalid state causes the whole operation from above to fail?
Where and how does the code handle invalid state?
Does the code "fix" the invalid state and tries again?
Is the invalid state originating from a user error or a code issue?
How costly the operation is, in contrast to how costly the validation check is?
Edit: Check out Yuval's link in the comment to get better understanding of the costs of try-catch blocks.
The validation check is almost always very low-cost, so in conclusion I would say: Perform the check, even if you intend to throw your own exception in case of invalid state.
I'm new in a developement for Windows 8 and C#, but I have certain experience with Java Programming.
So, when I try to make some Json parser (for example) in java, I can't do it without use a try - catch block, and this way I can handle the exception, but when I try to do the same in c# (Windows 8) and I don't use the try - catch block it works too, like this:
if (json != null)
{
JObject jObject = JObject.Parse(json);
JArray jArrayUsers = (JArray)jObject["users"];
foreach (JObject obj in jArrayUsers)
{
ListViewMainViewModel user = new ListViewMainViewModel(
(String)obj["email"],
(String)obj["token"],
(String)obj["institution"],
(String)obj["uuidInstitution"]);
usersList.Add(user);
}
return usersList;
}
}
As I know the right way is to catch JsonReaderException, but Visual Studio never warned me on that. I would like to know if there's a easy way to know if some method throw an exception, like is on java using eclipse (it's mandatory implement try-catch block or code wont compile)
You will have to consult the documentation for that. C# lacks a throws keyword.
The term for what you are looking for is checked exceptions, and more info can be found in the C# FAQ.
In C# you are responsible for handling exceptions - which IMHO is the better way of going about it than the Java implementation. In effect, an exception should be, well exceptional, that is: It isn't something you should just always expect to happen.
Consider this weirding (yet, common) anti-pattern:
try {
} catch (Exception ex) { /* Handler goes here */ }
What exactly does that mean? Are you really going to handle every single exception that passes through here? Even stuff like OutOfMemoryExceptions? That's nuts. The only thing this sort of pattern will lead to is suppressing legitimate exceptions that really ought to bring down the application - this is fairly similar to the Java approach.
Think of an Exception as being a flag to the programmer that says 'hey, the environment just entered an impossible state'. For example, if I try to divide by zero and the system throws a DivideByZeroException, then rightly the system should alert you to this, because this is a failure - one the system can't just 'figure it's way out of' - and if you simply suppress the issue, how is that really helping? In the end this is counter-productive, in that all you're doing is masking over what is really an impossible application state. If you do this a lot in your application, then it eventually just devolves into a sludge of toxic wrong-ness. Yuck!
Exceptions also take up a lot of screen real estate. Sometimes I wish they would make the try/catch/finally blocks a little more streamlined, but then I remember that doing so would encourage people to use them more, so I repent of that position pretty quick.
Exceptions are useful programmer-to-programmer notifications saying that something you're doing doesn't make sense. Obviously we should never pass raw exceptions to the user because they won't know what to do with them. At the same time, you don't want to try to handle every single exception on the face of the earth, because 'handling' in this sense typically transforms into 'suppression', which is way worse than just letting the application fail (gracefully).
C#, as has been mentioned, does not have checked exceptions, and thank goodness.
The idea of checked exceptions sounds great on its face, but talk to anyone who is forced to use them by language or runtime, and they'll say there are three big problems with checked exceptions:
They impose their will upon the consuming coder. Checked exceptions, by their definition, are expected to be handled before they are thrown out of the runtime. The runtime is in effect telling the coder "you should know what to do when I throw this, so do so". First off, think about it; you are told to expect something that happens in exceptional cases by its very definition. Second, you're expected to somehow handle it. Well, that's all well and good when you actually have the ability to address the problem the exception indicates. Unfortunately, we don't always have that ability, nor do we always want to do everything we should. If I'm writing a simple form applet that performs a data transformation, and I just want my application to die a fiery death if there's any problem, I can't just not catch anything; I have to go up all possible call stacks of every method that could throw something and add what it could throw to the throws clause (or be extremely lazy and put a "throws Exception" clause on every method of my codebase). Similarly, if my app is constructed such that I can't throw out a particular exception, perhaps because I'm implementing an interface beyond my control that doesn't specify it as a potential throwable, then my only options are to swallow it entirely and return a possibly invalid result to my callers, or to wrap the exception in an unchecked throwable type like a RuntimeException and throw it out that way (ignoring the entire checked exception mechanism, which is not recommended of course).
They violate SOLID, especially the Open-Closed Principle. Make a change that adds a checked exception to your code, and if you can't handle said exception, all usages of your method must either handle it or mark themselves as throwing the exception. Usages which rethrow must be handled by their own callers or they have to be marked as throwing the same exception. By making a change as surgical as calling an alternate method in a particular line of code, you now have to trace up all possible call stacks and make other changes to code that was working just fine, just to tell them your code could conceivably throw an exception.
They create leaky abstractions by definition. A caller consuming a method with a "throws" clause must, in effect, know these implementation details about its dependency. It must then, if it is unwilling or unable to handle these errors, inform its own consumers about these errors. The problem is compounded when the method is part of an interface implementation; in order for the object to throw it, the interface must specify it as a throwable, even if not all of the implementations throw that exception.
Java mitigates this by having a multilevel hierarchy of Exception classes; all I/O-related exceptions are (supposed to be) IOExceptions, for instance, and an interface with methods that have IO-related purposes can specify that an IOException can be thrown, relieving it of the responsibility to specify each specific child IOException. This causes almost as many problems as it solves, however; there are dozens of IOExceptions, which can have very different causes and resolutions. So, you must interrogate each IOException that you catch at runtime to obtain its true type (and you get little or no help identifying the specific ones that could be thrown) in order to determine whether it's something you can handle automatically, and how.
EDIT: One more big problem:
They assume try-catch is the only way to handle a possible exception situation. Let's say you're in C# in an alternate universe where C# has Java-style checked exceptions. You want your method to open and read a file given a filename passed into it by the caller. Like a good little coder, you first validate that the file exists in a guard clause, using File.Exists (which will never throw an exception; in order to return true, the path must be valid, the file specified at the path must exist, and the executing user account must have at least read access to the folder and file). If File.Exists returns false, your method simply returns no data, and your callers know what to do (say this method opens a file containing optional config data, and if it doesn't exist, is blank or is corrupted, your program generates and uses a default configuration).
If the file exists, you then call File.Open. Well, File.Open can throw nine different types of exceptions. But none of them are likely to occur, because you already verified using File.Exists that the file can be opened read-only by the user running the program. The checked exception mechanism, however, wouldn't care; the method you're using specifies it can throw these exceptions, and therefore you must either handle them or specify that your own method can throw them, even though you may take every precaution to prevent it. The go-to answer would be to swallow them and return null (or to forget the guard clause and just catch and handle File.Open's exceptions), but that's the pattern you were trying to avoid with the guard clause in the first place.
None of this even considers the potential for evil. A developer might, for instance, catch and encapsulate an unchecked exception as a checked one (for instance, catching a NullPointerException and throwing an IOException), and now you have to catch (or specify that your method throws) an exception that isn't even a good representation of what's wrong.
As far as what to use instead in C#, the best practice is to use XML documentation comments to inform the immediate caller using your method that an exception could potentially be thrown from it. XML-doc is the .NET equivalent to JavaDoc comments, and is used in much the same way, but the syntax is different (three forward slashes followed by the comments surrounded with a system of XML tags). The tag for an exception is easy enough to specify. To efficiently document your codebase, I recommend GhostDoc. It will only generate exception comments for exceptions explicitly thrown from inside the method being documented, however, and you'll have to fill in some blanks.
I'm not a java developer, but from the answers here it seems as though the Java implementation is a burden to clients of those methods. However, C# missed an opportunity (Java-like or otherwise) to communicate to the caller the type of exceptional outcomes that could happen, as authored by the developer of the method, allowing me the caller to handle it appropriately.
Since this construct isn't built into the language, I would suggest to library developers that you adopt a wrapper class and use it as the return type for any methods that could go awry. Using said class as the return type in lieu of exceptions, clients can reason about what to expect when calling the method, as it is clearly defined in the method signature. Also, using the wrapper would allow a method to tell a client why something went awry in a way does not break the flow like exceptions do.
More on this subject here: http://enterprisecraftsmanship.com/2015/03/20/functional-c-handling-failures-input-errors/
Is it a good practice to define and throw custom exceptions even if the application needs lots of them?
EntityNotFoundException
EntityAlreadyExistsException
EntityNotUniqueException
EntityNotAddedException
EntityNotUpdatedException
EntityNotDeletedException
QuizOverException
QuizExpiredException
TableAlreadyBookedException
EndDateMustBeGreaterThanStartDateException
I tried to name these sample exception names to describe their purpose as good as I could. I hope they could form an idea of what I am trying to ask.
Don't limit your imagination with only these exceptions but all that could arise during you application's life. Consider both CRUD and business exceptions.
I know that throwing and catching exceptions is an expensive process in terms of performance but don't they provide a more elegant way to develop you app?
Isn't it better to throw a EntityNotFoundException instead of writing an if statement to check whether the entity is null?
Isn't it better to throw a EntityAlreadyExistsException instead of writing an additional if statement which will call a method to check whether the entity with the given Id already exists?
Isn't it better to throw a EntityNotAddedException instead of checking the return value of type bool specifying whether the transaction was successful or not? What if we want to return an object?
I feel that the answer will be like "you should not use EntityNotFoundException but instead check if null, but you should use EntityAlreadyExistsException", "there is no holy grail".
I am wondering what is the elegant way of doing this?
Keeping in mind that exceptions are supposed to represent exceptional circumstances all of your questions can only really be answered with - it depends.
The context of when & where you intend on throwing a particular exception will naturally decide whether it makes sense. For example, if you attempt to retrieve an entity that should exist but doesn't, then throwing an EntityNotFoundException would be considered appropriate because we now have an exceptional circumstance. On the other hand, if you are checking whether the entity already exists before creating a new one then you could argue that because we know there is a chance the entity may or may not exist then it's not really an exceptional circumstance.
Like I said, it really depends on the context of the situation and the nature of your application whether you should throw an exception or not, however, the one thing you don't want to end up doing is controlling the program flow with exceptions.
To help make the distinction between when it's suitable to use an exception vs business logic, simply ask yourself "is this particular situation valid?" or in other words "is it OK for the application to find itself in this state?". If the answer is yes, use logic to control the flow of the application and deal with the situation, otherwise you want to throw an Exception to effectively interrupt the program flow and inform the user that something isn't quite right.
When creating exceptions ask about their added value.
Will someone care about specific types of exception to be caught?
Will exceptions have different fields to help exception handling?
More abstract exception with custom message can save you time writing exceptions with no value.
Using exceptions to control program flow is considered bad idea. Here are some reasons:
Exceptions have been created for concept of error handling
Performance as you said
you can forget to handle some exceptions
If you use checked exceptions you may need to write handlers for exceptions you do not care about or don't know how to handle.
Exceptions increase uncertainty in programs (exceptions thrown while exception handling, finally statements,...)
There are other ways to solve conditional statements, take a look at scala programming language and its use of "monads".
One major limitation with the exception-handling paradigm in C++, which was inherited by Java and subsequently .NET, is that if a call to Foo throws a BozException, that can have two very different meanings:
Some condition was detected during the execution of Foo which implied that it should throw a BozException.
Foo called some method which it was not expecting to throw a BozException, but the method threw one anyway and Foo didn't catch it, the exception was thrown out of Foo.
Even though the Framework guidelines discourage the use of custom exceptions when an existing exception would seem to "fit", the lack of any standard means for code that catches a Framework-defined exception to know whether it actually represents an expected circumstance is a pretty big disadvantage to using a Framework exception (like InvalidOperationException) to report business-logic circumstances a caller might want to handle (e.g. trying to add to a Dictionary to records with the same ID). If you can tolerate the boilerplate associated with defining exceptions, I'd suggest that it's better to err on the side of too many rather than too few (though you may wish to use inheritance for exceptions that will likely be handled the same way).
As with almost everything in software development, given a general rule or best practise the skill is knowing when and how to apply it.
Should I program to an interface? YES! Should I make every single class I write implement a corresponding interface and only ever program to that abstraction? I could do but writing a very simple application would take me an age and my productivity would grind to a halt.
Single Responsibility - is it a good thing? YES! Does every class I write have exactly one and only one responsibility. No - partly because of my own failings as a programmer, but also because I'd end up with a plethora of single-method classes and an unmanageably disconnected code base.
Now let us turn to error handling:
Firstly, by looking at your comment to James' answer, let us clarify that using error codes and exception handling represent two distinct models of handling errors in your application and as a general rule they should not be mixed.
Let us assume you are using exception handling and make the following argument:
Why do we throw exceptions?
We throw an exception because something bad has happened. If we are expecting a scenario to occur some point, then it is within the flow of our application, and is therefore not exceptional - so throwing an Exception would not be appropriate!
With this argument, it makes little sense to throw anything other than the top level Exception class, as any other exception implies that we have foreseen this scenario and have been able to attach extra metadata to the exception.
Why handle exception?
Having thrown an exception, we expect someone somewhere to deal with it, hopefully with the intention of restoring the application to a consistent state. However, if the exception is truly exceptional - we can have no way of knowing what state has been corrupted so exception handling is futile.
Isn't this taking things a bit too far?
Well - this is exactly how error handling works in a service orientated architecture. A robust service should not reveal any incriminating details of what has happened when an exception occurs (it's a security breach and introduces coupling between the service and the client) - all the client needs to know is something bad happened.
However, I'm guessing that we are working within an Object Orientated environment, where we are prepared to accept a slightly higher degree of coupling between an implementation and it's consumers. And it is this that is the important point - by introducing an exception hierarchy which exposes detailed information about the exception you increase the coupling in your application (the consumers need to have detailed knowledge about all the exceptions you could throw).
In software we strive for a loosely coupled code base, making it easy to maintain and extend. I have no doubt there is a happy medium between the SOA approach to exceptions and the one you describe in your question - finding that sweet spot is the skill of the developer.
The main example here is copying a word document. I have these lines of code in my program:
try
{
File.Copy(docTemplatePath, docOutputPath, true);
}
catch (IOException e)
{
MessageBox.Show(e.ToString());
}
Now I'm trying to build in error checks. I want to make sure that the output Word Document is not open elsewhere before I try to save, because otherwise an exception is thrown.
The way I see it is that the exception is thrown to warn me of an error that is causing the default functionality of the code to not work as expected. In this sense I would feel comfortable catching an exception, reading it to discern the issue (in this case that the document is currently locked/open elsewhere) and thus showing a MessageBox to alert the user to the fact the document they're trying to write to a file that is open elsewhere.
Is this fine to do? I have seen many places over the course of my looking into this where it would seem that this is what exceptions are designed to do, and other places where people seem to think thaat using exception to do stuff like this is hideously against all programming traditions and would prefer to check themselves.
What is the overall consensus?
Thanks
You should use Exceptions to handle exceptional occurrences.
That is; sometimes there will be foreseeable circumstances: A file name entered by a user might not exist, so your code should check File.Exists() before attempting to load it, for example (not relying on an exception).
That file already being in use and locked by something else might be an exceptional situation; it probably is, so that's probably just fine.
IMO, in .Net, exceptions should be used for managed unexpected errors.
For me it's a bad idea to throw an exception for a authentification error (like bad password) but it's a good to use it for manage a database connection error.
So, in few words, i use exceptions in order to manage unexpectable issues and not business issues. The idea of doing every business issues with an exception is more an "over" object oriented approach and is not what it should be use for.
Your example is IMO a good example of the good way to use exception.
Globally it's just a "big" try/catch around functionnality or specific tasks.
AFAIK Exceptions are designed for handling things that are out of the developers control like a hardware failure or disconnected network or something similar to that, where the developer might not have the knowledge of the problem,
IMHO it is better to check for the value of divider in the expression
int r = val/divider; than to check for the DivideByZeroException
Using Exceptions to control program flow is 'not done'. They should be used only to handle exceptional circumstances, when you don't want your entire application to crash.
That said, sometime it is necessary to use Exceptions. I believe the int.TryParse and other TryParse methods in the .NET Framework use Exceptions, catch them if it doesn't work, and then return false.
If there is no other way of knowing if a Word file is already open, my opinion is that you could use an Exception to do this. The good thing is that you catch a specific exception, because other things could go wrong. The problem is that the IOException could have another source (i.e. the destination folder is not accesible, etc.). This is true not only for your example, but for all (complex) exception-driven flows. The TryParse example I gave above is fairly simple, so there, it's not so much of a problem.
Conclusion: don't do it, unless it's the only way you can. And then, try to isolate it in a separate method. This way, if you find a better solution, you can always change your implementation. Also, try to catch the most specific exception, and keep in mind that exception can have several sources.
If a routine can satisfy its contract by returning normally, it should do so. If there is no way a routine can return normally without violating its contract, it should throw an exception. If a routine's contract is taken as a given, there's really not much room for judgment in deciding whether the routine should throw an exception. It should return or throw based upon the above simple rule.
The place judgment enters into the equation is in deciding what a routine's contract should be. A useful pattern is to provide both a "Try" version of a routine and a "Do" version; if the "Try" version is unable to perform the requested action because of a reasonably-anticipated problem, it will indicate that by returning some type of error value; if a "Do" version is unable to perform the requested action, for any reason, it will throw an exception.
As a simple example, consider "Integer.TryParse" and "Integer.Parse". If one has a string which may or may not be a valid number, one may call Integer.TryParse. Integer.TryParse will use a returned flag to indicate whether the parse was successful; it will return perfectly happily whether the parse succeeded or not, and the caller is responsible for ensuring that TryParse succeeded before trying to use the returned value. By contrast, Integer.Parse will only return if the number was parsed successfully. If the number wasn't valid, Integer.Parse will throw an exception. Calling code may thus use the value returned by Integer.Parse without having to check whether it succeeded; if Integer.Parse didn't succeed, it wouldn't have returned. Note that it's possible for Integer.TryParse to throw exceptions in some truly exceptional cases (e.g. if unsafe code had made the passed-in String reference point to some other type of object); the only guarantee is that it won't throw in the reasonably-expected cases (e.g. it's passed a string like "XYZ" instead of one like "123").
A slight enhancement to the Try/Do pattern is to have a routine accept a delegate which will be invoked if something goes wrong. In many cases, passing a delegate would be overkill, and it's often hard to decide in advance what parameters the delegate should take, but this approach can be advantageous in cases where a decision of whether to muddle on or give up may be determined by outside factors. Such situations arise in communications scenarios, where a program's proper response to a communications hiccup may be to up a message notifying the user that the program is having difficulty and allow the user to hit "cancel", but to have the program retry the operation a few times if the user does not. If the operation that had to be retried was a small portion of the overall operation to be performed, throwing an exception out to the main line would 'permanently' give up on the larger operation, while performing retries without user interaction could force a user to sit annoyingly long for the computer to give up on an operation the user might know won't possibly succeed (e.g. because the battery just died on the device he was communicating with). Using a callback delegate allows the optimal user interface experience, without tying the communications code to any particular user-interface implementation.
I'm not sure if this is a duplicate but if it is please feel free to close this.
Background:
I have a timer component for a game i'm writing that supports Stop and Pause methods. The non-critical error cases in question are doing things like calling Pause when in the timer is already paused, this is not fatal but it's not going to cause the change in state implied by the method name
Questions:
1. How does one generally indicate a non-fatal but abnormal condition?
2. Should I actually be throwing an exception in these cases? I think it's a little heavy-handed considering calling Pause when paused wont do any harm
3. Am I over-thinking this
UPDATE:
Based on the responses and comments here is the statergy I have chosen to take:
In development builds an exception will occur because I consider these bugs and I'd like to catch them and correct them. I can't justify an exception in a release build because these bugs don't corrupt the game state, and I don't think users of the application would appreciate the loss of their hard earned score because I failed to code properly
Thanks for all your responses, this has been very educational for me.
I think your fine to just ignore the call if the timer is already paused. Assuming the method is called Pause() then the client only requires that after the method call that the timer is paused, and exceptions should only be thrown if it won't be; the method doesn't imply any requirement on the current state of the timer.
On the other hand if the method was called ChangeTimerFromRunningToPaused() then that implies that it is only valid to call this on a running timer. Under these circumstances I would expect it to throw an exception informing the client that the timer is not in a valid state to process this method call.
Against the other answers, I would consider throwing an exception. If it would be my code performing the second Pause() call, I might consider my code to be broken if it makes this call where it should not. Maybe I am missing a check like if (Timer.IsRunning) { } and I don't want to hide this bug by silently ignoring the call. Even if the call is triggered by user input - a button click for example - this might be an indication of bad design and I should have a look at it. Maybe the button should be disabled.
The more I think about it, the less situations come to mind where the second call should not be an exception indicating bad calling code. So, yes, I would throw the exception.
UPDATE
In a comment Martin Harris suggest using Debug.Assert() to get the bug during development. I think that this is to weak because you won't get the bug in production code. But of course you don't want to crash an application in production because of this non-fatal error. So we will just catch this exception up the stack and generate a error report and than resume as if nothing happend.
Here are two goo links.
API Design Myth: Exceptions are for "Exceptional Errors"
Coding Horror - Exception-Driven Development
In such cases (moving some state machine to a state on which it already is), I'd just skip the call. Usually, non-fatal errors or warnings should not be thrown as exception, but rather returned as result (which can be ignored or processed, whatever fits the situation best).
No, don't throw an exception, Exceptions are heavy. There's nothing wrong to pause again. I don't see any harm.
This looks similar (though not identical) to one of my questions, perhaps the answers there are helpful for you.