在Clojure中重构时的结构正确性

时间:2015-05-29 13:55:09

标签: clojure

如果我的项目正在使用" person"形状为{:firstName :lastName :address}的地图,我希望将该形状更改为{:name {:firstName :lastName} :address},我该怎么做才能确保我在使用这些对象的地方做出相应的更改?

在Java中,它很简单,因为我仍然有person.firstName会发出编译错误。在Clojure中,我可能甚至没有得到运行时错误,但只是将错误数据保存到服务器。我认为保证正确性是不可能的,但除了细齿梳之外还有什么呢?

2 个答案:

答案 0 :(得分:6)

Clojure拥有提供数据定义和验证的库。例如,您可以使用https://github.com/Prismatic/schema

关于编译时与运行时错误的难度......好吧,这个问题并不是Clojure特有的。引用John Carmack:" lisp的挑战是让你的程序运行,Haskell的挑战是让它编译。"

答案 1 :(得分:4)

我同意@noahlz - 如果你真的很确定,那么你必须使用像他建议的那样的库。使用地图的大型重构可能是一个问题,这是真的。

话虽如此,如果你使用带有构造函数的Record来创建你的person(并且仍保留关于地图的好东西),你可以略微提高你的机会:

(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

现在这个例子在运行时捕获了这个问题,它显然只会在一些简单的情况下起作用。但是静态分析工具也会在开发时发现这个bug(例如:像Cursive这样的Clojure插件可用于IntelliJ)。