Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Duct for beginners.
Search
Nakamura, Ryotaro
February 16, 2018
Technology
0
4.2k
Duct for beginners.
How to use Integrant and Duct.
Nakamura, Ryotaro
February 16, 2018
Tweet
Share
More Decks by Nakamura, Ryotaro
See All by Nakamura, Ryotaro
Learn Go in 15 minutes
nryotaro
0
42
An introduction of statistical learning
nryotaro
0
43
Seven architectural patterns
nryotaro
1
110
Improving Performance with Parallel Programming
nryotaro
0
55
Other Decks in Technology
See All in Technology
アラフォーおじさん、はじめてre:Inventに行く / A 40-Something Guy’s First re:Invent Adventure
kaminashi
0
120
Building Serverless AI Memory with Mastra × AWS
vvatanabe
0
370
Amazon Quick Suite で始める手軽な AI エージェント
shimy
1
1.7k
【U/Day Tokyo 2025】Cygames流 最新スマートフォンゲームの技術設計 〜『Shadowverse: Worlds Beyond』におけるアーキテクチャ再設計の挑戦~
cygames
PRO
2
1.4k
「もしもデータ基盤開発で『強くてニューゲーム』ができたなら今の僕はどんなデータ基盤を作っただろう」
aeonpeople
0
230
AI with TiDD
shiraji
1
260
New Relic 1 年生の振り返りと Cloud Cost Intelligence について #NRUG
play_inc
0
220
1人1サービス開発しているチームでのClaudeCodeの使い方
noayaoshiro
2
570
Strands AgentsとNova 2 SonicでS2Sを実践してみた
yama3133
1
1.7k
オープンソースKeycloakのMCP認可サーバの仕様の対応状況 / 20251219 OpenID BizDay #18 LT Keycloak
oidfj
0
150
Oracle Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
1
760
20251219 OpenIDファウンデーション・ジャパン紹介 / OpenID Foundation Japan Intro
oidfj
0
480
Featured
See All Featured
[RailsConf 2023] Rails as a piece of cake
palkan
58
6.2k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
34
The Spectacular Lies of Maps
axbom
PRO
1
400
Claude Code のすすめ
schroneko
65
200k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
310
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
100
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
0
22
Deep Space Network (abreviated)
tonyrice
0
20
So, you think you're a good person
axbom
PRO
0
1.8k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.2k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.5k
Transcript
はじめてのDuct 中村 遼太郎
話すこと 2 IntegrantでこまってDuctを使うようになった話 • Integrant ◦ 概要 ◦ 困ったこと •
Duct ◦ 概要 ◦ Boundaries ◦ Moduleの作り方
Integrant 3
Ringの初期化例 4 (def endpoint “http://localhost/health”) (defn handler [request] (get-health endpoint))
(defn -main [] (jetty/run-jetty handler {:port 3000})) 他のサービスの状態を調べるハンドラ endpointに対するヘルスチェックの結果を返す
よくないところ 5 (def endpoint “http://localhost/health”) (defn handler [request] (get-health endpoint))
(defn -main [] (jetty/run-jetty handler {:port 3000})) グローバル変数による依存解決 変数のスコープが必要以上に大きい mainからendpointが見える
パラメタでスコープを小さくする 6 パラメタによる依存解決 設定とリクエストまじり,パラメタが複雑になる (defn wrap-handler [handler ep] (fn [request]
(handler (assoc request :endpoint ep)))) (defn handler [request] (get-health (:endpoint request))) (wrap-handler handler “http://localhost/health”)
Integrant 7 クロージャによる依存解決 クロージャでローカル変数を個別に渡す (defmethod ig/init-key :ebis/handler [_ endpoint] (fn
[request] (get-health endpoint))) (defmethod ig/init-key :ebis/jetty [_ {:keys [handler] :as options}] (jetty/run-jetty handler options))
関心ごと分離 8 コンフィグマップ(構造) Integrantはシステムの実装と構造を分ける {:ebis/handler “http://localhost/health” :ebis/jetty {:handler #ig/ref :ebis/handler
:port 3000}}
Integrantがやること 9 キーワードをオブジェクトに置き換える Integrantはシステムの実装と構造を分ける {:ebis/handler “http://localhost/health” :ebis/jetty {:handler #ig/ref :ebis/handler
:port 3000}} init-key
Integrantからみたシステム 10 コードの木 Integrantはコードの幹にある integrantは コードを呼び出す コードが ライブラリを呼ぶ https://skillsmatter.com/skillscasts/8717-arachne-building-a-framework-in-clojure
Integrantからみたシステム 11 システムの実装と構造の分離 Integrantは幹の部分から実装とコードを分けていく James Reeves, Enter Integrant: a micro-framework
for data-driven-architecture 実装
Integrantで困ったこと 12 途中までIntegrantを使う ライブラリの呼び出し部分への適用が最後になる ライブラリと コードが密結合 コンフィグマップ にする順序
ほしいもの 13 途中までIntegrantを使う ➔ ライブラリの呼び出しを楽を疎にするもの ➔ コンフィグマップの適用を楽にするもの 楽に適用できる システムの境界 を疎にできる
ほしいもの 14 途中までIntegrantを使う ➔ ライブラリの呼び出しを楽を疎にするもの ➔ コンフィグマップの適用を楽にするもの 楽に適用できる システムの境界 を疎にできる
Duct Boundaries Duct modules
Duct 15 weavejester If Integrant is the “grammar”, Duct is
attempting to build a “vocabulary”
Integrantの初期化手順 16 コンフィグをもとにシステムを初期化する read init コンフィグを読む コンフィグをオブジェクトに変換する
Ductの初期化手順 17 コンフィグを拡張する中間ステップがある read init コンフィグを読む prep コンフィグを書き換える コンフィグをオブジェクトに変換する
モジュール 18 prepステップでコンフィグを展開する純粋関数 read init prep module.web module.cljs module.sql module.logging
module.ataraxy Ductが提供するもの
コンフィグの展開 19 config.ednで使うモジュールを宣言する コンフィグのロード $ cat resources/ebis/config.edn { :duct.module/logging {}
... } ... $ lein repl user => (dev) :loaded Read Prep init
コンフィグの展開 20 prepでコンフィグを展開する モジュールによるloggerの展開 Read Prep init (dev) => (prep)
:prepped dev => (pprint config) { :duct.logger/timbre {:level :debug, {:appenders {: ...} :duct.logger.timbre/spit {:fname “logs/..”} :duct.module/logging {} ... }
コンフィグの展開 21 展開されたコンフィグでシステムが初期化される サーバの起動 Read Prep init dev => (go)
:duct.server.http.jetty/starting-server {:port 3000} :initiated
プロジェクトの構造 22 lein newでテンプレートからプロジェクトを作れる プロジェクトの構造 lein new duct ebis +api
+ataraxy {{project}} ├── src │ └── {{project}} │ ├── boundary │ │ └── {{boundary}}.clj │ ├── handler │ │ └── {{handler}}.clj │ └── main.clj
Boundaries 23 protocolを介してシステムの外と通信する プロトコルの利用例 (defprotocol Health (get-health [this])) (defrecord HttpHealth
[method url handler] Health (get-health [{:keys [method url handler]}] (handler (method url)))) (defmethod ig/init-key ::http [_ {:keys [url]}] (->HttpHealth http/get “http://..” #(..)))
Ductで困ること 24 必要なモジュールがない https://github.com/duct-framework module.web module.cljs module.sql module.logging module.ataraxy Duct
frameworkが提供するモジュール
事例 25 Google pubsubのモジュールを作る 購読開始処理 (def s-name (SubscriptionName/create “p-id” “s-id”))
(def receiver (reify MessageReceiver (receiveMessage [this message consume] (println (. message getData))))) (def subscriber (Subscriber/newBuilder s-name receiver)) (. (. subscriber build) startAsync)
モジュール化の方針 26 SubscriptionName/createをモジュールに移す 処理の分割 (def s-name → モジュール (SubscriptionName/create “p-id”
“s-id”)) (def receiver → ig/init (reify MessageReceiver (receiveMessage [this message consume] (println (. message getData))))) (def subscriber (Subscriber/newBuilder s-name receiver)) (. (. subscriber build) startAsync)→ protocol
モジュール側 1/3 27 src/duct_hierachy.ednにprepで呼び出すキーを登録 :duct/moduleを継承する {:duct.module/message [:duct/module]}
モジュール側 2/3 28 :duct/moduleを継承したキーがprepで呼び出される :duct/message/pubsubをコンフィグマップに追加 (defmethod ig/init-key :duct.module/message [_ options]
{:fn (fn [config] (core/merge-configs config ; ユーザが定義したコンフィグ {:duct.message/pubsub ;追加するキー {:logger (ig/ref :duct/logger)}}))}) :duct/module
モジュール側 3/3 29 prepで追加されたキーはinitするときに呼び出される SubscriptionNameのインスタンス化 (defmethod ig/init-key :duct.message/pubsub [_ {:keys
[p-id s-id] :as opt}] (assoc opt :s-name (SubscriptionName/create p-id s-id)))
アプリケーション側 1/3 30 config.ednに作ったモジュールを宣言する config.ednにモジュールを宣言 {:duct.message/pubsub {:p-id "clj-p" :s-id "clj-s"}
:duct.module/message {} :ebis.boundary/message #ig/ref :duct.message/pubsub } モジュールが初期化する
アプリケーション側 2/3 31 boundaryでprotocolを宣言する Receiverの宣言 (defprotocol Receiver (start [this]) (stop
[this])) (defrecord PubSubReceiver [subscriber logger] (start [this] (l/log logger :info “start”) (. subscriber startAsync)) ..)
アプリケーション側 3/3 32 Receiverをinit-keyの中で作る Receiverの生成 (defmethod :ig/init-key :ebis.boundary/message [_ {:keys
s-name logger}] (let [subscriber (... (reify MessageReceiver ...)) receiver (->PubSubReceiver subscriber logger)] (start receiver) (receiver)))
おさらい 33 ➔ Integrantだけだとコンフィグマップの適用がたいへん ➔ Ductのモジュールはコンフィグ化を助けてくれる ➔ しかしモジュールの数は少なく,作り方の説明は不十分 ➔ そこでモジュールの作り方を紹介した
参考資料 34 ➔ Arachne: building a framework in Clojure https://skillsmatter.com/skillscasts/8717-arachne-building-a-framework-in-clojure
➔ Productive Duct https://skillsmatter.com/skillscasts/10836-productive-duct ➔ Integrant: a micro-framework for data-driven architecture with James Reeves https://skillsmatter.com/skillscasts/9820-enter-integrant-a-micro-framework-for-data-driven-architecture-with-james-r eeves ➔ Duct, Covered https://skillsmatter.com/skillscasts/7229-duct-covered ➔ Duct Framework and supporting libraries https://github.com/duct-framework