2016-06-21 58 views
39

所以,我深入潛入Clojure.Spec在哪裏投放Clojure.Spec?

我偶然發現的一件事是,在哪裏把我的規格。我看到三個選項:

全球SPEC文件

在大多數例子中,我發現網上,有一個很大的spec.clj文件時,被在主命名空間要求。它具有所有「數據類型」和功能的所有(s/def)(s/fdef)

臨:

  • 一個文件解決所有問題

魂鬥羅:

  • 此文件可以是大
  • 單Responsibliy原理侵犯?

規格生產的命名空間

你可以把你的(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 

臨:

  • 專用(但相關)的命名空間規格

魂鬥羅:

  • 您必須提供並要求正確的名稱空間

誰對這些方法有經驗?
還有其他的選擇嗎?
你對不同的選擇有什麼看法?

回答

14

我通常把specs放在他們自己的命名空間中,並與他們描述的命名空間一起。只要它們使用一些一致的命名約定,它們的名稱並不特別重要。例如,如果我的代碼位於my.app.foo,我將把規格放在my.app.foo.specs

規範鍵名稱最好放在代碼的名稱空間中,但不是規範的名稱空間。這仍然是很容易通過使用關鍵字空間別名做:

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

(s/def ::f/name string?) 

我從試圖把一切都在一個巨大的規範命名空間(什麼是噩夢)雖然我當然可以把他們的權利望而卻步與同一文件中的spec'd代碼一起,會傷害IMO的可讀性。

可以把所有規格的命名空間在一個單獨的源路徑,但除非你是在一個情況下,你要分發的代碼,但不規範或反之亦然沒有真正的好處這樣做..很難想象那會是什麼。

+5

什麼是你的[使用解構規範時,他們是在一個單獨的命名空間]建議(http://stackoverflow.com/q/38024650/5044950)? –

+1

@levand Sam Estep在他的問題中提出了一個很好的觀點,即你不能依賴一個被加載的規範來使​​用它進行解析,因爲如果規範已經需要你的ns,你就不需要該規範。所以可能是一個'(加載「my/app/foo_specs」)/(in-ns'my.app.foo)(require'[clojure.spec:as s])'沒有單獨的ns將是一個可取的模式,如果你想在可讀性 –

+1

一個單獨的文件,該文件是一個很好的點...規格有您希望您實現命名空間取決於您的規範命名空間,這意味着你的天賦NS *不能*取決於IMPL NS的情況。 目前,爲解決這個沒有什麼好辦法 - 最好是剛打出來的規格完全合格的命名空間的名稱。 幸運的是,在將允許您還沒有被加載/還需要別名命名空間,這應該整齊地解決這一問題的作品一些變化。 – levand

6

取決於您的使用案例的另一個考慮 - 將規範放在您的主代碼旁邊將代碼用於Clojure 1.9客戶端,這可能會或可能不是您想要的。像@levand一樣,我會爲每個代碼命名空間推薦一個並行命名空間。

10

在我看來,規格應該與代碼一樣。

我的主要考慮是我的個人理念,從技術上說它工作得很好。我的理念是功能的規格是積分的一部分。這不是一件額外的事情。這是絕對是不是「OP的兩個問題」。實際上,它的功能就是這樣,因爲就正確性而言:誰在乎實現?誰在乎你在defn上寫了什麼?誰在乎標識符?誰在乎什麼但規格?
我覺得這很奇怪,因爲不僅clojure.spec後來,大多數語言也不會讓你的規範作爲一個整體事物,即使你想要它,並且任何接近(代碼中的測試)通常都會被忽視,所以當然這很奇怪。但請給出一些想法,你可能會像我一樣得出結論(或者你可能不會,這部分是有見地的)。

我能想到的,爲什麼你不希望在同一納秒規格的唯一理由是這兩個原因:

  1. 它雜波您的代碼。
  2. 您希望在Clojure 1.9.0之前支持Clojure版本。

至於第一個原因,好吧,我認爲它是你的函數的一個組成部分。如果你發現它確實太多了,我的建議就會和你的ns無論規範太混亂一樣:看看你是否可以分解它。

至於第二個原因,如果你真正關心,你可以在代碼檢查clojure.spec NS是可用的,如果沒有的話用功能/是NOP宏影的名字。另一種選擇是使用clojure-future-spec,但我沒有嘗試過,所以我不知道它的工作效果如何。

另一種方式這個工程搞好技術上是,有時有,你不能用不同的命名空間,例如處理循環依賴當你的規範取決於你的代碼(對於函數規範),你的代碼取決於你的規範解析(見question)。

+2

我認爲我同意這一點。關於規格的基本原理文章提到文檔是其中的一個方面。如果你把它們放在遠離他們規範的代碼的地方,你就失去了這個好處。 –