2017-02-20 6 views
3

clojure.specを使用すると、ネストされたマップの「人間が読める」仕様を定義する方法はありますか?以下は非常によく読まれていません。私の不満は、それが仕様を読むために(ER)硬くなることである clojure.spec人間が読める形ですか?

{:a {:c 1 :d "hello"} :b false}

のように準拠したエンティティの形状は何かであることを考えると

(s/def ::my-domain-entity (s/keys :req-un [:a :b]) 
(s/def :a (s/keys :req-un [:c :d])) 
(s/def :b boolean?) 
(s/def :c number?) 
(s/def :d string?) 

をネストされたマップや深い構造のものがあれば...ファイルを上下にキーを追いかけているので、 "インプレース"宣言ではありません。比較するため

スキーマのようなものが密接に実際のデータ形状を反映し、より読みやすいネストされた構文ができ、:

(m/defschema my-domain-entity {:a {:c sc/number :d sc/string} :b sc/bool})

をこれはclojure.specで行うことができますか?

+1

同様の質問:https://stackoverflow.com/q/42054643 – glts

答えて

3

仕様の価値提案の1つは、実際のスキーマを定義しようとしないことです。エンティティの定義をコンポーネントの定義にバインドしません。 spec rationaleから引用する:

特定構造のため

ほとんどのシステムは、それらのキーによって指定された値の仕様(例えば、マップ内のキーの、オブジェクトのフィールド)キーセットの仕様をconflate。私。そのようなアプローチでは、マップのスキーマは、aキーのタイプがxタイプであり、bキーのタイプがyタイプであると言うことがあります。これは剛性と冗長性の主要な原因です。

Clojureでは、マップを動的に合成、マージ、ビルドすることでパワーを得ています。我々は、オプションおよび部分データ、信頼できない外部ソースによって生成されたデータ、動的クエリなどを日常的に扱います。これらのマップは、同じキーのさまざまなセット、サブセット、交差点および共用体を表し、一般的に同じキーに対して同じセマンティックを持つ必要がありますそれが使用されます。すべてのサブセット/ユニオン/交差点の仕様を定義し、各キーの意味を重複して記述することは、最もダイナミックなケースでは反パターンであり、実行不能である。

したがって、仕様にはこのように特別に設計されているため、この仕様は提供されません。よりダイナミックで、構成可能で、柔軟な仕様のために、スキーマのような定義で人間が読みやすいレベルのものをトレードオフします。

エンティティの定義をコンポーネントの定義から切り離すシステムを使用することの利点を考慮してください。それは不自然だが、(単にタイヤとシャーシを使用して、ここではスペースを節約するためにそれをシンプルに保つ)車を定義することを検討:

(s/def ::car (s/keys :req [::tires ::chassis])) 

我々はそれを一度定義し、我々はそれを私たちが望むタイヤの任意の構成を置くことができます。

(s/def ::tires (s/coll-of ::tire :count 4)) 

(s/def ::tire (s/or :goodyear ::goodyear} 
        :michelin ::michelin)) 

(s/def ::goodyear #{"all-season" "sport" "value"}) 
(s/def ::michelin #{"smooth ride" "sport performance"}) 

(s/def ::chassis #{"family sedan" "sports"}) 

次は異なる構成されているが、すべてが有効な車です:

(s/valid? ::car {::tires ["sport" "sport" "sport" "sport"] 
       ::chassis "sports"}) 

(s/valid? ::car {::tires ["smooth ride" "smooth ride" 
          "smooth ride" "smooth ride"] 
       ::chassis "family sedan"}) 

それはSEとしてコンポーネントを定義するに柔軟性があることを確認するために工夫したが、明らかですコンポーネントがどのような形で構成されているかを区別します。タイヤは独自の仕様を持っており、仕様は自動車を構成するものではありません。もっと冗長ですが、はるかに柔軟です。

+1

この詳細な説明をいただきありがとうございます。私はclojure.spec/guideを読んだことがあります。特に上の引用符で囲まれた段落は、ほんの一握りですが、今まではそれほど沈んでいませんでした。+1 – Clev3r

+0

私の誤解は、私の特定のエンティティの形と関係していたと思います。 '' :: kwd' - > ''述語-fn''のような ''(def :: a string?)''のフラットな地図です。より多様なセットとseqsとkwdのペアを持つ上記の例では、事がより現実的に見えます。 – Clev3r

関連する問題