可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
According to the .NET Framework General Reference: Error Raising and Handling Guidelines exceptions should not be thrown during 'normal' operations. Is invalid user input to a web form, say the user enters a duplicate name, considered normal? !! IMPORTANT !!: I'm sure we pretty much all have an opinion on this, please include a reference to a reliable source.
EDIT:
A little more background: I'm questioning the approch to model validation advocated by a book I'm reading. The book is suggesting that you throw a custom exception from a repository when provided with invalid data to save. Now, this seems to me to violate MS guidlines because you are using exceptions as flow control...unless recieving invalid data is consider outside of 'normal' operation. I just want to see if there is any further guidance from a reliable source to resolve this.
ANOTHER EDIT:
OK so two and a half years later, I'm moving this repository to a WCF service and using exceptions in this method turned out to be a bad idea. Oh well.
回答1:
Generally speaking, invalid or ill-formed input is not consider 'exceptional' and should be handled using something other than exceptions. But note that this is a guideline - there may well be situations where using exceptions to handle the problem would result in better code.
回答2:
An invalid user input is an EXPECTED situation. You expect it to happen same often like valid input. When so, throwing exceptions might be too much.
On the other hand, you may throw custom exceptions and catch them internally if you prefer this code style for some reasons. But an invalid user input should not throw that type of exception that would stop your application completely.
回答3:
Here's how you do it:
On the database side, you throw if you try to create a new user record with a duplicate name. Its an exceptional situation and you can't do anything about it on the database side. You also provide methods for checking the availability of user names.
On the UI side, you allow the user to select a name, then check its availability. Its the responsibility of the UI side to interact with the user and tell them to choose another name. With the ability to check the validity of the name, the UI should never pass in a duplicate name... unless something exceptional has happened.
I agree with the book in this case. Your database is the lowest level of your application and shouldn't have too much business logic coded in it (if A happens, then do B, unless C, then D). That doesn't mean you can't provide useful methods within your data layer that you can use to avoid exceptions.
回答4:
an exception is something that is exceptional--that is why they are called exceptions. Bad user input is not an exception, as a general rule, and should be handled gracefully with some type of notification to said user. Also, lets not forget that exceptions really kill the performance of your code.
http://blogs.msdn.com/kcwalina/archive/2005/03/16/396787.aspx
http://msdn.microsoft.com/en-us/magazine/dd419661.aspx
回答5:
If you are explicitly validating user input against certain criteria, and plan on taking action based on the outcome of that validation then you will find it far easier if you don't throw exceptions.
回答6:
Generally no, but I can think of one exception to the rule that I have personally encountered.
We require that our domain objects are valid at all times. If an attempt is made to create or pass bad data, we do thrown an exception from the domain object. In this case, though, it is an "exceptional circumstance". Why? The logic is that bad data should never make it into the domain. Somewhere along that call stack is a place where invalid data was able to be entered into the system - whether it was through a miscalculation, bad data from the underlying data source, or from user input.
Another, ancillary reason we do this, is that the domain objects and their rules are encapsulated within a physically separated assembly. By doing this, we make sure that we provide as much information to the caller, as possible. Because of the implications of what is happening, the assumption is made that the caller will log this so that there is visibility into what truly is an issue - that of not validating the data.
So, in the case where you are looking to see if the data has not been validated or that the rules to validate themselves are at odds with your data persistence methods/functionality, I think that it is perfectly valid to throw. In all other cases, I tend to avoid throwing for invalid input.
回答7:
I have heard and read that good OO practices would not throw an exception for user input. However, this logic does make me scratch my head a bit too. Think of the history here. Back in C programming, I might write a function such as:
int validateUserInfo(struct info)
{
//...
}
The Caller would do something like:
int errorCode = validateUserInfo(info);
if (errorCode != 0)
handleError(errorcode);
As far as I can remember, exception handling was written to get away from returning error conditions as a return value for methods such as shown above. Yet, if I dont use exception handling for validating user info, am I not back to returning some condition about bad data that causes me to have an if statement to check for invalid data to change my "successful" flow of execution?
Now it seems like I have to check for return values and wrap in try/catch. The validateUserInfo method in a C++/C#/Java class could throw an exception for a "exceptional error" and return "bad data" validation errors as a return value or some other mechanism. Isnt that making the code more complex for the sake of some "OO Rule"?
Of course an OO purist will come back with some alternative such that I dont have to actually return the "bad data" validation error in an attempt to nullify this scenario, but the fact is that somewhere someone will be writing code to check for validation error as well as writing a try/catch block for exceptions.
If exception handling is slow, then the compiler developers should fix it to make it faster. That shouldnt be a reason for avoiding exceptions.
回答8:
Code Complete by Steve McConnell provides a check-list for Defensive Programming that is really good. Under the exceptions topic he includes:
- Does your project have standards (those trump all else)
- Are there alternatives?
- Can you handle it appropriately internally to the method?
My feeling is Defensive Programming should always be managed by the method taking in the data. So, throwing an exception would not be appropriate.
There are always mitigating circumstances, of course.
回答9:
I agree with other answer-ers that bad input is expected, and should not be handled with an exception. However, if you discover malicious input (sql injection attempt or something like that), then an exception might be appropriate.