[Elixir]マクロ defptとdefp、def

友人が作成していた https://github.com/skirino/croma に、 Mix.env の値によってコンパイル時に def として解釈するか、 defp として解釈するマクロがあります。

その使われ方が面白かったのでメモ。

その箇所だけ切り出して、参照値を環境変数のMIX_ENVにしたものが以下の Functions モジュールです。それをimportする Defpt モジュール、利用する Alexa と Alexaを呼び出す Me 。この Alexa で定義している defpt が今回の対象です。

これを見ると、 Me の中の Alexa.hello が、MIX_ENV == “test” の時はアクセス可能だけれど、それ以外ではundefined function errorになることがわかります。

ここで発生する可能性のある不具合としては、意図せず外部から defpt にアクセスしようとしてしまう、ということがありそうです。例えば、coverageが高いけれどテストコード実行時は def として扱われるので正常に動作する。ただ、それ以外だと defp として扱われるのでエラーに成る。

Elixirはコンパイルされるので、コンパイル時にdefpへ外部モジュールからアクセスしようとしたらwarningが出ます。そこで気付くことができるし、warningが出たらコンパイル失敗にもすることができるので、検出は可能。見逃しなどしなければ。

そう考えると defpt による定義間違いによるエラーは防げそうですね。

じゃぁ、 defpt 自体の有用さは置いておいて、隠蔽しようとしている関数をテストコードでテストするのか、です。これはprivateなメソッドをテストするか、という時折見る議論と重なるところがあります。それは開発途上、開発完了などの段階によって変わると思います。が、私は隠蔽しようとしているところ(外部モジュールから入出力で見ることができないところ)は無理にハックしない側の人なのでそこまでは不要かな、と感じます。

一方で、細かくメソッドを分割してそれらの小さな部品をチェックしつつも、それらを統合した時はその小さすぎるメソッド群は隠蔽したいということもあると思っています。(そして、それは理解出る…私も不安なときよくやる) そういう不安に立ち向かうときは、こういうprivateな関数をチェックすることは有用かなと。ただ、その場合は関数単位での小さなチェック以上の必要最低限のテスト、という形とは異なってはきますね。

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s