Search code examples
javascriptvalidationdefensive-programming

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


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?


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.