どうも、靖宗です。
ようやくGETTING STARTEDが終わりましたが氷山の一角すら体感できてない感じです。
ささっとウェブのチュートリアルを終わらせてfukuoka.exの強い人の記事なんかを追いたいところです。
浮気心を押さえてMix and OTP編を進めて行きます。
- Our first project
- Project compilation
- Running tests
- Automatic code formatting
- Environments
- Exploring
Elixirのアプリケーションのビルドとかの話だと思うのですが、「アプリケーションはキーバリューストアとして動作する」とあります。
('ω')。o(????????????)
イマイチ全容がつかめません。この章で作って行くサンプルのことを指している?
おそらくこの章、もしくは章をまたいでシンプルなクライアントを作って行きます。想定としては下記のようなリクエストが送受信できる感じ?
CREATE shopping OK PUT shopping milk 1 OK PUT shopping eggs 3 OK GET shopping milk 1 OK DELETE shopping eggs OK
典型的なCRUD?とりあえず読み進めます。
このキーバリューのアプリケーションを作って行くに当たって3つのツールを使います。
- OTP (Open Telecom Platform) Erlangのライブラリ。Erlangの開発者はコレを使って堅牢なシステムを作ってるみたい。たぶん進めれば分かる。
- Mix ビルドツール。テストとかもコレを使う?
- ExUnit Elixirのユニットテストのフレームワーク。たぶん。
たぶんばっかりですが、知らないものは仕方ない。
Our first project
って言っても前回なにもしないプロジェクトを作成してるゾ!
という突っ込みは無しにして、このMix and OTP
編で使うプロジェクトを作成していきます。
PS > mix new kv --module KV
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/kv.ex
* creating test
* creating test/test_helper.exs
* creating test/kv_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd kv
mix test
mix new プロジェクト名
という感じでしょうか。
今回は--module KV
としてますが、デフォルトではKv
となるそうです。hello_project
ならHello_project
になるのかな。
defmodule HelloProject do @moduledoc """ Documentation for HelloProject. """ @doc """ Hello world. ## Examples iex> HelloProject.hello() :world """ def hello do :world end end
HelloProject
になってました。意外と賢い。
兎に角、明示的にモジュール名を指定するときは--module 名前
とするそうです。
Project compilation
生成されたファイルで、プロジェクト名のディレクトリ直下にあるmix.exs
を見ていきます。
どうやらこれはプロジェクトの設定ファイルのようです。
defmodule KV.MixProject do use Mix.Project def project do [ app: :kv, version: "0.1.0", elixir: "~> 1.6-dev", start_permanent: Mix.env == :prod, deps: deps() ] end # Run "mix help compile.app" to learn about applications def application do [ extra_applications: [:logger] ] end # Run "mix help deps" to learn about dependencies defp deps do [ # {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, ] end end
KV.MixProject
モジュール内にパブリックな関数2つとプライベートな関数1つが定義されてます。
project
はプロジェクト自体のバージョンやElixirのバージョン依存などでしょうか。内部でプライベート関数deps
の呼び出しもあります。
aplication
はよく分かりませんがなんか要るんでしょう。そういえば二十二章のThe crypto module
で書き足せって言われた気がします。これはまぁ追々。
あとはプライベート関数のdeps
。見るからに依存関係を表してそうな感じ。ライブラリや外部のライブラリなどの依存関係?gitのアドレスも例として書かれているのでウェブからも参照してコンパイルできるのかな。(Goっぽい?)
次にlib/kv.ex
ファイル。これはプロジェクト名にも該当するし実質的なメインファイル?
defmodule KV do @moduledoc """ Documentation for KV. """ @doc """ Hello world. ## Examples iex> KV.hello() :world """ def hello do :world end end
Hello Worldが書かれている。
とりあえずコンパイルするにはこんだけで良いらしい。
コンパイルもmixで行う。
PS kvのプロジェクトフォルダ> mix compile
Compiling 1 file (.ex)
Generated kv app
プロジェクトのディレクトリに_build
というフォルダが追加される。この中にコンパイルされたkv.app
がある。
他にもconsolidated
フォルダの中にゴチャゴチャとあるが、これらはおそらくkv.appを動かす時に必要なモジュール群であり、全てが独立したプロトコルとしてVM上を走るっぽい。
十六章ではイマイチピンときませんでしたが、なるほどなっとく。
iexでは色々動いてる環境下でありがたくStringライブラリなど使えてましたが、おそらくコンパイルした後はそうも行かないのでそういった有り難いライブラリはプロトコルとして動かしてる感じでしょうか。
iex -S mix
でiex上で起動できる。ただしWindowsでPowerShell上なのでiex.bat
PS > iex.bat -S mix Interactive Elixir (1.8.0) - press Ctrl+C to exit (type h() ENTER for help) iex(1)> KV.hello() :world
Running tests
mixツールでテストまで実行できるようです。
基本的にテストのスクリプトはtest
ディレクトリ内部に<filename>_test.exs
として用意するようです。
今回生成したkv.ex
のテストファイルkv_test.exs
は最初っから生成されてます。
defmodule KVTest do use ExUnit.Case doctest KV test "greets the world" do assert KV.hello() == :world end end
なんか注意書きが。
- テストファイルはElixirのスクリプトファイル
.exs
であること。(いちいちコンパイルしなくていいように) - テストのモジュールは
モジュール名Test
とし、ExUnit.Case
をuse
してtest/2
マクロを使う(ルー大柴みたいになってますが許して)
最初に生成されるテストファイルを参照しつつドキュメント読めばよさそうではあります。
あとtest
ディレクトリにtest_helper.exs
というファイルが生成されていますが、中には関数一個が実行されるように書かれてるだけです。
ExUnit.start()
テストをカスタムしたいときとかに使うんでしょうか。
テストの実行もmixを使用します。
PS > mix test Compiling 1 file (.ex) Generated kv app .. Finished in 0.04 seconds 1 doctest, 1 test, 0 failures Randomized with seed 994000
テストするときに再コンパイルしてるのが気になりますが後々言及がある様なのでひとまず置いときます。
doctest
はドキュメントとして成り立ってればそれでええのかな?
テストが問題無く終わってるので、敢えてミスるように書き換える。
kv_test.exs
の比較してるところを変更する。
assert KV.hello() == :oops
mix test
を再実行
PS > mix test 1) test greets the world (KVTest) test/kv_test.exs:5 Assertion with == failed code: assert KV.hello() == :oops left: :world right: :oops stacktrace: test/kv_test.exs:6: (test) . Finished in 0.03 seconds 1 doctest, 1 test, 1 failure Randomized with seed 927000
今回はコンパイルが起こってない。
また、書き換えた箇所が「こう違うで!」と表示されている。
テストが失敗した箇所(test/kv_test.exs:5
)が表示されてるが、ここだけをテストすることも可能だそうで。
試しに変更した箇所を元に戻してやってみる。
PS > mix test test/kv_test.exs:5 Excluding tags: [:test] Including tags: [line: "5"] . Finished in 0.03 seconds 1 doctest, 1 test, 0 failures, 1 excluded Randomized with seed 50000
開発していくときに結構使えそう。
Automatic code formatting
mix new
でプロジェクトを生成した際に出てくる.formatter.exs
の説明が書かれていますがイマイチぴんときません。
たぶんプロジェクト内部で、ファイル名をどうするか、ディレクトリ名をどうするかなどの決まり事をチェックできる機能であるmix format
のオプションファイルでしょうか。
チーム内で開発してる時にファイル名をどうするだとか決まり事を書くのに使うのかもしれません。(使い方次第ではキャメルケースだの指定可能?)
よく分からないので必要になるまで放置!
Environments
Mixでコンパイルする際に環境毎に機能を切り替える機能も備わっているようです。
つまり開発時には自社内のプライベート空間にあるサーバー(192.168.200.xなど)を参照するようにして、リリースする際にはグローバルなサーバー(101.142.xxx.yyyなど)を参照する様にする機能だと思います。
主に3種類あり
:dev
開発用:test
テスト用:prod
リリース用(in production?)
となっております。
この環境で切り替わる機能はMix.env
という関数で取得できるそうで、例としてプロジェクト直下のmix.exs
が挙げられています。
start_permanent: Mix.env() == :prod,
たしかに書かれてる。
このstart_permanent:
というオプションはおそらくこのアプリケーションがなんらかのトラブルでクラッシュしても永遠に再起動するようにするオプションだと思います。
まさにリリース用のオプション・・・
この例から分かるように、環境毎に機能を切り分けたいときはMix.env()
で場合分けすれば良さそうです。
また、mixで環境を切り替えてコンパイルするには以下の通り
MIX_ENV=prod mix compile # Windowsはこっち > set "MIX_ENV=prod" && mix compile
Exploring
mixで困ったらmix help
をしてみると良い。コマンド一覧とちょっとした説明はこれで出てきます。
より詳しい説明はドキュメントかmixのソースを見るのがよさそう。