> You can self-document things with tests that you cannot with just types
Absolutely.
But I would say that is a different debate. In my case, I don't want to specify the behavior, but only the form, which is the counterpart of a static type, but more flexible (e.g. {} is likened to any structure that behaves like a map - the class doesn't have to be exactly the same).
With my like-function, I don't have to spend too much time specifying what is expected, and I get a lot of bang for the buck.
I want to do just enough so the code stays comprehensible and thus manageable.
(fn parse-int [str] ...) needs no type or unit-test to be understood.
(fn parse-appointment [str] ...) is better understood when it has {:post [(like {:id (UUID.) :name "me" :date (java.util.Date .)} %)]}
And as soon as the function gets really smart, and it's smartness isn't revealed directly by the code, it would be time for either a good comment or a Unit Test (or make the code better so that it does, which is an often forgotten option).
Absolutely. But I would say that is a different debate. In my case, I don't want to specify the behavior, but only the form, which is the counterpart of a static type, but more flexible (e.g. {} is likened to any structure that behaves like a map - the class doesn't have to be exactly the same).
With my like-function, I don't have to spend too much time specifying what is expected, and I get a lot of bang for the buck.
I want to do just enough so the code stays comprehensible and thus manageable.
(fn parse-int [str] ...) needs no type or unit-test to be understood.
(fn parse-appointment [str] ...) is better understood when it has {:post [(like {:id (UUID.) :name "me" :date (java.util.Date .)} %)]}
And as soon as the function gets really smart, and it's smartness isn't revealed directly by the code, it would be time for either a good comment or a Unit Test (or make the code better so that it does, which is an often forgotten option).