Clojure.spec - 为什么它有用,什么时候使用它

时间:2016-12-11 16:33:03

标签: clojure clojure.spec

我最近看过Rich Hickeys talk at Cojure Conj 2016虽然这很有意思,但我并没有真正理解clojure.spec或者你使用它时的观点。似乎大多数想法,例如符合,有效等,已经在Clojure中具有类似的功能。

我现在只学习了大约3个月的clojure,所以这可能是由于缺乏编程/ Clojure经验。

clojure.spec和cljs.spec的工作方式与Clojure和Cljs类似,尽管它们不是100%相同,但它们基于相同的基本原则。

2 个答案:

答案 0 :(得分:9)

  • 您是否厌倦了记录您的程序?
  • 弥补更多测试的前景是否导致拖延?
  • 当老板说“测试报道”时,你是否因恐惧而畏缩?
  • 您是否忘记了数据名称的含义?

为了顺利表达硬性规格,您需要 Clojure.Spec

Clojure.spec为您提供统一的记录,指定和自动测试程序以及验证实时数据的方法。

它几乎窃取了每一个想法。而且它对你自己无能为力。

但在我的 - 几乎不知情的意见 - 中,它改变了规范的经济性,使其在做得好的同时值得。一个改变游戏规则的人? - 很可能。

答案 1 :(得分:5)

在上周的clojure / conj会议上,可能有一半的演讲以某种方式展示了规格,而且它甚至还没有出现。 spec是clojure的 主要 功能;它就在这里,它很强大。

作为其力量的一个例子,采取静态类型检查,被许多人称为一种安全网,并且是许多编程语言的定义特征。它非常有限,因为它只在编译时很好,而且它只检查类型。另一方面,spec验证并符合args的任何谓词(不仅仅是类型),返回,还可以验证两者之间的 关系 。所有这些都在函数代码的外部,将函数的逻辑与验证和代码文档混合在一起。

关于工作流程:

关系检查的好处的一个原型示例,而不仅仅是类型检查,是一个计算字符串子串的函数。类型检查可确保(subs s start end) s中的start为字符串,endstart为整数。但是,必须在函数内进行其他检查,以确保endend为正整数,start大于(s/fdef clojure.core/subs :args (s/and (s/cat :s string? :start nat-int? :end (s/? nat-int?)) (fn [{:keys [s start end]}] (if end (<= 0 start end (count s)) (<= 0 start (count s))))) :ret string? :fn (fn [{{:keys [s start end]} :args, substring :ret}] (and (if end (= (- end start) (count substring)) (= (- (count s) start) (count substring))) (<= (count substring) (count s))))) ,并且生成的子字符串为否大于原始字符串。例如,所有这些事情都可以指出(如果其中一些有点多余或甚至可能不准确,请原谅我):

args

使用符合上述(s/exercise-fn `subs) 规范的示例数据调用该函数:

:args

或者运行1000次测试(这可能会失败几次,但是继续运行并且它会起作用 - 这是由于内置生成器无法满足(stest/check `subs) 谓词的第二部分;如果需要,可以编写自定义生成器):

subs

或者,想要查看您的应用是否在实时运行时拨打(stest/instrument `subs) 无效的电话?只需运行此命令,如果调用该函数并且未满足规范,您将获得规范异常:

(-> (stest/enumerate-namespace 'user) stest/check)

我们尚未将其整合到我们的工作流程中,并且因为它仍处于alpha状态而无法生产,但第一个目标是编写规范。我将它们放在相同的命名空间中,但目前放在不同的文件中。

我预见到我们的工作流程是使用此功能(在clojure规范指南中找到)运行规范功能的测试:

s/conform

然后,打开所有功能的仪表,并按照我们通常会测试的负载运行应用程序,并确保&#34;真实世界&#34;数据有效。

您还可以使用s/valid来解析函数本身中的复杂数据,或者使用{{1}}作为运行函数的前置条件和后置条件。我不太热衷于此,因为它是生产系统中的开销,但这是一种可能性。

天空是极限,我们只是划伤了表面!在接下来的几个月和几年里,有一些很酷的东西出现在规范中!