Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structural correctness while refactoring in Clojure

Tags:

clojure

If my project is using "person" maps with the shape {:firstName :lastName :address}, and I want to change that shape to {:name {:firstName :lastName} :address}, what can I do to help ensure that I've made the corresponding changes everywhere these objects are used?

In Java, it's straightforward as anywhere I still have person.firstName would issue a compile error. In Clojure I might not even get a runtime error, but just bad data saved to the server. I assume it's not possible to guarantee correctness, but what is there other than fine-toothed-combs?

like image 561
lobsterism Avatar asked May 29 '15 13:05

lobsterism


2 Answers

Clojure has libraries that provide data definition and validation. For example, you could use https://github.com/Prismatic/schema

Regarding the difficulty of compile-time vs. runtime errors...well, that issue is not unique to Clojure. To quote John Carmack: "The challenge of lisp is getting your program to run, the challenge of Haskell is getting it to compile."

like image 113
noahlz Avatar answered Nov 05 '22 19:11

noahlz


I agree with @noahlz - if you want to be really sure then, you'll have to use a library like the one he's suggested. Large refactoring with maps can be a problem, it's true.

Having said that, you could slightly improve your chances in your case if you used a Record with its constructor function to create your person (and still retain the good things about maps):

(defrecord Person [name address])

;; Okay. No problem
(def scott (->Person {:firstname "Scott" :lastname "Lowe"}
                     "23 Hope Street, Edinburgh"))
;; But then...
(def scott (->Person "Scott"
                     "Lowe"
                     "23 Hope Street, Edinburgh"))
;; Boom!
ArityException Wrong number of args (3) passed to: user/eval990/->Person--1005

Now this example catches the issue at runtime, and it will obviously only help in some simple cases. But static analysis tools will also pick up on this bug at development time (for example: Clojure plugins like Cursive available for IntelliJ).

like image 29
Scott Avatar answered Nov 05 '22 18:11

Scott