Skip to content

Latest commit

 

History

History
1102 lines (827 loc) · 28.9 KB

README-jaJP.md

File metadata and controls

1102 lines (827 loc) · 28.9 KB

目次

はじめに

まるでジャズみたいに一緒に即興で演奏するんだ。 私が何かを作って、彼らも何かを作ることで答える

-フランク・ゲーリー

スタイルは重要です。 Elixir には実に様々なスタイルがありますが、他の言語と同じように無視されがちです。 スタイルを尊重しましょう。

このガイドについて

これは、プログラミング言語 Elixir のコミュニティスタイルガイドを作ろうという試みです。気軽にプルリクエストを送ってください。 実際より5倍も長生きしている言語のようにElixirのコミュニティを活発にしましょう。

もし他に貢献できるプロジェクトを探しているならHex package manager siteを見てみてください。

このガイドは以下の言語にも翻訳されています。

ソースコードのレイアウト

  • インデントは スペース 2つ。ハードタブは使わないこと。

    [link]

    # 悪い例 - スペースが4つ
    def some_function do
        do_something
    end
    
    # 良い例
    def some_function do
      do_something
    end
  • Unixスタイルの改行コードを使うこと (*BSD/Solaris/Linux/OSX ではこれがデフォルトです。Windowsを使っている場合は気をつけてください) [link]

  • Gitを使っている場合はWindowsの改行コードであなたのプロジェクトがめちゃくちゃになるのを防ぐために、このように設定してください。 [link]

    git config --global core.autocrlf true
    • オペレータの前後、カンマ、コロン、セミコロンの後にはスペースを入れてください。
    • ()や[]の間にはスペースを入れないでください。
    • Elixirの処理系にとって空白にほとんど意味はありませんが、コードを読みやすくするためには重要です。 [link]
    sum = 1 + 2
    {a, b} = {2, 3}
    Enum.map(["one", <<"two">>, "three"], fn num -> IO.puts num end)
  • defの間や関数内のロジックの区切りに空白行を入れてください。 [link]

    def some_function(some_data) do
      altered_data = Module.function(data)
    end
    
    def some_function do
      result
    end
    
    def some_other_function do
      another_result
    end
    
    def a_longer_function do
      one
      two
    
      three
      four
    end
  • 関数節に一行のdefがあるならまとめて定義してしまってもよい。 [link]

    def some_function(nil), do: {:err, "No Value"}
    def some_function([]), do: :ok
    def some_function([first|rest]) do
      some_function(rest)
    end
  • do:を使った関数定義が長くなった場合は、改行後インデントしてからdo:を入れてください。 [link]

    def some_function(args),
      do: Enum.map(args, fn(arg) -> arg <> " is on a very long line!" end)

 上記の規約を使用した関数節があり、かつ他にdo:を使った関数節がある場合は すべての関数節で改行してから do:を入れてください:

# 悪い例
def some_function([]), do: :empty
def some_function(_),
  do: :very_long_line_here

# 良い例
def some_function([]),
  do: :empty
def some_function(_),
  do: :very_long_line_here
  • 複数行の関数節が一つ以上ある場合は一行のdefを使わないこと。 [link]

    def some_function(nil) do
      {:err, "No Value"}
    end
    
    def some_function([]) do
      :ok
    end
    
    def some_function([first|rest]) do
      some_function(rest)
    end
    
    def some_function([first|rest], opts) do
      some_function(rest, opts)
    end
  • 関数のチェインにはパイプライン演算子を使ってください。 [link]

    # 悪い例
    String.strip(String.downcase(some_string))
    
    # 良い例
    some_string |> String.downcase |> String.strip
    
    # 複数行のパイプラインはインデントしないこと。
    some_string
    |> String.downcase
    |> String.strip
    
    # パターンマッチの右辺として複数行のパイプラインを使う場合は改行してから書くこと。
    sanitized_string =
      some_string
      |> String.downcase
      |> String.strip

    これは好ましい書き方ですが少し注意が必要です。 IExが次の行にパイプラインがあることを認識せずに最初の行を評価するため、複数行のパイプラインをIExにコピーすると構文エラーが発生する可能性があります。

  • パイプライン演算子を一度だけ使うのをやめましょう。 [link]

    # 悪い例
    some_string |> String.downcase
    
    # 良い例
    String.downcase(some_string)
  • 関数チェインの最初の値は関数の戻り値ではなく、通常の変数を使ってください。 [link]

    # これは最悪!
    #  String.strip("nope" |> String.downcase).にパースされます
    String.strip "nope" |> String.downcase
    
    # 悪い例
    String.strip(some_string) |> String.downcase |> String.codepoints
    
    # 良い例
    some_string |> String.strip |> String.downcase |> String.codepoints
  • 行末に余分な空白を入れないこと。 [link]

  • ファイルの終わりには空行を入れること。 [link]

構文

  • def が引数をとる場合は括弧を使うこと。引数がない場合は省略すること。 [link]

    # 悪い例
    def some_function arg1, arg2 do
      # body omitted
    end
    
    def some_function() do
      # body omitted
    end
    
    # 良い例
    def some_function(arg1, arg2) do
      # body omitted
    end
    
    def some_function do
      # body omitted
    end
  • 複数行のif/unlessdo:を使ってはいけない。 [link]

    # 悪い例
    if some_condition, do:
      # a line of code
      # another line of code
      # note no end in this block
    
    # 良い例
    if some_condition do
      # some
      # lines
      # of code
    end
  • 一行のif/unless にはdo:を使うこと。 [link]

    # 良い例
    if some_condition, do: # some_stuff
    
  • unlesselseを使ってはいけない。 正常系が最初に来るように書き直してください。 [link]

    # 悪い例
    unless success? do
      IO.puts 'failure'
    else
      IO.puts 'success'
    end
    
    # 良い例
    if success? do
      IO.puts 'success'
    else
      IO.puts 'failure'
    end
  • cond構文の最後の条件は常にtrueを使うこと。 [link]

    cond do
      1 + 2 == 5 ->
        "Nope"
      1 + 3 == 5 ->
        "Uh, uh"
      true ->
        "OK"
    end
  •  関数名と括弧の間にはスペースを入れないこと。 [link]

    # 悪い例
    f (3 + 2) + 1
    
    # 良い例
    f(3 + 2) + 1
  •  関数呼び出しには括弧を使うこと。特にパイプライン演算子の中では必ず使うこと。 [link]

    # 悪い例
    f 3
    
    # 良い例
    f(3)
    
    # 悪い例.  rem(2, (3 |> g)) にパースされてしまう
    2 |> rem 3 |> g
    
    # 良い例
    2 |> rem(3) |> g
  • doブロックをとるマクロの呼び出しでは括弧を省略すること。 [link]

    # 悪い例
    quote(do
      foo
    end)
    
    # 良い例
    quote do
      foo
    end
  • 引数の最後が関数の場合は括弧を省略してもよい。 [link]

    # 良い例
    Enum.reduce(1..10, 0, fn x, acc ->
      x + acc
    end)
    
    # これも良い例
    Enum.reduce 1..10, 0, fn x, acc ->
      x + acc
    end
  • 変数と区別するため引数がない関数呼び出しでも括弧を使うこと。 (Elixir 1.4からは、このようなあいまいな記述があった場合には警告を出すようになりました) [link]

    defp do_stuff, do: ...
    
    # 悪い例
    def my_func do
      do_stuff # 関数呼び出しなのか変数なのかわからない
    end
    
    # 良い例
    def my_func do
      do_stuff() # 間違いなく関数呼び出し
    end
  • 連続したwith節はインデントを揃え、引数のdo:を新しい行に入れてください。 [link]

    with {:ok, foo} <- fetch(opts, :foo),
         {:ok, bar} <- fetch(opts, :bar),
      do: {:ok, foo, bar}
  •  with に 複数行のdoブロックがある場合や、elseオプションがある場合は複数行の構文を使用してください。 [link]

    with {:ok, foo} <- fetch(opts, :foo),
         {:ok, bar} <- fetch(opts, :bar) do
      {:ok, foo, bar}
    else
      :error ->
        {:error, :bad_arg}
    end

命名

  • アトム、関数、変数には snake_case を使うこと。 [link]

    # 悪い例
    :"some atom"
    :SomeAtom
    :someAtom
    
    someVar = 5
    
    def someFunction do
      ...
    end
    
    def SomeFunction do
      ...
    end
    
    # 良い例
    :some_atom
    
    some_var = 5
    
    def some_function do
      ...
    end
  • モジュール名はCamelCaseを使うこと(HTTP, RFC, XMLなどの頭字語はそのままでよい) [link]

    # 悪い例
    defmodule Somemodule do
      ...
    end
    
    defmodule Some_Module do
      ...
    end
    
    defmodule SomeXml do
      ...
    end
    
    # 良い例
    defmodule SomeModule do
      ...
    end
    
    defmodule SomeXML do
      ...
    end
  • ガード内で使用できる述語マクロ(コンパイル時にbooleanを返す関数になるもの)にはis_接頭辞をつけること。 ガード内で使用できる式については Expressions in Guard Clausesを参照してください。 [link]

    defmacro is_cool(var) do
      quote do: unquote(var) == "cool"
    end
  • ガード内で使わない述語関数はis_接頭辞ではなく末尾に?をつけること。 [link]

    def cool?(var) do
      # Complex check if var is cool not possible in a pure function.
    end
  • パブリック関数と同名のプライベート関数を定義したい場合はdo_を頭につけること。 [link]

    def sum(list), do: do_sum(list, 0)
    
    # private functions
    defp do_sum([], total), do: total
    defp do_sum([head|tail], total), do: do_sum(tail, head + total)

コメント

  • 表現力豊かなコードを書いてください。 制御フロー、構造、命名を通じてプログラムの意図を伝えてください。 [link]

  • # とコメントの間にスペースを一つ入れること。 [link]

  • 一語以上のコメントは先頭を大文字にして句読点を使うこと。 ピリオドの後にはスペースを一つ入れること。 [link]

    # 悪い例
    String.upcase(some_string) # Capitalize string.

注釈

  • 注釈は関連するコードのすぐ上に書くこと。 [link]

  • 注釈キーワードの後には: とスペースを入れてから本文を書いてください。 [link]

  • もし問題の説明が複数行になる場合は#の後にスペースを2つ入れてください。 [link]

  • もし問題が明らかな場合は注釈キーワードだけを該当行の最後に入れてください。 これは強制ではありません。 [link]

  • 未実装や、将来の機能追加のための注釈にはTODOを使ってください。 [link]

  • 壊れたコードの注釈には FIXME を使ってください。 [link]

  • 遅かったり、非効率的なコードの注釈にはOPTIMIZE を使ってください。 [link]

  • コードの書き方に疑問の残る箇所の注釈にはHACKを使ってください。 [link]

  • 正しく動くか確認する必要があるコードの注釈には REVIEW を使ってください。 例: REVIEW: Are we sure this is how the client does X currently? [link]

  • もし必要があるようなら独自の注釈キーワードを使ってもかまいませんが、それらはプロジェクトの README などに書かれるべきでしょう。 [link]

モジュール

  • モジュールは一つのファイルに一つだけ定義すること。 ただし内部的にのみ使用しているモジュール(テストなど) の場合はこの限りではない。 [link]

  • キャメルケースのモジュール名をアンダースコア化したファイル名にすること。 [link]

    # file is called some_module.ex
    
    defmodule SomeModule do
    end
  • モジュール名のネストはディレクトリ構造を反映させること。 [link]

    # file is called parser/core/xml_parser.ex
    
    defmodule Parser.Core.XMLParser do
    end
  • defmoduleの後に空行を入れてはいけない。 [link]

  • モジュールレベルのコードブロックの後には空行を入れること。 [link]

  • モジュール内の定義順は下記のようにする。 [link]

    1. @moduledoc
    2. @behaviour
    3. use
    4. import
    5. alias
    6. require
    7. defstruct
    8. @type
    9. @module_attribute

    それぞれのグループの間には空白行を入れ、アルファベット順でソートしてください。 モジュール定義の例を以下に記します。

    defmodule MyModule do
      @moduledoc """
      An example module
      """
    
      @behaviour MyBehaviour
    
      use GenServer
    
      import Something
      import SomethingElse
    
      alias My.Long.Module.Name
      alias My.Other.Module.Name
    
      require Integer
    
      defstruct name: nil, params: []
    
      @type params :: [{binary, binary}]
    
      @module_attribute :foo
      @other_attribute 100
    
      ...
    end
  • モジュールが自身を参照するには__MODULE__疑似変数を使用すること。 これならモジュール名が変更されてもコードの変更が要りません。 [link]

    defmodule SomeProject.SomeModule do
      defstruct [:name]
    
      def name(%__MODULE__{name: name}), do: name
    end
  • もしモジュール自身の参照にもっとわかりやすい名前を使いたければaliasを使うことができます。 [link]

    defmodule SomeProject.SomeModule do
      alias __MODULE__, as: SomeModule
    
      defstruct [:name]
    
      def name(%SomeModule{name: name}), do: name
    end

ドキュメント

Elixrのドキュメント(iexの中でhを入力するか、ExDocで作られたもの) はモジュールアトリビュートである @moduledoc@docを使います。

  • @moduledoc は必ずdefmoduleの次の行に書くこと。 [link]

    # 悪い例
    
    defmodule SomeModule do
    
      @moduledoc """
      About the module
      """
      ...
    end
    
    defmodule AnotherModule do
      use SomeModule
      @moduledoc """
      About the module
      """
      ...
    end
    
    # 良い例
    
    defmodule SomeModule do
      @moduledoc """
      About the module
      """
      ...
    end
  • モジュールについてのドキュメントを書かない場合は @moduledoc falseを使ってください。 [link]

    defmodule SomeModule do
      @moduledoc false
      ...
    end
  • @moduledocの後には空白行を入れてください。 [link]

    # 悪い例
    
    defmodule SomeModule do
      @moduledoc """
      About the module
      """
      use AnotherModule
    end
    
    # 良い例
    defmodule SomeModule do
      @moduledoc """
      About the module
      """
    
      use AnotherModule
    end
  • ドキュメントのため、複数行コメント内ではmarkdownを使いましょう。 [link]

    # 悪い例
    
    defmodule SomeModule do
      @moduledoc "About the module"
    end
    
    defmodule SomeModule do
      @moduledoc """
      About the module
    
      Examples:
      iex> SomeModule.some_function
      :result
      """
    end
    
    # 良い例
    defmodule SomeModule do
      @moduledoc """
      About the module
    
      ## Examples
    
          iex> SomeModule.some_function
          :result
      """
    end

Typespecs

typespecsは、型と仕様を宣言するための表記法です。 ドキュメント、または静的解析ツールDialyzerに使用されます。 カスタムタイプは、モジュール上部に他のタイプと一緒に定義する必要があります。 (モジュールをみてください)

  • @typedoc@type の定義は一緒に書き、それぞれのペア間には空白行を入れてください。 [link]

    defmodule SomeModule do
      @moduledoc false
    
      @typedoc "The name"
      @type name :: atom
    
      @typedoc "The result"
      @type result :: {:ok, term} | {:error, term}
    
      ...
    end
  • 直和型の定義が長過ぎる場合は改行して戻り値の型で整列するようにインデントしてください。 [link]

    # 悪い例 - インデントしていない
    @type long_union_type :: some_type | another_type | some_other_type
    | a_final_type
    
    # 良い例
    @type long_union_type :: some_type | another_type | some_other_type
                           | a_final_type
    
    # これも良い例 - 一行ごとに型一つ
    @type long_union_type :: some_type
                           | another_type
                           | some_other_type
                           | a_final_type
  • モジュール内で定義された構造体などの型定義は tとしてください。 [link]

    defstruct name: nil, params: []
    
    @type t :: %__MODULE__{
      name: String.t,
      params: Keyword.t
    }
  • 型定義は関数のすぐ上に空白行無しで書いてください。 [link]

    @spec some_function(term) :: result
    def some_function(some_data) do
      {:ok, some_data}
    end

構造体

  • もし構造体のフィールドのデフォルト値が全てnilならアトムのリストとしてください。 [link]

    # 悪い例
    defstruct name: nil, params: nil
    
    # 良い例
    defstruct [:name, :params]
  • 複数行に渡る構造体の定義の場合は、最初のキーの位置に合わせてインデントしてください。 [link]

    defstruct foo: "test", bar: true, baz: false,
              qux: false, quux: nil

例外

  • 例外の名前はErrorで終わること。 [link]

    # 悪い例
    defmodule BadHTTPCode do
      defexception [:message]
    end
    
    defmodule BadHTTPCodeException do
      defexception [:message]
    end
    
    # 良い例
    defmodule BadHTTPCodeError do
      defexception [:message]
    end
  • エラーメッセージは小文字で句読点を省いてください。 [link]

    # 悪い例
    raise ArgumentError, "This is not valid."
    
    # 良い例
    raise ArgumentError, "this is not valid"

コレクション

  • キーワードリストに対して常に特別な構文を使うこと。 [link]

    # 悪い例
    some_value = [{:a, "baz"}, {:b, "qux"}]
    
    # 良い例
    some_value = [a: "baz", b: "qux"]
  • マップのキーがすべてアトムの場合は短く書けるキーバリュー構文を使うこと。 [link]

    # 悪い例
    %{:a => 1, :b => 2, :c => 0}
    
    # 良い例
    %{a: 1, b: 2, c: 3}
  • マップのキーにアトムではないものがある場合は冗長なキーバリュー構文を使うこと。 [link]

    # 悪い例
    %{"c" => 0, a: 1, b: 2}
    
    # 良い例
    %{:a => 1, :b => 2, "c" => 0}

文字列

  • 文字列のパターンマッチはバイナリではなく、文字列結合演算子を使用してください。 [link]

    # 悪い例
    <<"my"::utf8, _rest>> = "my string"
    
    # 良い例
    "my" <> _rest = "my string"

正規表現

正規表現に関するガイドラインは今のところありません

メタプログラミング

  • 不要なメタプログラミングをしてはいけない。 [link]

その他のスタイル

あまり一般的ではないスタイルですが役立つ場合があるかもしれません。

Cond

  • アトムはtrueとして評価されるのでcondの最後に入れるすべてにマッチする節として使うことができます。 :else:otherwise を使うと良いでしょう。 [link]

    cond do
      1 + 2 == 5 ->
        "Nope"
      1 + 3 == 5 ->
        "Uh, uh"
      :else ->
        "OK"
    end
    
    # is the same as
    cond do
      1 + 2 == 5 ->
        "Nope"
      1 + 3 == 5 ->
        "Uh, uh"
      true ->
        "OK"
    end

スタイルガイド

他のスタイルガイドについては Awesome Elixir を見てください。

ツール

Awesome Elixir にコードの静的解析とlintのためのツールがあります。

コミュニティへの参加方法

コントリビュート

私達はここがElixirのベストプラクティスに関する議論の中心になることを願っています。 気軽にイシューを書いたりプルリクエストを送ってください。 contributing guidelinescode of conduct を確認してください。

広めてください

コミュニティスタイルガイドは、コミュニティのサポートなしでは無意味です。 ツイートしたり、スターをつけたり、Elixirプログラマに広めてください。

コピーライト

ライセンス

Creative Commons License 本翻訳のライセンスはCreative Commons Attribution 3.0 Unported Licenseです。

帰属

このドキュメントの作成にあたり、ガイドの章立てやコード例の一部、そして原案の多くをRuby community style guideから拝借しました。 それらの多くのことがElixirにも応用でき、また私達が議論するために 一部の ドキュメントを引くことが早くにできました。

ここに、このプロジェクトに対して親切にもコントリビュートして頂いた方々のリストを記します。