Why are Exceptions said to be so bad for Input Val

2019-01-10 06:24发布

I understand that "Exceptions are for exceptional cases" [a], but besides just being repeated over and over again, I've never found an actual reason for this fact.

Being that they halt execution, it makes sense that you wouldn't want them for plain conditional logic, but why not input validation?

Say you were to loop through a group of inputs and catch each exception to group them together for user notification... I continually see that this is somehow "wrong" because users enter incorrect input all the time, but that point seems to be based on semantics.

The input is Not what was expected and hence is exceptional. Throwing an exception allows me to define exactly what was wrong like StringValueTooLong or or IntegerValueTooLow or InvalidDateValue or whatever. Why is this considered wrong?

Alternatives to throwing an exception would be to either return (and eventually collect) an error code or far worse an error string. Then I would either show those error strings directly, or parse the error codes and then show corresponding error messages to the user. Wouldn't a exception be considered a malleable error code? Why create a separate table of error codes and messages, when these could be generalized with the exception functionality already built into my language?

Also, I found this article by Martin Fowler as to how to handle such things - the Notification pattern. I'm not sure how I see this as being anything other than Exceptions that don't halt execution.

a: Everywhere I've read anything about Exceptions.

--- Edit ---

Many great points have been made. I've commented on most and +'d the good points, but I'm not yet completely convinced.

I don't mean to advocate Exceptions as the proper means to resolve Input Validation, but I would like to find good reasons why the practice is considered so evil when it seems most alternate solutions are just Exceptions in disguise.

17条回答
兄弟一词,经得起流年.
2楼-- · 2019-01-10 06:55

A user entering 'bad' input is not an exception: it's to be expected.

Exceptions should not be used for normal control flow.

In the past many authors have said that Exceptions are inherently expensive. Jon Skeet has blogged contrary to this (and mentioned a few time in answers here on SO), saying that they are not as expensive as reported (although I wouldn’t advocate using them in a tight loop!)

The biggest reason to use them is ‘statement of intent’ i.e. if you see an exception handling block you immediately see the exceptional cases which are dealt with outside of normal flow.

查看更多
欢心
3楼-- · 2019-01-10 06:56

8 years later, and I'm running into the same dilemma trying to apply the CQS pattern. I'm on the side that input validation can throw an exception, but with an added constraint. If any input fails, you need to throw ONE type of exception: ValidationException, BrokenRuleException, etc. Don't throw a bunch of different types as it'll be impossible to handle them all. This way, you get a list of all the broken rules in one place. You create a single class that is responsible for doing validation (SRP) and throw an exception if at least 1 rule is broken. That way, you handle one situation with one catch and you know you are good. You can handle that scenario no matter what code is called. This leaves all the code downstream much cleaner as you know it is in a valid state or it wouldn't have gotten there.

To me, getting invalid data from a user is not something you would normally expect. (If every user sends invalid data to you the first time, I'd take a second look at your UI.) Any data that prevents you from processing the true intent whether it is user or sourced elsewhere needs to abort processing. How is it any different than throwing an ArgumentNullException from a single piece of data if it was user input vs. it being a field on a class that says This is required.

Sure, you could do validation first and write that same boilerplate code on every single "command", but I think that is a maintenance nightmare than catching invalid user input all in one place at the top that gets handled the same way regardless. (Less code!) The performance hit will only come if the user gives invalid data, which should not happen that often (or you have bad UI). Any and all rules on the client side have to be re-written on the server, anyway, so you could just write them once, do an AJAX call, and the < 500 ms delay will save you a ton of coding time (only 1 place to put all your validation logic).

Also, while you can do some neat validation with ASP.NET out of the box, if you want to re-use your validation logic in other UIs, you can't since it is baked into ASP.NET. You'd be better off creating something below and handling it above regardless of the UI being used. (My 2 cents, at least.)

查看更多
地球回转人心会变
4楼-- · 2019-01-10 06:57
  1. Maintainability - Exceptions create odd code paths, not unlike GOTOs.
  2. Ease of Use (for other classes) - Other classes can trust that exceptions raised from your user input class are actual errors
  3. Performance - In most languages, an exception incurs a performance and memory usage penalty.
  4. Semantics - The meaning of words does matter. Bad input is not "exceptional".
查看更多
老娘就宠你
5楼-- · 2019-01-10 06:57

One problem with using exceptions is a tendency to detect only one problem at a time. The user fixes that and resubmits, only to find another problem! An interface that returns a list of issues that need resolving is much friendlier (though it could be wrapped in an exception).

查看更多
劫难
6楼-- · 2019-01-10 07:00

This is a linguistic pov( point of view) on the matter.

Why are Exceptions said to be so bad for Input Validation?

conclusion :

  • Exceptions are not defined clearly enough, so there are different opinions.
  • Wrong input is seen as a normal thing, not as an exception.

thoughts ?

It probably comes down to the expectations one takes about the code that is created.

  • the client can not be trusted
    • validation has to happen at the server's side. stronger : every validation happens at server's side.
    • because validation happens at the server's side it is expected to be done there and what is expected is not an exception, since it is expected.

However,

  • the client's input can not to be trusted
  • the client's input-validation can be trusted
    • if validation is trusted it can be expected to produce valid input
    • now every input is expected to be valid
    • invalid input is now unexpected, an exception

.

exceptions can be a nice way to exit the code.

A thing mentioned to consider is if your code is left in a proper state. I would not know what would leave my code in an improper state. Connections get closed automatically, leftover variables are garbage-collected, what's the problem?

查看更多
【Aperson】
7楼-- · 2019-01-10 07:01

I think the difference depends on the contract of the particular class, i.e.

For code that is meant to deal with user input, and program defensively for it (i.e. sanitise it) it would be wrong to throw an exception for invalid input - it is expected.

For code that is meant to deal with already sanitised and validated input, which may have originated with the user, throwing an exception would be valid if you found some input that is meant to be forbidden. The calling code is violating the contract in that case, and it indicates a bug in the sanitising and/or calling code.

查看更多
登录 后发表回答