How to make a good validation in programming?
Here is the question, I would like to develop my own set of API and it will shares among others, when I develop this API, I can't ensure other is doing the right thing...Let say I provide a simple say hello program... Within any error checking and validation will have something like this:
function sayHello($yourName){
echo($yourName);
}
then, some people may not know what should pass on $yourName params, and include a type checking, so I will enhance something like this...
/**
* Say hello to someone.
*
* @param string $aName
**/
function sayHello($yourName){
if (!is_string($aName)) {
throw new ArgumentException("Type not correct.");
}
echo($yourName);
}
OK, I may have further checking, for example, the user may pass开发者_高级运维 an empty string or very long string to me, so I need to avoid that as well, so my code will become like this :
/**
* Say hello to someone.
*
* @param string $aName
**/
function sayHello($yourName){
if (!is_string($yourName)) {
throw new ArgumentException("Type not correct.");
}
if(strlen($yourName)) == 0 || strlen($yourName)) > 100){
throw new ArgumentException("argument length is invalid.");
}
echo($yourName);
}
ok, even worst case, I have some business logic in my function, for example, my function only allow english name, so , I will have something more complex like this:
/**
* Say hello to someone.
*
* @param string $aName
**/
function sayHello($yourName){
if (!is_string($yourName)) {
throw new ArgumentException("Type not correct.");
}
if(strlen($yourName)) == 0 || strlen($yourName)) > 100){
throw new ArgumentException("argument length is invalid.");
}
if(!isEnglishName($yourName)){
throw new ArgumentException("argument business logic is wrong.");
}
echo($yourName);
}
As you can see, only this simple sayHello program can from a 3 lines code to become more, it only a simple function, consider I more complex logic, how can I simplify that process? What kind of strategic I can take? Thank you.
Brilliant example!
In short - do not validate anything, it's not worth of all further pains.
- you have to write them - which is hard (3 rules and it could be even worse)
- they're usually duplicated in different places (sayHello, setDefaultHello, etc.) - because you don't have proper type (Name), you're still just "restricting" string.
- you have to throw exceptions - but which one?
I know how bad this may sound (I'm completely ignoring design-by-contact, how bad I am!), but:
- what's the point of restricting input arguments, anyway?
- do you really want to disallow passing objects?
- is your code about "doing" or "restricting"? focus on your goal - what has to be done, not how and not when.
- which version is more readable? with or without validations?
Especially that last one should be convincing.
Summary:
- you can introduce Name class (and a lot of other classes for all of your types)
- or you can get into duck-typing
I suggest the latter one. If you don't have opinion about it yet, just try it, you can always get back to design-by-contract. Just never mix them together.
As for handling user input, modern web frameworks allow for validation of all web forms. Here's an example (not taken from any specific framework):
$validation()->item('name')->add_rule(array('required', 'min_length[2]','max_length[20]' 'is_english', 'is_string'));
You see, the validation is still present, but the code has been abstracted away and centralized in some other class, where you can reuse the functionality.
Then instead of duplicating code all over the place, you're just configuring forms.
Logically, you may not simplify the process.
You could put name validation in a function so as to make the top-level code easier to follow, but you must do these validations somewhere. And particularly so in the case where the user has typed $yourName
, as might be true in your example.
Consider an analog to this requirement: that you must check for an error return from every function you call. It's no different here.
You really have no choice: if you fail to check for errors from any function, you have placed a time bomb in your program. The same is true here: you must validate function inputs.
It's dismaying to find that argument validation takes as much code as does the core operation of the function. But that's the way it is. There is just no way around it.
精彩评论