Essential features of data specification libraries

栏目: IT技术 · 发布时间: 6年前

内容简介:Last week I took a look at three data specification libariers in Clojure:Data specification language.This is the foundation of every data specification library: a way to describe the data with a schema. You could use an existing language such asValidation.
Essential features of data specification libraries

Last week I took a look at three data specification libariers in Clojure: Schema, Spec, and Malli . This week, let’s talk about the essential features of these libraries.

Data specification language.This is the foundation of every data specification library: a way to describe the data with a schema. You could use an existing language such as JSON Schema , but in practice that’s clunky and everybody develops their own language.

;; Let's model users. We want to know the user's name and the year of birth.

;; Schema
(require '[schema.core :as schema])
(def User {:name schema/Str, :year-of-birth schema/Int})

;; Spec
(require '[clojure.spec.alpha :as spec])
(spec/def ::year-of-birth int?)
(spec/def ::name string?)
(spec/def ::user (spec/keys :req-un [::name ::year-of-birth]))

Validation.The basic operation is to validate data against a schema. What is interesting is what happens when the validation fails. Easy-to-read error messages are essential for the developers, but having errors as data is a useful building block, too. For example, you could build front-end form validation on top of a data specification library, and then you’d know what was the problem and in which field.

;; Our user data example is missing the year of birth. Who gives out their
;; real year of birth, anyway, to the services we (the software industry) build?
(def a-user {:name "hello@example.com", :year-of-birth nil})

(schema/validate User a-user)
;; Execution error (ExceptionInfo) at schema.core/validator$fn (core.clj:155).
;; Value does not match schema: {:year-of-birth (not (integer? nil))}

(spec/valid? ::user a-user)
;; => false

(spec/explain ::user a-user)
;; nil - failed: int? in: [:year-of-birth] at: [:year-of-birth] spec: :user/year-of-birth

Conforming.This feature is only implemented by Spec, but the idea is more general. A data specification language allows you to declare a grammar for your data structure. Conforming is parsing your data against that grammar. The result is akin to an abstract syntax tree, and Spec calls the conversion in the other direction “unforming”.

;; The regular expression specs and spec/or reveal the power of conforming.
;; Let's model hiccup-style HTML data.
(spec/def ::hiccup
  (spec/cat :tag keyword?
            :options (spec/? map?),
            :children (spec/* (spec/or :tag ::hiccup, :text string?))))

;; Now let's parse an anchor tag into a neat map.
(spec/conform
  ::hiccup
  [:a {:href "http://www.example.com/"} "Check out " [:i "example.com"]])
;; {:tag :a,
;;  :options {:href "http://www.example.com/"},
;;  :children [[:text "Check out "]
;;             [:tag {:tag :i,
;;                    :children [[:text "example.com"]]}]]}

Coercion.Coercion, or more generally, schema-driven transformation of data means that you walk your data and schema together and apply transformations to build new data. This allows you to do things like converting date strings in JSON to java.time instants and vice versa.

Program instrumentation.Yet another use case for data validation is to define a contract for a function: what kind of inputs it takes, what kind of data it returns, and how these are related. This is what Spec’s fdef does.

(require '[clojure.spec.test.alpha :as stest])

(defn plus [x y] (+ x y))
(spec/fdef plus :args (spec/cat :x int? :y int?) :ret int?)
(stest/instrument `plus)

(plus 1 2)
;; => 3

(plus 1 "2")
;; Execution error - invalid arguments to user/plus at (REPL:1).
;; "2" - failed: int? at: [:y]

Schema introspection.The ability to inspect the schema enables features such as generating JSON Schema from your schemas, as shown by spec-tools .

Performance.Data specification libraries can end up playing a pretty important role in your application. For REST APIs, JSON coercion is part of every request, and if you use instrumentation, validation is literally everywhere.

In my experience, indiscriminate use of Spec’s instrumentation makes programs crawl. Michael Borkent shared a similar experience on The REPL podcast :

If you have an application and you have like 100 core specs and then you start instrumenting those, the application becomes really really slow, even in just in development. So the overhead of calling spec validations on every function call in Clojure program becomes too much for core functions. That is what I had found and I was a little bit disappointed that it didn’t work out, so, at least for dev purpose.

The performance matters and your data specification library can become a bottleneck.

As far as I know, no data specification library for Clojure has all of the features mentioned above. Hopefully this list helps you to choose one – or to decide to roll your own!


以上所述就是小编给大家介绍的《Essential features of data specification libraries》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构

数据结构

殷人昆 / 清华大学 / 2007-6 / 39.00元

《数据结构》(第2版)“数据结构”是计算机专业的核心课程,是从事计算机软件开发和应用人员必备的专业基础。随着计算机的日益普及,“数据结构”课程也在不断地发展。《数据结构》(第2版)按照清华大学计算机系本科“数据结构”大纲的要求,从面向对象的概念、对象类设计的风格和数据结构的层次开始,从线性结构到非线性结构,从简单到复杂,深入地讨论了各种数据结构内在的逻辑关系及其在计算机中的实现方式和使用。此外,对......一起来看看 《数据结构》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具