Clojure
Leiningen

Leiningen のテンプレート機能とは一体なんなのか

More than 3 years have passed since last update.

たまにはノウハウ的なことを書いておいたほうが良いと思ったので書きます。

Leiningen のテンプレートが何かを知っていて、バージョンを指定出来るという話を知っている場合 テンプレートを使う意義について に進んでください。


Leiningen テンプレートとは

Leiningen というツールについて改めて説明する必要はないと思いますが、もし分らなければ以下を参照してください。

さて、この Leiningen というツールには テンプレート という機能が備っています。 どういう機能かというと 公開されているプロジェクトの雛形を展開できる または 良く使うプロジェクトの雛形を公開できる というものです。

これらは次のように利用することが出来ます。

$ lein new $TEMPLATE_NAME $PROJECT_NAME

$TEMPLATE_NAME は省略可能でその場合は default テンプレート(後述)が利用されます。こうすることによって $PROJECT_NAME のディレクトリが作成( --to-dir オプションで展開先を変更することは可能)されます。


テンプレートは何処から来るのか

デフォルトで Leiningen 自体が抱えているプロジェクトテンプレートがあり、それは次の 4 つです。


  • default: ライブラリのための一般的なテンプレート

  • plugin: Leiningen のプラグインを作るためのテンプレート

  • app: アプリケーションプロジェクトのテンプレート

  • template: lein new 用のメタテンプレート

これらは Leiningen をインストールしているだけで自動的に使うことが出来るようになっているものでオフライン時でも利用が可能です。

これら以外のテンプレート名を $TEMPLATE_NAME に指定した場合、 Clojars から自動的に $TEMPLATE_NAMEgroup-id [1] として artifact-idlein-template のもの(つまり、 $TEMPLATE_NAME/lein-template )を探してきて取得しようとします[2]。

使用可能になっているテンプレートは以下のリンクから参照可能です。


テンプレートのバージョンの話

以前もこの話は少し書いたのですが改めて触れたいと思います。 Leiningen はテンプレートを取得する際、特に指定がなければ 最新の安定版 テンプレートを取得しようと試みます。このときオフラインだったり、既にローカルの Maven リポジトリに最新版が存在する場合、ダウンロードを実行せずにローカルに存在する最新のテンプレートを使用することになります。

ほとんどの場合は最新版のテンプレートで困ることはないのですが、最新版が壊れていたり、ドキュメント(書籍等)でテンプレートのバージョンが指定されている場合は 特定のバージョン を使いたいときがあります。そのような場合、次のように解決できます[3]。

$ lein new $TEMPLATE_NAME $PROJECT_NAME --template-version $TEMPLATE_VERSION

例えば Luminus の最新バージョンは 2.9.10.3 [4]ですが、それより前のバージョンが使いたい場合は次のように書けます。

$ lein new luminus luminus-app --template-version 2.9.10.2

また、開発版の snapshot を使いたい場合は次のように指定できます。

$ lein new $TEMPLATE_NAME $PROJECT_NAME --snapshot

とはいえ Clojars に公開されているバージョンなので本当に最新の開発版が欲しいならリポジトリを clone して lein install などを実行する必要があります。

バージョン( or snapshot )の指定とテンプレートのオプションを同時に指定する場合 -- を使って引数を区切ります( lein new それ自身の引数として解釈されるのを防ぐため)。

$ lein new $TEMPLATE_NAME $PROJECT_NAME --snapshot -- template-arg-1 template-arg-2

$ lein new luminus luminus-app --template-version 2.9.10.2 -- +postgres +cljs

また良く作られているテンプレートの場合 lein new :show $TEMPLATE_NAME とすることで、そのテンプレートに関する情報を見ることができます。

$ lein new :show duct

Create a new Duct web application.

Accepts the following profile hints:
+cljs - adds in ClojureScript compilation and hot-loading
+example - adds an example endpoint
+heroku - adds configuration for deploying to Heroku
+postgres - adds a PostgreSQL dependency and database component
+ragtime - adds a Ragtime component to handle database migrations
+site - adds site middleware, a favicon, webjars and more
+sqlite - adds a SQLite dependency and database component

Argument list: ([name & hints])


テンプレートが出来ること

最初に簡単に書きましたが、雛形を共有するというのが目的だと思ってもらえると分かりやすいでしょう。

なので、一般的な Clojure プロジェクトのテンプレートが出来ることというのは具体的に表現すると次のようになります。


  • project.clj を共有できるためライブラリやプラグインの特定バージョンが固定されたプロジェクト雛形を簡単に共有できる

  • 一般的なグルーコードやボイラープレート、ノウハウなどを共有できる

  • ライブラリ/プラグイン作者がライブラリを素早く試すための土台を公開できる

おおよそ、テンプレート機能が出来ることというのはこのようなことです。


テンプレートを使う意義について

本題です。テンプレートについてはここまでで説明した通りですが、ある程度 Clojure に慣れてくるとこれらを使ってプロジェクトを開始する必要があるのかどうかという疑問が出てきます(例えば Web アプリを作りたいとして何かしたらのテンプレートを使ったほうがよいのか、など)。

ここではテンプレートを使用することのメリットとデメリットについて触れ、その上でどうするのが良いのかという話をします。


メリット


  • とりあえず始めることが出来る


    • どういうものを使ったらいいのか分からない場合などは、テンプレートを使うのは有用でしょう



  • 退屈なボイラープレートを書く必要がない


    • 例えば Web アプリケーションを作るのであればサーバーの起動部分はほとんど共通だったりします(拘りがある場合は違いますが)

    • 準備が面倒なところを肩代わりしてくれるのも嬉しい(e.g. descjop)



  • 特定のライブラリの使い方を知ることができる


    • 初めて見るライブラリやプラグインの README を読んでも具体的に嬉しさみたいなものが理解し難いときがあるのでそういう場合は有用です




デメリット


  • テンプレート自体の品質維持が難しく壊れていることがある (e.g. Luminus)


    • テンプレートはオプションを受け取って生成するプロジェクトを変化させることが出来ますが、大抵の場合その全ての組み合せをテストされているということは期待できません

    • 幾つかのテンプレート (e.g. juxt/modular) ではプロジェクトが生成されることのテストを行っていたりするが、実際に実行できるかまでは保証されてないことが多い



  • テンプレートが更新されてもそれを追従することが出来るわけではない

  • 展開されたテンプレートのライブラリを最新にしても簡単には動かなかったりする


    • ライブラリもメジャーバージョンが違うと簡単には更新できない

    • 展開されたプロジェクトの何処に deprecated な関数があったりするのか容易には分からない




どうすべきか

ここまででテンプレートというのものが一体どういう性質を持ったものなのか理解できたと思います。この機能は万能ではありません。なので、当然メリットを享受しやすいシーンもありますし、不便さしか感じることができないときもあります。

このテンプレート機能が活躍するのは具体的にはメリットにもあげたように学習のときだと僕は感じています。

例えば ClojureScript の Live Reloading に興味があって Figwheel をどのように設定すれば良いのか具体的に知りたいときには chestnut は良い例になるでしょうし、 Component を使った Web アプリケーションを作りたい場合 duct は良い先生役になってくれると思います。 Luminus を見れば最近の流行っているライブラリを知ることが比較的容易にできるでしょう。

逆に真面目なプロジェクトの土台として使うには少々難があることが多いかなという感じがしています[5]。

どうすべきかというのを強く言うつもりはないですが、ひとつ間違いなく言えるのは「テンプレートは使わなくても大丈夫」ということです。なのでテンプレートを使ったほうがいいのだろうかと悩んだときはココまでで説明したことを改めて読んでもらって決めてもらえたらいいかなと思います。


まとめ

テンプレートは便利なだけではなく、不便なこともあるので使うかどうかは自分の裁量で決めましょう。


特別枠: Luminus について

おそらく一番有名な Leiningen テンプレートだと思いますが、少しだけ本題とはそれますがこれに言及しておきたいと思います。

Luminus は Web フレームワーク として名前が知られていますが、これもひとつの テンプレート です。なので今迄で説明したようなメリット/デメリットを包含しています。

このテンプレートの特徴としては Web アプリケーション開発で必要となるであろうライブラリや設定、グルーコード/ボイラープレートを提供しているところです。これによって簡単に Web アプリケーションが作成できるようになっています。

ただメリットばかりがあるというものでもなく、デメリットも幾つかあります。 1. 最新の安定板が壊れていることが往々にしてある 2. 使っているライブラリがそれなりの頻度で変わる 3. 結構な頻度で本体もドキュメントも更新される。

これらのデメリットは恐らく最新の Luminus 公式ドキュメントを読んでチュートリアルを進めている間は気になることも少いと思いますが、困るのは恐らく和訳されたドキュメントを読みながら進めようとしたり、自分で何か作ってみようと思ったときでしょう。 一応テンプレートのバージョンについて頭に入れておけばハマることもないとは思いますが注意が必要です。

[1] 突然 group-idartifact-id というものが出てきましたが Maven などで指定するものと同じですので、詳細はそちらを参照してください

[2] Leiningen のヘルプでは Clojars としか書いてませんが Leiningen のコア機能を使っているので恐らく Maven Central やサードパーティのリポジトリからも解決できるはずですが、一般的には Clojars に公開していると思うのでテンプレートに関してはあまり他のリポジトリを意識する必要はないと思います

[3] 書籍 Clojure Web Development Essentials では $HOME/.lein/profiles.clj にてバージョンを固定する方法が示されていますが、 Leiningen のバージョンが最新であればそのような指定の仕方をする必要はありません

[4] 2016-2-25(Thu) 現在

[5] 例えば前述の chestnut では Reagent を使いたくても Om にべったりなので引き剥がすのに苦労しますし、かといって他のテンプレートだと少し微妙なところがあったりして使い辛かったりするという具合です