타입이 쓸만한가?
예전에 c로 struct
같은 키워드로 타입을 구현하던 기억을 떠올려보자. 그때의 타입은 메모리의 위치를 참조하기 편하게 하기 위해 타입을 썼던것 같다.
뭐, 그때는 메모리는 당연히 고정되어야 하는것이고 원시타입의 크기에 따라 크기를 가늠할 수 있었기 때문이라고 생각.
그렇기 때문에 요즘에는, 그러니까 데이터의 사이즈가 막 변하고, 어떻게 조합될지도 예측하기 어려운 상황에서 그런용도로 타입을 쓰는 사람은 드물지 않을까?
오히려 다음 두 가지 이유때문에 타입을 쓰는 사람이 많을 거라 생각한다.
그렇다면, 동일한 가치를 제공하는 다른 개념이 있으면 타입은 안써도 되지 않을까?
schema
https://github.com/plumatic/schema
스키마의 핵심적인 역할을 하는 함수는 validate
이다. 요걸로 확인하고자 하는 값이 미리 정의한 스키마에 부합하는지 판별한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| (def Data "A schema for a nested data type" {:a {:b s/Str :c s/Int} :d [{:e s/Keyword :f [s/Num]}]}) (s/validate Data {:a {:b 123 :c "ABC"}})
|
공홈의 저 예제를 보면 저 스키마의 형태가 상당히 직관적임을 알 수 있다. 물론 함수를 정의하면서 인자의 스키마를 지정할 수도 있고, 해당 함수 실행시에 인자가 스키마를 따르는지 확인 할 수도 있다.
그러나 매번 validate
를 하기엔 귀찮으므로 이러한 스키마를 지켜야 하는 namespace
안에서는 기본 clojure 기능들을 override 해버리자.
1 2 3 4 5 6
| (ns korma-run.core (:refer-clojure :exclude [atom fn defn defmethod letfn defrecord]) (:require [korma.core :refer :all] [schema-tools.core :as st] [medley.core :as md] [schema.core :refer :all]))
|
그리고 나서 전역 설정을 먹이면 매 함수 호출마다 스키마를 검사하게 된다.
1
| (set-fn-validation! true)
|
이제 이것과 SqlKorma
를 엮으면 데이터베이스 조회시 조금은 더 신뢰할 수 있는 결과가 나오겠지?
1 2 3 4 5 6 7 8 9 10 11 12
| (defentity discounts (table :discount)) (defschema Discount {(optional-key :id) Num (required-key :type) Str (required-key :sale?) Bool (required-key :amount) Num}) (defentity items (table :item)) (defschema Item {(optional-key :id) Num (required-key :price) Num (required-key :name) Str})
|
이제 defmulti
를 써서 자바에서 주로 내 밥벌이로 쓰던 mybatis
의 discriminator
같은 기능을 훨씬 쉽고 더 좋게 쓸 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| (defmulti promote (fn [_ discount :- Discount] (:type discount))) (defmethod promote "fixed" [item :- Item discount :- Discount] (- (:price item) (:amount discount))) (defmethod promote "rate" [item :- Item discount :- Discount] (* (:price item) (- 1 (:amount discount))))
|