At uSwitch we recently built a Clojure/ClojureScript service to handle the specification of questions in online forms and the validation of the user's answers. This combination of client and server side code has been an effective solution to some of the problem we had. In this post we talk about the sweet spot we found for applying Clojure/ClojureScript in combination and the lessons learned along the way.
The high cost of changes across applications and tiers
uSwitch is the number one energy supplier switching service in the UK. As part of the switching process we ask the customer a set of supplier specific questions (things such as credit check consent, previous addresses etc.)
From a maintenance perspective this means questions can be added, removed and updated in one place, (the Clojure/ClojureScript service) without touching the two applications. Only occasionally do we need to change the HTML layers of the applications (when adding a totally new question type for or applying custom styling).
Using Prismatic Schema for validation
We use Prismatic Schema to handle the validation itself. Prismatic Schema allows you to validate clojure data structures and supports both Clojure and ClojureScript.
You use Schema by first declaring a schema data structure:
and then validating a clojure data structure against this schema:
Check out their github page for more details.
Sharing code with CLJX
- We only included libraries of which we were using large parts. At first we included a ClojureScript version of cljs-time to utilise the functions it offered. This added several KB to the final file size so we replaced it with two of our own custom function.
- We only included the namespace we actually used! We experimented with schema.coerce early in the project. In the end we didn’t actually use it, but forgot to remove the require namespace in our code which increased the final file size.
Our macro to optimize maps
These optimisations reduced the minified and gzipped file size from 69KB to to 45KB.
The sweet spot
Overall we are happy with using Clojure/ClojureScript in combination for this use case. It has given us the ability to make changes in a single place that are reflected not just across applications but across both the client and server tiers of those applications.