Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure的规格放在哪里?_Clojure_Clojure.spec - Fatal编程技术网

Clojure的规格放在哪里?

Clojure的规格放在哪里?,clojure,clojure.spec,Clojure,Clojure.spec,因此,我正越来越深入地研究Clojure.Spec 我偶然发现的一件事是,在哪里放置我的规格。我认为有三种选择: 全局规范文件 在大多数示例中,我在网上发现,在主命名空间中需要一个大的spec.clj文件。它具有所有“数据类型”和功能的所有(s/def)和(s/fdef) 赞成者: 一个文件来管理他们所有人 相反: 这个文件可能很大 违反单一责任原则 生产名称空间中的规范 您可以将(s/def)和(s/fdef)放在生产代码旁边。因此,实现和规范在同一名称空间中共存 赞成者: 实施和规

因此,我正越来越深入地研究Clojure.Spec

我偶然发现的一件事是,在哪里放置我的规格。我认为有三种选择:

全局规范文件 在大多数示例中,我在网上发现,在主命名空间中需要一个大的
spec.clj
文件。它具有所有“数据类型”和功能的所有
(s/def)
(s/fdef)

赞成者:

  • 一个文件来管理他们所有人
相反:

  • 这个文件可能很大
  • 违反单一责任原则
生产名称空间中的规范 您可以将
(s/def)
(s/fdef)
放在生产代码旁边。因此,实现和规范在同一名称空间中共存

赞成者:

  • 实施和规范的合用地
  • 一个名称空间-一个问题
相反:

  • 生产代码可能会变得混乱
  • 一个名称空间-两个关注点
专用规范命名空间结构 然后我想,也许规范是第三种代码(仅次于生产和测试)。因此,也许它们应该拥有自己的名称空间结构,如下所示:

├─ src
│  └─ package
│     ├─ a.clj
│     └─ b.clj
├─ test
│  └─ package
│     ├─ a_test.clj
│     └─ b_test.clj
└─ spec
   └─ package
      ├─ a_spec.clj
      └─ b_spec.clj
赞成者:

  • 规范专用(但相关)名称空间
相反:

  • 您必须源代码并需要正确的名称空间

谁对其中一种方法有经验?
还有其他选择吗?

您对不同的选项有何看法?

我通常将规范放在它们自己的名称空间中,与它们所描述的名称空间一起。它们的名称并不特别重要,只要它们使用一致的命名约定。例如,如果我的代码在
my.app.foo
中,我将把规范放在
my.app.foo.specs

规范键名称最好位于代码的命名空间中,而不是规范的命名空间中。通过在关键字上使用命名空间别名,这仍然很容易做到:

(ns my.app.foo.specs
  (:require [my.app.foo :as f]))

(s/def ::f/name string?)
我不想把所有东西都放在一个巨大的规范名称空间中(这真是一场噩梦)。虽然我当然可以把它们放在同一个文件中的规范代码旁边,但这会损害可读性


您可以将所有规范名称空间放在一个单独的源路径中,但这样做并没有真正的好处,除非您希望分发代码而不是规范,反之亦然。。。很难想象会是什么情况。

另一个考虑因素取决于您的用例-将规范与主代码放在一起会限制您的代码用于Clojure 1.9客户端,这可能是您想要的,也可能不是您想要的。像@levand一样,我建议为每个代码名称空间使用一个并行名称空间。

我认为规范应该与代码使用相同的ns

我主要考虑的是我的个人哲学,从技术上讲,它很有效。我的理念是,函数的规范是它不可分割的一部分。这不是额外的事情。这绝对不是OP中提到的“两个关注点”。实际上,这是函数的含义,因为就正确性而言:谁关心实现?谁在乎你在
defn
中写了什么?谁在乎标识符?除了规格,谁还在乎别的呢?
我认为这很奇怪,因为不仅clojure.spec是后来才出现的,而且大多数语言都不允许将spec作为一个完整的东西,即使您希望它成为一个完整的东西,而且任何相近的东西(可能是代码中的测试)通常都是不受欢迎的,所以它当然看起来很奇怪。但是想一想,你可能会像我一样得出结论(或者你可能不会,这一部分是自以为是的)

我能想到的唯一好的原因是,为什么您不希望在相同的ns中使用规范,这有两个原因:

  • 它会弄乱你的代码
  • 您希望支持Clojure 1.9.0之前的Clojure版本
  • 至于第一个原因,好吧,我想这是你函数的一个组成部分。如果你发现它真的太多了,我的建议是,如果你的ns太乱了,不管规格如何:看看你能不能把它分开

    至于第二个原因,如果您真的关心,您可以在clojure.spec ns可用的情况下签入代码,如果不可用,则使用NOP函数/宏对名称进行阴影处理。另一个选择是使用,但我自己还没有尝试过,所以我不知道它的效果如何


    另一种技术上可行的方法是,有时存在循环依赖,您无法处理不同的名称空间,例如,当您的规范依赖于您的代码(对于函数规范)而您的代码依赖于您的规范进行解析时(参见此).

    你的建议是什么?@levand Sam Estep在他的问题中提出了一个很好的观点,即你不能依赖加载的规范来使用它进行解析,因为如果规范已经需要你的ns,你就不能要求它。因此,如果您希望规范位于单独的文件中以确保可读性,那么最好使用不带单独ns的
    (加载“my/app/foo_specs”)/(在ns'my.app.foo中)(要求'[clojure.spec:as s])
    。。。在某些情况下,您希望实现名称空间依赖于规范名称空间,这意味着您的规范ns不能依赖于impl ns。目前,还没有解决这个问题的好方法-最好是在规范中键入完全限定的命名空间名称。幸运的是,工作中有一些更改,允许您别名尚未加载/需要的命名空间,我同意在同一个文件中定义规范会带来可读性成本,但在主文件之外的命名空间中为该命名空间定义内容会带来不同的,甚至更糟糕的可读性成本。名称在主文件中无需任何
    require
    use
    即可神奇地使用。一个标准化的做法是一直使用规范来做这件事是可以的,但是一个局外人