This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-09-06
Channels
- # announcements (3)
- # beginners (83)
- # calva (11)
- # cider (24)
- # cljdoc (2)
- # cljs-dev (1)
- # clojure (216)
- # clojure-berlin (1)
- # clojure-dev (18)
- # clojure-europe (8)
- # clojure-italy (5)
- # clojure-losangeles (2)
- # clojure-nl (4)
- # clojure-spec (34)
- # clojure-uk (75)
- # clojuredesign-podcast (12)
- # clojurescript (33)
- # clojutre (13)
- # community-development (1)
- # core-async (38)
- # cursive (19)
- # datomic (28)
- # duct (3)
- # emacs (1)
- # events (5)
- # figwheel-main (3)
- # fulcro (93)
- # kaocha (20)
- # lambdaisland (2)
- # off-topic (40)
- # pathom (17)
- # pedestal (8)
- # quil (1)
- # re-frame (14)
- # reitit (19)
- # shadow-cljs (34)
- # sql (8)
- # tools-deps (6)
- # vim (1)
- # xtdb (8)
- # yada (18)
it seems like you want something like: https://cljdoc.org/d/metosin/spec-tools/0.10.0/doc/data-specs
the fundamental diff between “complex = verbose” and “complex = a few things glommed together” is the former can turn to the latter, but the inverse is not true 🙂
>A complex system that works is invariably found to have evolved from a simple system that worked. A complex system designed from scratch never works and cannot be patched up to make it work. You have to start over, beginning with a working simple system.
I think this quote resonates with my enjoyment of writing Clojure and how easy it is to compose little solutions into big ones
but I’m continuously surprised at how much simpler thing get if you design them to be run from the REPL
yeah, I felt the same way with other ML-like functional/immutable languages before Clojure. OCaml/F# is nice, but Clojure is more enjoyable for me
Thats exactly what im looking for! Thanks, @potetm i was about to spin my own solution and dig into how to create custom spec validators for that (might still do, but only for the learning experience)
As i said, i fully agree that well broken down Systems are easier to reason about and work with. But originally coming from Java, and then going to expressive languages like kotlin, haskell, Rust (and now clojure), ive really started to value expressivity. I like to talk in my Code like i would talk to a Person. I like to describe what im trying to achieve, how different Things relate to each other, and what Things represent, and i like to Use expressive Tools to achieve that. The Same way that a for Loop isnt really the best way to describe the relation of a list of numbers to the Same list with every number squared, i feel about using spec. Defining Things that Look and feel like Domain Model/ more complex stuff for simple validations works, but it doesnt Show what i want to express. In my analogy, i want to actually express (map #(* % %) my-list)
. Simmiarly, in my spec i dont want to say "the arg title
is of type ::title
, where ::title
is a String." but just "this function takes a String
that will be displayed as the tite."
It's not so much about complexity in a Code sense, but just about expressivity, readability and also just typing and reading time. And yes. Lines of Code do matter. Otherwise lisps would put their closing parens on New lines
One thing that I really disliked about spec is that it encouraged creating names where none would suffice.
as a datapoint, in ~2 years I specced like 5 functions, and am really amused how much attention s/fdef and instrument get
i spec pretty much all my functions, but mainly because its the only way to get immediately helpful error messages. especially in clojurescript, sometimes the errors really dont help. i just get some errors in some G_1235
generated function name and have no idea what happened.
also, I'd say a big help for speccing all functions are the defn-spec
feature of orchestra or things like ds/defn
from defn-spec
that lets you add specs directly into the function signature
there are few functions which benefit from gen-testing. which somewhat rhymes with "you really need just few refs per project". but other things too: - read/write overhead, - maintenance, - "spec pushes you to have global names where none suffice", - project size/complexity is not that out of control, so "specing 100% of the code is the only way out" - wide contact surface with mutable DOM in cljs - etc.
I prefer to understand what system is doing, when I can afford it. Admittedly, you are not always in position to have this as an option (project/team size, domain complexity, etc.)
some analogies would be: - turning off code highlighter to pay more attention to code. - writing code w/o autocomplete/autosuggest to know better whats there in the project. these things keep your mind in a tonus
and more stuff you will know you will have to keep track of, more reluctant you will be to let bloat slide in.
I’ve honestly had very little urge to use spec at all. Though I’ve spent the last 9mo on a novel thing, so nothing is solidified to the point where I want to invest in pouring some concrete.
Actually, there are a fair number of unit tests, and IMO even those aren’t worth enough to bother.
from spec hq: agree
From our code base (World Singles Networks):
Clojure build/config 52 files 936 total loc
Clojure source 299 files 70282 total loc,
3207 fns, 662 of which are private,
441 vars, 29 macros, 62 atoms,
602 specs, 21 function specs.
Clojure tests 330 files 19116 total loc,
4 specs, 1 function specs.
We were an early adopter of Spec in production code (`conform`/`valid?`/`explain-data`) but we mostly spec data rather than functions, as you can see above.@seancorfield are you using valid?
and conform
in production paths or in tests or their own specs.clj file? that is to say, are you paying the performance costs at runtime for the specs you do have?
@gerred We use conform
and invalid?
mostly, then explain-data
to drive heuristics for turning spec errors into codes/messages we can return to client apps. But, yes, that's all production path code.
A lot of our input form data and most of our API input parameters are run through Spec. We have conforming Specs that accept strings and will conform them to simple numbers, dates, Booleans etc. Something that Alex frowns on 🙂 but it has worked exceptionally well for us.
We usually write the specs to accept either the native type we want or a string that can be parsed/coerced/conformed to that native type, and our specs have generators that produce strings (we mostly generate the underlying spec and then fmap
str
over that).