Use `clojure.spec` to describe function shapes and enable instrumentation where it improves development feedback.
spec(clojure.spec.alpha): A Clojure library for describing the shape of values and functions, generating sample data, and instrumenting code during development and testing.
Using spec for function contracts is one of the clearest ways to make expectations explicit in a data-oriented Clojure system. But it also needs realistic framing: spec is not a static type system, and instrumentation is not something you blindly leave enabled everywhere in production.
The value comes from writing clearer contracts and getting better feedback in development, tests, and exploratory work.
Function specs help describe:
That makes them useful for:
1(ns app.discount
2 (:require [clojure.spec.alpha :as s]
3 [clojure.spec.test.alpha :as stest]))
4
5(defn apply-discount [amount percent]
6 (* amount (- 1 percent)))
7
8(s/fdef apply-discount
9 :args (s/cat :amount pos-number?
10 :percent (s/and number? #(<= 0 % 1)))
11 :ret number?)
This already gives you more than prose comments do:
Instrumentation wraps function calls so spec checks whether the arguments satisfy the declared contract.
That is especially useful when:
It is less useful when developers start treating it as a full replacement for careful domain modeling or targeted validation logic.
spec Does Not Give YouIt is important to be precise:
This keeps the lesson grounded. spec is a powerful descriptive and checking tool, but it still sits inside a broader design discipline.
spec is especially helpful at boundaries:
It is often less valuable on every tiny private helper. Over-specifying everything can produce a lot of maintenance noise without proportionate clarity.
The first mistake is treating function specs as if they were free documentation. If the spec is vague or stale, it becomes another source of confusion.
The second mistake is instrumenting everything without considering overhead or developer workflow.
The third mistake is using spec where a smaller local predicate or explicit validation function would be clearer.
Ask these when reviewing spec usage:
spec clarifying the model, or compensating for a weak one?Good spec usage sharpens contracts. Bad spec usage adds ceremony without improving understanding.