6. New helpers in 1.10.0
Throwable->map , ex-triage , ex-str
clojure.main/repl with :caught option
https://clojure.org/reference/repl_and_main
7. New ex-data in 1.10.0
:clojure.error/phase - phase indicator
:clojure.error/source - le name (no path)
:clojure.error/line - integer line number
:clojure.error/column - integer column number
:clojure.error/symbol - symbol being
expanded/compiled/invoked
:clojure.error/class - cause exception symbol
:clojure.error/cause - cause exception message
:clojure.error/spec - explain-data for a spec error
20. Metosin Public Corner
Integrating spell-spec with spec-tools for closed
validation of spec'd con gurations (with
@bhauman-grade error reporting)
metosin/reitit is a playground of joyful things,
including data, performance and... error messages!
Some Schema too?
23. Fail Fast
During static analysis (e.g. linter)
At compile-time (macros, defs)
At creation-time
At development-time (schema/spec annos)
At runtime ( )
24. On Component 1/2
Clean separation of creation and request-time
Support declarative validation at creation-time
Correct Initialization, Fast Runtime
(defn coerce-request-interceptor
"Interceptor for pluggable request coercion.
Expects a :coercion of type `reitit.coercion/Coercion`
and :parameters, otherwise does not mount."
[]
{:name ::coerce-request
:spec ::rs/parameters
:compile (fn [{:keys [coercion parameters]} opts]
...)})
25. On Component 2/2
Schema is great at validating function args:
clojure.spec has fdef and s/assert
(require '[schema.core :as s])
(s/defn ^:always-validate interceptor-x
[opts :- {:string? s/Bool}]
...)
(coerce-request-interceptor {})
; Syntax error (ExceptionInfo) compiling at (test.cljc:150:1).
; Input to interceptor-x does not match schema:
;
; [(named {:string? missing-required-key} opts)]
26. On Error
No formatting here, just emit a unique id for the
error and all the needed info for print the error:
(when-let [problems (validate-route-data routes spec)]
(exception/fail!
::invalid-route-data
{:problems problems}))
27. On (Router) Creation
Before there is a way to hook a custom exception
handler into a running REPL, we just catch the
exceptions ourself on the public api and use a
con gured formatter for the errors:
(defn router [raw-routes opts]
(try
...
(catch #?(:clj Exception, :cljs js/Error) e
(throw ((get opts :exception identity) e)))))
35. Challenges
clojure.spec is open by design
enables growth (and typos!)
clojure.spec is macros (Spec2 adds functions)
clojure.spec doesn't support rt-transformations
Spec2 is xing some of the things, WIP
(Remember Schema, anyone?)
36. Batteries to clojure.spec ?
Ability to deep-merge (map) specs
Ability to close (map) specs
s/select in Spec2 looks promising (WIP, TBD):
(s/select
::user
[::first ::last ::addr
{::addr [::street ::city ::state ::zip]}])
37. While waiting
spec-tools.spell will have functions to close specs
Work nicely with data-specs (DEMO)
Might work with normal specs using Coercion
https://cljdoc.org/d/metosin/spec-
tools/0.9.1/doc/spec-coercion
Will integrate to reitit if that ever works
st/defn to help validating component options?
38.
39. Final Words
Clojure is a Dynamic language -> Fail Fast(!!!)
Fast linters coming ( joker & clj-kondo )
Ongoing work to make reitit awesome
Fipp, Expound, spell-spec & spec-tools
Community should build a kick-ass error
formatter & rules for Clojure, Made in ?
Join #reitit & #clj-commons in Slack
join@metosin.