所以,我越来越深入地进入 Clojure.Spec 。
我偶然发现的一件事是,在哪里放置我的规格。我看到三个选项:
在大多数示例中,我发现在线,有一个大的spec.clj
文件,在主命名空间中需要。它包含所有"数据类型的所有(s/def)
和(s/fdef)
"和功能。
亲:
魂斗罗:
您可以将(s/def)
和(s/fdef)
放在生产代码旁边。因此,实现和规范在同一名称空间中共存。
临:
魂斗罗:
然后我想,也许Specs是第三种代码(在生产和测试之后)。所以也许他们应该拥有自己的名称空间结构,如下所示:
├─ src
│ └─ package
│ ├─ a.clj
│ └─ b.clj
├─ test
│ └─ package
│ ├─ a_test.clj
│ └─ b_test.clj
└─ spec
└─ package
├─ a_spec.clj
└─ b_spec.clj
临:
魂斗罗:
谁有使用其中一种方法的经验?
还有其他选择吗?
您如何看待不同的选择?
答案 0 :(得分:20)
我通常将specs放在他们自己的命名空间中,以及他们描述的命名空间。只要它们使用一些一致的命名约定,它们的命名并不特别重要。例如,如果我的代码位于my.app.foo
,我会将规范放在my.app.foo.specs
中。
规范密钥名称最好位于代码的名称空间中,但不是规范的名称空间。通过在关键字上使用命名空间别名,这仍然很容易做到:
(ns my.app.foo.specs
(:require [my.app.foo :as f]))
(s/def ::f/name string?)
我不会试图将所有内容放在一个巨大的规范名称空间中(这真是一场噩梦。)虽然我当然可以将它们放在同一文件中的规范代码旁边,这会伤害IMO的可读性。
你可以将所有规范名称空间放在一个单独的源路径中,但这样做没有任何实际好处,除非您处于要分发代码而不是规范或反之亦然......很难想象那会是什么。
答案 1 :(得分:14)
在我看来,规格应与代码在同一个ns中。
我的主要考虑因素是我的个人理念,从技术上讲,它的效果很好。我的理念是函数的规范是整数的一部分。这不是一件额外的事情。它的绝对不是"两个问题"如在OP中。实际上,它的功能是什么,因为在正确性方面:谁在乎实施?谁在乎你在defn
写的内容?谁在乎标识符?谁关心任何事情但规范?
我认为这很奇怪,因为不仅clojure.spec后来出现,大多数语言也不会让你将规格作为一个整体的东西,即使你想要它,并且任何接近(在代码中测试)通常都是不满意,所以当然看起来很奇怪。但是要考虑一下,你可能会像我一样得出结论(或者你可能没有,这部分是固执己见的。)
我能想到为什么你不想在相同的ns中使用规格的唯一理由是这两个原因:
至于第一个原因,嗯,我认为它是你职能中不可或缺的一部分。如果你发现它确实太多了,我的建议就像你的ns太乱了一样,无论规格如何:看看你是否可以拆分它。
至于第二个原因,如果你真正关心,你可以检查代码是否可用clojure.spec ns,如果没有,则使用NOP的函数/宏来遮蔽名称。另一种选择是使用clojure-future-spec,但我自己没有尝试过,所以我不知道它的效果如何。
另一种在技术上运作良好的方法是,有时存在一个循环依赖,你不能用不同的命名空间来处理,例如:当您的规范依赖于您的代码(对于函数规范)而您的代码取决于您的解析规范(请参阅此question)。
答案 2 :(得分:7)
另一个考虑因素取决于您的使用案例 - 将规范与主代码放在一起限制了您的代码使用Clojure 1.9客户端,这可能是您想要的,也可能不是。和@levand一样,我建议为每个代码名称空间使用并行命名空间。