Is having multiple layers of data validation in a program defense in depth against malfunction, or code-cluttering paranoia?

StackOverflow https://stackoverflow.com/questions/20062198

Question

For example, when the data is initially input, I might just spit it back out if it doesn't match my validation regex. Then when it comes time to use it, I often feel the impulse to do something like:

function useData(data) {
  if(data.match(/some invalidating substring/) throw Error('Shouldn\'t have ever gotten past the orig. regex, but somehow it did, so its good that this extra layer of debugging info was integrated.');
  // actually use the data.
}

I'm not really talking about security, because then you want to have defense in depth. The type of code I'm referring to is usually not security-sensitive, I'm just trying to write well-designed code that has a good chance of catching bugs. In some sense defense in depth is also called for against malfunction, and not only vulnerability, I suppose, but at the same time, the Unix philosophy calls for code to do one thing, and just that thing, but well. Considering that, it seems bad practice to not "trust" your validation code to do its job, and then make another piece of validation code in another function somewhere, "just in case". Having two pieces of code do one thing can't be good, either. Another disadvantage is that if you change the validation pattern, then you may forget to do so in both places.

Feedback?

Was it helpful?

Solution

This is something of a religious issue among programmers, but a sound approach is to follow a Design by Contract paradigm where you design functions that abide by contracts. A contract states preconditions, postconditions, and invariants. A function shall abide by its contract and provide no guarantees for behavior left unspecified within the contract.

Validating input within each function is redundant and can lead to messy code. Consider a simple function which takes in an integer x and returns the square root of x. Are you going to validate the input to make sure x is nonnegative? You could, or you could just specify in the contract that x must be nonnegative. The latter is much cleaner, but it requires more care on behalf of the programmer to use it correctly.

Don't try to catch bugs within your code. Instead, catch bugs with a good testing framework.

OTHER TIPS

A layered approach to validation is appropriate and is not overkill. While you are correct that duplicating validation should be avoided if possible, there are legitimate UX and test considerations that outweigh that concern. As an example, you might have model validation in your business layer that is duplicated in your UI layer for UX considerations. Your business layer cannot assume anything about your UI layer, (it might be accessed by a completely different UI implementation now or in the future), but that doesn't mean a good UI shouldn't push validation as close to the user as possible, even if it is duplicating logic.

A good (practical) validation framework should help you minimize this duplication by making your validation data driven (or even metadata driven). If your UI can get validation rules from the business layer, it can make use of these rules where appropriate to make a more responsive user experience.

Deciding what type of validation to do at each layer is important from a UX standpoint. You don't want to do heavyweight or long running validation during user keystrokes, for example.

The touch points for validation are generally:

Keystroke (Field Validation - is the field valid?)

Keystroke (Form Validation - are all the fields valid independently and when taken together?)

Element Change (Field Validation)

Element Change (Form Validation)

Form Submit (Client Field and Form Validation)

Form Submit (Server Field and Form Validation)

There are many variations on this theme (it's not unheard of to do some server side validation even at the keystroke level, if done appropriately). While not exactly validation, Google's instant search feature is a good example of how the technique can work).

Taking some time to design your validation framework end to end will pay dividends down the road. Most of the major frameworks also have built in validation frameworks that can be great starting points.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top