Help us understand the problem. What is going on with this article?

真のミニマルフレームワーク duct

More than 3 years have passed since last update.

Ring, compojure, hiccupでお馴染みのweavejester先生の新作フレームワークがductです。

ductはclojureらしさを、存分に活かしたフレームワークでclojureの良さを十分に堪能できるかと思います。

ductの特長

REPL-driven development

開発はすべてREPLの中でやるように設計されています。

user=> (go)
:started
user=> (reset)
:reloading (charset-mapper.endpoint.example charset-mapper.system charset-mapper.config charset-mapper.main charset-mapper.endpoint.example-test user)
:resumed

(go)でRingサーバを起動し、(reset)で再起動しソースの変更を反映できます。オートリロードは見たところ標準ではついてなさそうです。

Component

ググらビリティの低い"Component"とは、状態の一元管理とライフサイクルの記述を担うフレームワークです。状態管理を各ネームスペースのatomやrefでやり始めると、散らばってどこになにがあるかわからなくなるし、前述のREPLでサーバ再起動したりする際に、状態の適切なクリアと再初期化ができないとうまく動かなくなってしまうのでComponentが作られたようです。

ductでもComponentをフル活用しています。というかductはComponentの薄いラッパーに過ぎません。とにかくweavejester先生の、高機能かつ小さいライブラリや薄いラッパーを作る能力は感動ものです。

Componentではsystemというマップに、すべての状態を押し込めます。

(component/system-map
  :app  (handler-component (:app config))
  :http (jetty-server (:http config))
  :cdi  (cdi-component)
  :example (endpoint-component example-endpoint)
  :api (endpoint-component api-endpoint))

Componentの依存関係があるときは、using関数を使って宣言しておくと、フレームワーク側がいい順番で初期化してくれるようになります。
このusingを全てのコンポーネントに対して定義するために、system-using関数が使えます。

スレッディングマクロでつなげて書くとこんな感じです。

(-> (component/system-map
     :app  (handler-component (:app config))
     :http (jetty-server (:http config))
     :example (endpoint-component example-endpoint))
    (component/system-using
     {:http [:app]
      :app  [:example]}))

duct用のコンポーネントを作ってみる

後述のExampleアプリで、Component作ってみました。JavaEEのJPAを使うので、CDIコンテナを起動・停止するためのものです。

(defrecord CDI []
  component/Lifecycle
  (start [component]
    (if (:weld component)
      component
      (let [weld (Weld.)]
        (.initialize weld)
        (assoc component :weld weld))))
  (stop [component]
    (if-let [weld (:weld component)]
      (do (.shutdown weld)
          (dissoc component :weld))
      component)))

(defn cdi-component []
  (->CDI))

Weldの起動・停止しかしてないので、この程度でかけちゃいます。

ductのアプリケーションを作ってみる

Leiningenテンプレートがあるので、さくっと作れます。必要な機能が選択式であるのはLuminusあたりと同じです。

⇒  lein new duct myduct +example +cljs 
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=lcd
Retrieving duct/lein-template/0.5.5/lein-template-0.5.5.pom from clojars
Retrieving duct/lein-template/0.5.5/lein-template-0.5.5.jar from clojars
Generating a new Duct project named myduct...
Run 'lein setup' in the project directory to create local config files.

この状態でreplを起動すれば、すぐにWebサーバを起動できる状態にあります。

2015-12-02 15:40:29.094:INFO::main: Logging initialized @12654ms
nREPL server started on port 46827 on host 127.0.0.1 - nrepl://127.0.0.1:46827
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.7.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_66-b17
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> (go)
Compiling "target/figwheel/myduct/public/js/main.js" from ["src" "dev"]...
notifying browser that file changed:  target/figwheel/myduct/public/js/goog/deps.js
notifying browser that file changed:  target/figwheel/myduct/public/js/cljs_deps.js
notifying browser that file changed:  out/cljs/user.js
Successfully compiled "target/figwheel/myduct/public/js/main.js" in 7.073 seconds.
:started

これで、Ringサーバが起動し、ブラウザからhttp://localhost:3000/example+exampleで足したExampleアプリケーションにルーティングされて、レスポンスが返ってきます。

+cljsを付けると、Clojurescriptのベースも出力されます。REPLで、

user=> (reset)

とやると、Clojurescriptのファイルを編集していれば、同時にコンパイルされ、Figwheelの機能を使って、ブラウザ側もライブリロードされます。

ここから先は特にductに特別なことはありません。compujureなどを使ってWebアプリケーションを作るのと同じです。

ductを使ったアプリケーション

ductを使って作ってみました。

https://github.com/kawasima/supreme-uploading

アプリケーションの機能自体については、12/14のシステムエンジニア Advent Calendarで書く予定です。

omとductで簡単なシングルページアプリケーションを実装してあります。

ductへコントリビュートしてみた

+cljsを付けてlein newすると、プロジェクト配下にJavaファイルを作ったときにコンパイル対象にならない、というところでハマったので、初めてweavejester先生にプルリクを送ってみました。

https://github.com/weavejester/duct/pull/14

履歴を追うとわかるのですが、懇切丁寧にコミットメッセージの書き方指導までしていただきました :flushed:

まとめ

weavejester先生のことなので、ductは多機能の方向には進まず、このままミニマルな立ち位置を貫くことでしょう。したがって、フルスタック指向の人たちにはマッチしないと思われます。このミニマル/シンプルさはClojureの醍醐味なので、それを十分に堪能したいという人は、触れてみると面白いかと思います。

kawasima
Clojure関連のことをブログがわりに書き綴ります。 ※ここでの発言はシステムエンジニアを代表するものであって、所属する組織は二の次です。
https://github.com/kawasima/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした