2016-06-21 3 views
39

그래서, 나는 더 깊은 곳에서 다이빙을하고 있습니다. Clojure.Spec.Clojure의 스펙을 어디에 넣을 것인가?

내가 우연히 발견 한 한 가지는 인 입니다. 주요 네임 스페이스에 요구됩니다 하나 개의 큰 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

나는 일반적으로 스펙을 설명하는 네임 스페이스와 함께 고유 한 네임 스페이스에 넣습니다. 일관된 명명 규칙을 사용하는 한 명명 된 이름은 특히 중요하지 않습니다. 예를 들어 내 코드가 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가 필요하다면 스펙 ns를 요구할 수 없기 때문에 구문 분석에 사용하기 위해로드되는 스펙에 의존 할 수 없다는 점에서 좋은 지적입니다. 그러므로 ns가없는'(load "my/app/foo_specs")/(in-ns 'my.app.foo) ('[clojure.spec : as s] '가 필요합니다)가 바람직한 패턴 일 것입니다. 가독성을 위해 별도의 파일에 사양을 넣으십시오. –

+1

좋은 지적입니다 ... 구현 네임 스페이스가 스펙 네임 스페이스에 종속되기를 원하는 상황이 있습니다. 이는 스펙 ns *가 impl ns에 종속 될 수 없음을 의미합니다. 현재이 문제를 해결할 좋은 방법이 없습니다. 사양에 정규화 된 네임 스페이스 이름을 입력하는 것이 가장 좋습니다. 다행히도 아직로드/필요하지 않은 네임 스페이스를 별칭으로 지정할 수있는 몇 가지 변경 사항이 있으므로이 문제를 깔끔하게 해결해야합니다. – levand

6

사용 사례에 따라 다른 고려 사항 - 기본 코드와 함께 사양을 지정하면 Clojure 1.9 클라이언트에 코드 사용이 제한되며 원하는대로 또는 그렇지 않을 수도 있습니다. @levand와 마찬가지로 각 코드 네임 스페이스에 대한 병렬 네임 스페이스를 권장합니다.

10

제 생각에는 스펙은 코드와 동일한 ns에 있어야합니다.

나의 주요 고려 사항은 나의 개인 철학이며, 기술적으로 잘 작동합니다. 필자의 철학은 함수의 spec이 의 일부분이라는 것입니다. 그것은 여분의 것이 아닙니다. 그것은 입니다. OP에는 "two concern"이 없습니다. 실제로, 그것은 기능이란 무엇입니까? 정확성 측면에서 : 누가 구현에 신경을 씁니까? 당신이 defn에 쓴 것을 누가 신경 쓰나요? 누가 그 식별자에 신경을 쓴다? 누가 약 을 걱정하지만 사양?
clojure.spec이 나중에 나왔을뿐 아니라 대부분의 언어가 원하면 필요하지 않더라도 필수적인 사양으로 사용할 수 없으므로 이상하다고 생각합니다. 가까운 곳에있는 코드 (대개 코드의 테스트)는 대개 싫어합니다. , 물론 그것은 이상하게 보입니다. 그러나 약간 생각을해라. 그러면 내가했던 것처럼 결론에 도달 할지도 모른다 (또는, 그렇지 않을지도 모른다,이 부분은 독단적이다).

  1. 그것은 당신의 코드를 클러 :

    난 당신이 같은 NS의 사양을 원하지 않을 것이다 이유에 대해 생각할 수있는 유일한 이유는 두 가지 이유가 있습니다.

  2. Clojure 버전 1.9.0 이전을 지원하려고합니다.

첫 번째 이유는 음, 다시 말하지만, 나는 그것이 여러분의 기능에 없어서는 안될 부분이라고 생각합니다. 만약 당신이 정말로 너무 많은 것을 알게된다면, 스펙에 관계없이 당신의 NS가 너무 어수선하게 될 것 같은 나의 충고는 당신이 그것을 나눌 수 있는지 보아라.

두 번째 이유는 진정한 관심이 있다면 clojure.spec ns를 사용할 수 있는지 코드를 체크하고, 그렇지 않다면 NOP 인 함수/매크로를 사용하여 이름을 숨길 수 있습니다. 또 다른 옵션은 clojure-future-spec을 사용하는 것이지만 나 자신을 시도하지 않았으므로 그것이 얼마나 잘 작동하는지 알지 못합니다.

기술적으로 잘 작동하는 또 다른 방법은 때로는 다른 네임 스페이스로 처리 할 수없는 주기적 종속성이 있다는 것입니다. 스펙이 코드에 의존하고 (함수 스펙의 경우) 코드가 스펙 분석에 따라 달라집니다 (이 내용은 question 참조).

+2

나는 이것에 동의한다고 생각한다. 사양에 대한 이론적 근거 문서는 문서를 그 중 하나의 측면으로 언급합니다. 그들이 지정한 코드에서 멀리 떨어지게되면 그 이익을 잃게됩니다. –