Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Clojure.specを活用したコード・ファーストスタイルのRESTサービス開発
Search
Kenji Nakamura
October 05, 2017
Technology
1
730
Clojure.specを活用したコード・ファーストスタイルのRESTサービス開発
(増席) 教養としてのClojure - そろそろ学んでおきたい2017年秋
https://d-cube.connpass.com/event/67567/presentation/
Kenji Nakamura
October 05, 2017
Tweet
Share
Other Decks in Technology
See All in Technology
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
15
93k
AzureでのIaC - Bicep? Terraform? それ早く言ってよ会議
torumakabe
1
610
CDK対応したAWS DevOps Agentを試そう_20260201
masakiokuda
1
420
予期せぬコストの急増を障害のように扱う――「コスト版ポストモーテム」の導入とその後の改善
muziyoshiz
1
2.1k
モダンUIでフルサーバーレスなAIエージェントをAmplifyとCDKでサクッとデプロイしよう
minorun365
4
220
今こそ学びたいKubernetesネットワーク ~CNIが繋ぐNWとプラットフォームの「フラッと」な対話
logica0419
5
460
30万人の同時アクセスに耐えたい!新サービスの盤石なリリースを支える負荷試験 / SRE Kaigi 2026
genda
4
1.4k
20260208_第66回 コンピュータビジョン勉強会
keiichiito1978
0
200
ClickHouseはどのように大規模データを活用したAIエージェントを全社展開しているのか
mikimatsumoto
0
270
会社紹介資料 / Sansan Company Profile
sansan33
PRO
15
400k
OCI Database Management サービス詳細
oracle4engineer
PRO
1
7.4k
【Ubie】AIを活用した広告アセット「爆速」生成事例 | AI_Ops_Community_Vol.2
yoshiki_0316
1
120
Featured
See All Featured
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.9k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
470
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
79
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
170
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
260
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
68
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
3.6k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.8k
How to Think Like a Performance Engineer
csswizardry
28
2.5k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
950
Utilizing Notion as your number one productivity tool
mfonobong
3
220
The Curse of the Amulet
leimatthew05
1
8.7k
Transcript
を活用したコード・ファーストスタ を活用したコード・ファーストスタ イルの イルの サービス開発 サービス開発 - D3 Meetup 教養としてのClojure
2017/10/4 - 株式会社シグニファイア 代表 中村研二
自己紹介 自己紹介 年間米国の金融・通信系スタートアップでエンジニア・マネー ジャ・ディレクターをしていました。 年から開発は 。ミッションクリティカルシステ ムにも使用しました。 昨年 の開発に特化した、株式会社シグニファ イアを設立。
紹介したいこと 紹介したいこと コードと デザインの乖離を無くし、メンテナンスコストを最 小に抑える の動的言語を活用したクイック・ターンアラウンドな開 発サイクル の活用例 質問・ディスカッションは で!
の文法解説 の詳細な使い方 の詳細
って って 型がないから心配 で静的型付き言語とは違ったアプローチでエラー チェック 起動が遅くて 駆動開発 によるホットリロー ディング カッコが多くて読み書きしづらそう
モードを使えばカッコを気にせずコーディングでき る!
フレームワーク フレームワーク ビルドツール 対話開発環境 サーバ抽象化フレームワーク 上で動作するルーティングライブラリ 上で 用の機能を追加したライ ブラリ
フレームワーク フレームワーク を定義する スペックに準拠し、設計、 ドキュメントなどをサポートするツール群 データ構造を定義し、バリデーションなどを行うラ イブラリ に や ス
キーマ、 サポート機能を付加するライブラリ サーバーを起動することなく 上のロジックをテスト することができるライブラリ
プロジェクトの生成と設定 プロジェクトの生成と設定 は をサポート、 はまだ 依存だが で 対応予定) lein new
compojure-api-with-spec
None
(defproject compojure-api-with-spec "0.1.0-SNAPSHOT" :description "compojure-api v2 and clojure.spec demo" :url
"https://github.com/k2n/compojure-api-with-spec" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[clj-time "0.14.0"] [metosin/compojure-api "2.0.0-alpha7"] [metosin/spec-tools "0.3.2"] [org.clojure/clojure "1.9.0-beta1"]] :ring {:handler compojure-api-with-spec.handler/app :async? true :nrepl {:start? true}} :uberjar-name "server.jar" :profiles {:dev {:dependencies [[peridot "0.5.0"]] :plugins [[lein-ring "0.12.0"] [com.jakemccrary/lein-test-refresh "0.21.1"]] :global-vars {*warn-on-reflection* true}}})
None
(ns compojure-api-with-spec.handler (:require [compojure.api.sweet :refer [api]] [compojure-api-with-spec [spec-coercion-routes :refer [spec-coercion-routes]]
[spec-validation-routes :refer [spec-validation-routes]]])) (def app (api {:swagger {:ui "/" :spec "/swagger.json" :data {:info {:title "Clojureでコード・ファーストなSwagger駆動REST API"} :tags [{:name "validation" :description "clojure.specによるバリデーション"} {:name "coercion" :description "clojure.specでコアーション"}]}}} spec-validation-routes spec-coercion-routes))
None
(ns compojure-api-with-spec.spec-validation-routes (:require [compojure.api.sweet :refer [context GET POST]] [ring.util.http-response :refer
[ok]] [clojure.spec.alpha :as s] [spec-tools.spec :as spec])) (def email-regex #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$") (def max-age 140) (s/def ::greeting (assoc spec/string? :description "このように注釈を定義することができる")) (s/def ::comment (assoc spec/string? :description "年齢の偶奇数を判定します")) (s/def ::response (s/keys :req-un [::greeting ::comment])) (s/def ::email (s/and spec/string? #(re-matches email-regex %))) (s/def ::age (s/and spec/int? #(> max-age %) #((complement neg?) %))) (defn validation-handler [email-address current-age] {:pre [(s/valid? ::email email-address) (s/valid? ::age current-age)] :post [(s/valid? ::response %)]} {:greeting (str email-address "を登録しました!") :comment (if (even? current-age) "あなたの年齢は偶数です"
None
(ns compojure-api-with-spec.spec-coercion-routes (:require [compojure.api.sweet :refer [context GET POST]] [compojure.api.coercion.spec :as
spec-coercion] [ring.util.http-response :refer [ok]] [clojure.spec.alpha :as s] [spec-tools.conform :as conform] [spec-tools.core :as st] [spec-tools.spec :as spec])) (s/def ::name spec/string?) (s/def ::amount (assoc spec/bigdec? :json-schema/type "string" :description "整数または小数を文字列として入力")) (s/def ::amount-type spec/string?) (defn string->bigdec [_ x] (cond (bigdec? x) x (string? x) (try (java.math.BigDecimal. x) (catch NumberFormatException e ::s/invalid)) :else ::s/invalid)) (def string-conforming (st/type-conforming
None
(ns compojure-api-with-spec.spec-routes-test (:require [clojure.test :refer :all] [clojure.edn :as edn] [cheshire.core
:as json] [compojure-api-with-spec.handler :refer [app]] [peridot.core :refer :all])) (deftest spec-routes-test (testing "validation" (testing "get" (testing "valid email address" (is (= 200 (-> (session app) (request "/
[email protected]
") :response :status)))) (testing "email address without domain" (is (= 400 (-> (session app) (request "/validation?email-address=foo") :response :status)))) (testing "email address without TLD" (is (= 400 (-> (session app) (request "/validation?email-address=foo@example") :response :status)))) (testing "email address with 1 character TLD, which is invalid."
終わりに 終わりに 今回の例はマクロを多用した 的な使われ方。通常はこれほど マジカルではない。 と はまだα版 の統合 への適用 を導入したくなったらお声がけください!コンサル・開
発承ります。