Calling s/valid? will tell me if the data is valid *if it has been conformed*. 
But what if it hasn't? Can I use the data? Is it "valid" according to the spec 
I wrote?

If your spec includes coercions, you have inherently made the “is valid?” 
question include the coercion. Your ::test-spec accepts anything that can be 
used as the argument to keyword. This is why Cognitect keep recommending people 
do not do this. And I’m jumping into this thread because we _do_ include 
coercions in some of our specs at work… we’ve been heavy users of spec since 
the early alpha builds and we ran those alphas in production. But we are very 
conscious about our specs that coerce: we know and accept that they will work 
on “any string that can be coerced to <desired type>”. If we specifically want 
to check whether some data is <desired type> we use a different spec.

We do this for parameters in our REST API, for long, double, Boolean, date, etc 
– we have two specs for each: one that is a spec for the target type in the 
domain model (which in these cases is just defined as the appropriate built-in 
predicate), and one that is a spec for the API level (which accepts either the 
target type or a string that can be coerced to the target type). Then we use 
the appropriate spec at the appropriate “level” in our application.

Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"If you're not annoying somebody, you're not really alive."
-- Margaret Atwood

________________________________
From: clojure@googlegroups.com <clojure@googlegroups.com> on behalf of Jan 
Rychter <jrych...@gmail.com>
Sent: Tuesday, February 20, 2018 2:41:38 AM
To: Clojure
Subject: s/valid? does not tell me if the data is valid as supplied

I've been using spec for a while now, in a reasonably large code base (>30k 
lines of Clojure and ClojureScript) and there is an issue that bit me several 
times.

I use conformers for coercing data that is *almost* what I need, usually when 
reading from JSON (RethinkDB). Common conformers are keyword and set. And it 
works really well, except for one problem: there is no way to know if data has 
been conformed or not.

Calling s/valid? will tell me if the data is valid *if it has been conformed*. 
But what if it hasn't? Can I use the data? Is it "valid" according to the spec 
I wrote?

This is a very real problem: I've spent considerable time chasing bugs where 
there was a code path which did not call s/conform. The data passed all 
validations done with valid? and the bug manifested itself far down the road, 
where something expected a keyword instead of a string, or a set instead of a 
vector.

Here is a specific minimal example demonstrating what I'm talking about:

(ns spectest
  (:require [clojure.spec.alpha :as s]))

(s/def ::test-spec (s/and (s/conformer keyword) keyword?))

(s/conform ::test-spec "a") ;; :a
(s/valid? ::test-spec "a") ;; true

I expected the last valid? to return false, because my code does not expect a 
string, it expects a keyword, according to the spec.

I might be missing something, but I would much rather see valid? tell me if the 
data is valid for use (as supplied) and have a separate valid-when-conformed? 
which tells me if the data is, well, valid when conformed. It seems to me that 
the current valid? that does two things is confusing and not very useful for 
contracts.

At the very least I'd really like to see a function that tells me if the data 
is valid *as supplied*, as this is the function that I'd want to use when 
enforcing contracts everywhere in my code.

Alternatively, I could stop using conformers altogether, and write explicit 
data conversion functions. That might not be a bad idea, but it seems other 
people started using conformers, too, so eventually I'll hit the same problem 
again.

--J.


--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to 
clojure+unsubscr...@googlegroups.com<mailto:clojure+unsubscr...@googlegroups.com>.
For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to