Elixir 1.2-rc1のドキュメント Writing Documentationより翻訳。
1.2からの新機能…ですよねこれ。より能動的に埋め込みドキュメントを利用していくような開発スタイルが推奨されるようです。
ドキュメントを書くということ
Elixirはドキュメントを第一級市民として扱います。即ちドキュメントは書きやすくまた読みやすくあるべきです。このドキュメントでElixirでドキュメントを書くにはどのようにすればいいか、モジュールの属性やスタイルの実例またdoctestについて学びます。
Markdown
ElixirのドキュメントはMarkdownを利用して書きます。ネット上にMarkdownについては十分に参考資料がありますが、まずGithub上にある以下から始めるのがよいと思います。
- https://help.github.com/articles/markdown-basics/
- https://help.github.com/articles/github-flavored-markdown/
モジュールの属性
Elixirのドキュメントは通常モジュールに属性として添付されます。例を見てみましょう。
defmodule MyApp.Hello do
@moduledoc """
This is the Hello module.
"""
@doc """
Says hello to the given `name`.
Returns `:ok`.
## Examples
iex> MyApp.Hello.world(:john)
:ok
"""
def world(name) do
IO.puts "hello #{name}"
end
end
@moduledoc
属性はドキュメントをモジュールに添付するのに使います。@doc
は関数の直前でその関数のドキュメントをつけるのに使います。これらに加えて@typedoc
はtypespecの一部として定義された型についてのドキュメントをつけるのに使います。
関数の引数
関数のドキュメントを書くと、引数名はコンパイラによって推論されます。
例を挙げると:
def size(%HashDict{size: size}) do
size
end
コンパイラはこの引数をhash_dict
と推論します。この推論は特に関数が複数の節を持っていて引数が毎回異なる値とマッチングされるような場合に時として最適ではないことがあります。正しい名前は本体のない節として指定することができます。
def size(dict)
推奨される書き方
開発者がドキュメントを書く際に従うべき推奨の方法がいくつかあります。
- ドキュメントの第一パラグラフは簡潔かつ単純に保つべきです。ExDocsなどのツールは第一行をサマリーの生成に使います。
- Markdownではバックティック(
`
)はコードの引用に使います。Elixirのビルドはその前提に基づいてモジュールや関数が参照された時に自動的にリンクを生成します。例えばMyApps.Hello
という名のモジュールがあった場合それは`MyApps.Hello`
として参照され、`Hello`
として参照されることはありません。関数名はローカル関数の場合、名前とアリティで`world/1`
のように参照されなければならず、モジュールとともに指定する場合は名前とアリティと外部のモジュール名で例えば`MyApps.Hello.world/1`
のように参照されます。 - 見出しを使う場合は常に
##
による第二レベルの見出しから使います。第一レベルの見出しはモジュールまたは関数名自体のために予約されています。
Doctest
我々は開発者がドキュメントに例を含めることを推奨します。例は ## Examples
以下に書かれることもあります。例が古くなってしまわないことを保証するためElixirのテストフレームワーク(ExUnit)は開発者がドキュメント内に書かれた例をテストするdoctestという機能を提供します。Doctestはドキュメント内のiex>
で始まるコードサンプルをパースして読みだすことで機能します。更に詳しくはExUnit.DocTest
をお読みください。
Doctestには制限があることに注意してください。状態や副作用によって関数が影響される場合doctestは書けません。そのような場合にはiex>
プロンプトなしで例題を直接ドキュメントに含めるようにすることを推奨します。
プライバシー
Elixirはdoc属性をfalseにすることで開発者がモジュールも関数もドキュメントから隠すことを許しています。
defmodule MyApp.Hidden do
@moduledoc false
def this_will_be_ignored_by_tools do
# ...
end
end
@doc false
を付けても関数がprivateになるわけではないことに注意してください。
defmodule MyApp.Sample do
@doc false
def add(a, b), do: a + b
end
上記の関数はMyApp.Sample.add(1, 2)
で呼び出されてしまいます。それだけではなくもしMyApp.Sample
がインポートされている場合はこのadd/2
関数も呼び出し側にインポートされます。これらの理由から関数に@doc false
を付ける場合には以下のどちらかお好みの方法で注意深く対応してください:
- privateな関数を
@moduledoc false
な、例えばMyApp.Hidden
のようなモジュールに移動し、関数がうっかり公開されたりインポートされないことを保証する。事実、@moduledoc false
を使うとモジュール全体を、個々の関数については@doc
をつけたままで隠蔽できます。ツール類はこのモジュールを無視します。 - 関数名をアンダースコアから始めて例えば
__add__/2
のようにします。コンパイラはアンダースコアから始まる関数はインポートしませんし、アンダースコアが付いていることで利用者に用心して使うようにということがわかるようになります。
ドキュメントはコメントとは違います(Documentation != Comments)
Elixirではドキュメントとコードコメントは違うものとして扱います。ドキュメントはAPIの利用者、つまりあなたの共同開発者や未来のあなた自身のためのものです。モジュールや関数はアプリケーションで公開されるインターフェイス(API)の一部である限り必ずドキュメント化されるべきです。
コードコメントは開発者がコードを読むためのものです。改良点のマーキング、コードを読む開発者のための注意書き(例えばあるライブラリにバグがあったのでこの関数を呼ばないようにした、など)その他に有用です。
言い換えるとドキュメントは必須ですがコードコメントはオプションです。
Code.get_docs/2
Elixirはドキュメントをバイトコードの予め定義されたチャンク内に格納します。そのドキュメントにはElixirからCode.get_docs/2
を使ってアクセスすることができます。このことはドキュメントが必要とされた時だけアクセスされ、仮想マシンによってモジュールがロードされた時にはアクセスされないことを意味します。唯一出来の良くない点は例えばIExによってモジュールがメモリ上で定義された場合、そのドキュメントはアクセスできないということです。