Why validation libraries suck

Daniel Steigerwald
3 min readJul 11, 2016

--

Almost all validation libraries I have seen (and I wrote) suck. Everything is nice and all with isRequired and isEmail, but then suddenly things become complicated. Custom validations, async validation, cross form fields or even cross forms validation rules, we all have been there. The reason for all of that is simple. There is no such thing as an ideal validation library. Why?

Your application is the validation library you are looking for. The application itself has to enforce various business rules. And we never know which business rules can come.

I wrote several validation libraries in last ten years. They all were wrong. What am I using nowadays in the github.com/este/este? Super simple validation primitives. I believe validation belongs to Redux Action (or somewhere else if you are using other state containers), but never into user interface aka React Components. It’s tempting but utterly wrong. It works only for super simple use cases, and then you have to rewrite everything. It’s a bad pattern. Don’t use it.

In Este, I’m using thin extensible wrapper for chriso/validator.js. I can add as much custom validation as I want. Validation itself is just a single flow rule by rule, sync or async, doesn’t really matter. I don’t like showing all validation errors to the user at once. But hey, some people prefer it. Do we have to rewrite whole Este validation? No :-)

Check how the validateEmailAndPassword function returns the promise with rejection expressed as ValidationError. That’s the only contract we need between validation and validation projection.

Because the Este validation is not coupled with validation error projection into UI directly, I can implement another validation style whenever I want. The only thing what components need to know about validation error is:

It’s super simple and works for me, but sure we can put additional complexity inside anytime later :-) With custom ValidationError, we can distinguish whether we can handle the error, or whether it should be propagated.

Long story short, validation in Este is:

  • modular (just tiny functions and helpers)
  • universal (the same validation in the browser, React Native, wherever)
  • stable (no breaking changes since I wrote it)
  • localized with react-intl

The problem with validation libraries nowadays is they mix two separated concerns: The validation process itself and the validation result UI projection. These things must be separated. It’s the single responsibility principle violation to mix these concerns.

The Moral

The best validation library is the myth. What we really need is validation primitives like validation rules, focus helpers, custom ValidationError, etc.

What we really don’t need is another validation abstraction replacing our application logic. Try to limit abstractions as much as you can. Duplication is far cheaper than the wrong abstraction.

Favour building small things, they tend to be stable. For example, check Este fields and Este validation. It just works. No crazy rewriting, no brutal API changes, no magic. You can learn how to use it just from reading the code.

The deterrent example of over monolithic code is erikras/redux-form. I can’t imagine anyone is using it without constant app rewriting. Just take a look how many times API has been changed and the endless list of various issues. That’s the result of mixing concerns aka violating single responsibility principle.

--

--