Skip to content

Latest commit

 

History

History
1159 lines (852 loc) · 47.2 KB

README_ru.md

File metadata and controls

1159 lines (852 loc) · 47.2 KB

Оглавление

Введение

Жидкая архитектура. Это как джаз - вы импровизируете, работаете вместе, взаимодействуете друг с другом, вы создаете что-то, они создают что-то.

—Френк Гери

Стиль имеет значение. Elixir имеет много стилей, но, как и все языки, его можно задушить. Не душите стиль.

Описание

Это перевод на русский язык руководства по написанию кода от сообщества языка программирования Elixir. Не стесняйтесь вносить предложения и создавать pull requests, и присоединяйтесь к живому сообществу Elixir.

Если вы ищете другие проекты, в которые можно внести свой вклад, посетите сайт менеджера пакетов Hex.

Переводы руководства доступны на следующих языках:

Форматирование

В Elixir v1.6 был представлен форматировщик кода и команда Mix format. Для всех новых проектов и исходного кода предпочтительнее использовать форматировщик.

Правила, перечисленные в этом разделе, применяются автоматически форматировщиком кода, здесь же они представлены в качестве примеров предпочтительного стиля.

Пробелы

Избегайте пробелов в конце строки. [ссылка]

  • Заканчивайте каждый файл пустой строкой. [ссылка]

  • Используйте символы новой строки в стиле Unix (*BSD/Solaris/Linux/OSX по умолчанию, пользователи Windows должны быть особенно осторожны). [ссылка]

  • Если вы используете Git, вы можете добавить следующую конфигурационную настройку, чтобы защитить свой проект от появления символов новой строки Windows: [ссылка]

  git config --global core.autocrlf true
  • Ограничивайте длину строк 98 символами или установите параметр :line_length в вашем файле .formatter.exs. [ссылка]

  • Используйте пробелы вокруг операторов, после запятых, двоеточий и точек с запятой. Не ставьте пробелы вокруг парных символов, таких как кавычки, скобки и т.д. Пробелы (в основном) несущественны для Elixir во время выполнения, но их правильное использование является ключом к написанию легко читаемого кода. [ссылка]

sum = 1 + 2
{a, b} = {2, 3}
[first | rest] = [1, 2, 3]
Enum.map(["one", <<"two">>, "three"], fn num -> IO.puts(num) end)
  • Не используйте пробелы после операторов, которые принимают только один аргумент, или вокруг оператора range. [ссылка]

    0 - 1 == -1
    ^pinned = some_func()
    5 in 1..10
  • Используйте пустые строки между def для разбиения функции на логические параграфы. [ссылка]

    def some_function(some_data) do
      some_data |> other_function() |> List.first()
    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
  • Не ставьте пустую строку после defmodule. [ссылка]

  • Если заголовок функции и do:-клауза слишком длинные и не помещаются на одной строке, поместите do: на новую строку, с отступом на один уровень больше, чем на предыдущей строке. [ссылка]

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

    Когда 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
  • Добавьте пустую строку после многострочного присвоения как визуальный критерий того, что присвоение завершено. [ссылка]

    # нежелательно
    some_string =
      "Hello"
      |> String.downcase()
      |> String.trim()
    another_string <> some_string
    
    # предпочтительно
    some_string =
      "Hello"
      |> String.downcase()
      |> String.trim()
    
    another_string <> some_string
    # также нежелательно
    something =
      if x == 2 do
        "Hi"
      else
        "Bye"
      end
    String.downcase(something)
    
    # предпочтительно
    something =
      if x == 2 do
        "Hi"
      else
        "Bye"
      end
    
    String.downcase(something)
  • Если список, ассоциативный массив или структура занимает несколько строк, помещайте каждый элемент, а также открывающую и закрывающую скобки, на отдельных строках. Сделайте отступ для содержимого на 1 уровень относительно открывающей и закрывабшей скобки. [ссылка]

    # нежелательно
    [:first_item, :second_item, :next_item,
    :final_item]
    
    # предпочтительно
    [
      :first_item,
      :second_item,
      :next_item,
      :final_item
    ]
  • Когда вы присваиваете список, ассоциативный массив или структуру, поместите открывающую скобку на ту же строку, что и присваивание. [ссылка]

    # нежелательно
    list =
    [
      :first_item,
      :second_item
    ]
    
    # предпочтительно
    list = [
      :first_item,
      :second_item
    ]
  • Если любой из клауз case или cond требует более одной строки (из-за длины строки, нескольких выражений в теле клаузы и т.д.), используйте многострочный синтаксис для всех клауз и разделяйте их с помощью пустой строки.[ссылка]

    # нежелательно
    case arg do
      true -> IO.puts("ok"); :ok
      false -> :error
    end
    
    # нежелательно
    case arg do
      true ->
        IO.puts("ok")
        :ok
      false -> :error
    end
    
    # предпочтительно
    case arg do
      true ->
        IO.puts("ok")
        :ok
    
      false ->
        :error
    end
  • Размещайте комментарии над строкой, которую они комментируют. [ссылка]

    String.first(some_string) # нежелательно
    
    # предпочтительно
    String.first(some_string)
  • Используйте один пробел между ведущим символом # комментария и текстом комментария. [ссылка]

    #not preferred
    String.first(some_string)
    
    # предпочтительно
    String.first(some_string)

Отступы

  • Выравнивайте последовательные with-клаузы и делайте для них одинаковый отступ. Помещайте аргумент do:-клаузы на новую строку, выровненную с предыдущими клаузами. [ссылка]

    with {:ok, foo} <- fetch(opts, :foo),
         {:ok, my_var} <- fetch(opts, :my_var),
         do: {:ok, foo, my_var}
  • Если блок with содержит несколько строк или имеет вариант else, используйте многострочный синтаксис. [ссылка]

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

Скобки

  • Используйте скобки для функций с одним аргументом при использовании оператора конвейера (pipe operator) (|>). [ссылка]

    # нежелательно
    some_string |> String.downcase |> String.trim
    
    # предпочтительно
    some_string |> String.downcase() |> String.trim()
  • Никогда не ставьте пробел между именем функции и открывающей скобкой. [ссылка]

    # нежелательно
    f (3 + 2)
    
    # предпочтительно
    f(3 + 2)
  • Используйте скобки в вызовах функций, особенно внутри конвейера (pipeline). [ссылка]

    # нежелательно
    f 3
    
    # предпочтительно
    f(3)
    
    # нежелательно и читается как rem(2, (3 |> g)), а не как задумано.
    2 |> rem 3 |> g
    
    # предпочтительно
    2 |> rem(3) |> g()
  • Опустите квадратные скобки в ключевых списках, когда они необязательны.[ссылка]

    # нежелательно
    some_function(foo, bar, [a: "baz", b: "qux"])
    
    # предпочтительно
    some_function(foo, bar, a: "baz", b: "qux")

Руководство

Правила в этом разделе могут не применяться форматировщиком кода автоматически, однако обычно эти правила являются предпочтительной практикой.

Выражения

  • Выравнивайте однострочные выражения def, которые относятся к одной функции, друг за другом, а многострочные выражения def разделяйте пустой строкой. [ссылка]

    def some_function(nil), do: {:error, "No Value"}
    def some_function([]), do: :ok
    
    def some_function([first | rest]) do
      some_function(rest)
    end
  • Если у вас больше одного многострочного выражения def, не используйте однострочные def. [ссылка]

    def some_function(nil) do
      {:error, "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
  • Используйте оператор конвейера |> для объединения функций в цепочку. [ссылка]

    # нежелательно
    String.trim(String.downcase(some_string))
    
    # предпочтительно
    some_string |> String.downcase() |> String.trim()
    
    # Многострочные конвейеры (pipelines) не требуют дополнительного отступа.
    some_string
    |> String.downcase()
    |> String.trim()
    
    # Многострочные конвейеры (pipelines) на правой стороне сопоставления с образцом
    # следует выравнивать по отступу на новой строке с правой частью выражения сопоставления.
    sanitized_string =
      some_string
      |> String.downcase()
      |> String.trim()

Хотя это предпочтительный метод, следует учитывать, что при копировании и вставке многострочных конвейеров в IEx может возникнуть синтаксическая ошибка, так как IEx будет оценивать первую строку, не осознавая, что следующая строка содержит конвейер. Чтобы избежать этого, можно обернуть вставленный код в скобки.

  • Избегайте использования оператора pipe |> только однократно. [ссылка]

    # нежелательно
    some_string |> String.downcase()
    
    System.version() |> Version.parse()
    
    # предпочтительно
    String.downcase(some_string)
    
    Version.parse(System.version())
  • Используйте простые (а не вызовы функций) переменные в начале цепочки функций. [ссылка]

    # нежелательно
    String.trim(some_string) |> String.downcase() |> String.codepoints()
    
    # предпочтительно
    some_string |> String.trim() |> String.downcase() |> String.codepoints()
  • Используйте скобки при объявлении def, если у функции есть аргументы, и не используйте скобки, если аргументов нет. [ссылка]

    # нежелательно
    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
  • Используйте do:: для однострочных операторов if/unless. [ссылка]

    # предпочтительно
    if some_condition, do: # some_stuff
    
  • Никогда не используйте unless с else. Перепишите такие случаи в "положительном" виде с использованием if. [ссылка]

    # нежелательно
    unless success do
      IO.puts('failure')
    else
      IO.puts('success')
    end
    
    # предпочтительно
    if success do
      IO.puts('success')
    else
      IO.puts('failure')
    end
  • Используйте true в качестве последнего условия для специальной формы cond, когда вам нужна клауза, которая всегда срабатывает. [ссылка]

    # нежелательно
    cond do
      1 + 2 == 5 ->
        "Nope"
    
      1 + 3 == 5 ->
        "Uh, uh"
    
      :else ->
        "OK"
    end
    
    # предпочтительно
    cond do
      1 + 2 == 5 ->
        "Nope"
    
      1 + 3 == 5 ->
        "Uh, uh"
    
      true ->
        "OK"
    end
  • Используйте скобки при вызове функций с нулевым арностью, чтобы они можно было отличить от переменных. Начиная с версии Elixir 1.4, компилятор будет предупреждать вас о местах, где существует неоднозначность. [ссылка]

    defp do_stuff, do: ...
    
    # нежелательно
    def my_func do
      # is this a variable or a function call?
      do_stuff
    end
    
    # предпочтительно
    def my_func do
      # this is clearly a function call
      do_stuff()
    end

Именование

Это руководство следует соглашениям об именовании из документации Elixir, включая использование snake_case и CamelCase для описания правил написания имен.

  • Используйте snake_case для атомов, функций и переменных. [ссылка]

    # нежелательно
    :"some atom"
    :SomeAtom
    :someAtom
    
    someVar = 5
    
    def someFunction do
      ...
    end
    
    # предпочтительно
    :some_atom
    
    some_var = 5
    
    def some_function do
      ...
    end
  • Используйте CamelCase для модулей (оставляйте аббревиатуры, такие как HTTP, RFC, XML, в верхнем регистре).[ссылка]

    # нежелательно
    defmodule Somemodule do
      ...
    end
    
    defmodule Some_Module do
      ...
    end
    
    defmodule SomeXml do
      ...
    end
    
    # предпочтительно
    defmodule SomeModule do
      ...
    end
    
    defmodule SomeXML do
      ...
    end
  • Функции, которые возвращают булевое значение (true или false), должны иметь название с вопросительным знаком в конце. [ссылка]

    def cool?(var) do
      String.contains?(var, "cool")
    end
  • Логические проверки, которые можно использовать в ограничителях (guard clauses), должны иметь префикс is_. Для списка разрешенных выражений см. Ограничители в документации. [ссылка]

    defguard is_cool(var) when var == "cool"
    defguard is_very_cool(var) when var == "very cool"
  • Не следует давать приватным функциям то же имя, что и у публичных функций. Кроме того, не рекомендуется использовать шаблон def name и defp do_name.

Обычно можно попытаться найти более описательные имена, сосредоточившись на различиях. [ссылка]

def sum(list), do: sum_total(list, 0)

# приватные функции
defp sum_total([], total), do: total
defp sum_total([head | tail], total), do: sum_total(tail, head + total)

Комментарии

  • Пишите выразительный код и старайтесь передать намерения вашей программы через управляющие конструкции, структуру и названия. [ссылка]

  • Комментарии длиннее одного слова должны начинаться с заглавной буквы, а предложения в них должны иметь знаки препинания. Используйте один пробел после точек. [ссылка]

    # нежелательно
    # этот комментарий начинается с маленькой буквы и не содержат знаков препинания
    
    # предпочтительно
    # Начинайте комментарий с заглавной буквы, используйте знаки препинания.
  • Ограничьте длину комментариев до 100 символов. [ссылка]

Комментарии-аннотации

  • Аннотации обычно должны быть написаны на строке непосредственно над соответствующим кодом. [ссылка]

  • Ключевое слово аннотации пишется с заглавной буквы, за которым следует двоеточие и пробел, а затем примечание, описывающее проблему. [ссылка]

    # TODO: Deprecate in v1.5.
    def some_function(arg), do: {:ok, arg}
  • В случаях, когда проблема настолько очевидна, что любая документация будет избыточной, аннотации могут оставаться без примечания. Однако это должно быть исключением, а не правилом. [ссылка]

    start_task()
    
    # FIXME
    Process.sleep(5000)
  • Используйте TODO, чтобы отметить отсутствующие функции или функциональность, которые должны быть добавлены в будущем. [ссылка]

  • Используйте FIXME для отметки о неисправном коде, который нуждается в исправлении. [ссылка]

  • Используйте OPTIMIZE, чтобы отметить медленный или неэффективный код, который может вызвать проблемы с производительностью. [ссылка]

  • Используйте HACK, чтобы указать на "запахи кода", где были использованы сомнительные методы написания кода и их следует переработать. [ссылка]

  • Используйте REVIEW, чтобы отметить все, что должно быть рассмотрено, чтобы убедиться, что оно работает по назначению. Например: REVIEW: Мы уверены, что это то, как клиент сейчас делает X? [ссылка]

  • Используйте другие пользовательские ключевые слова аннотации, если они кажутся уместными, но не забудьте задокументировать их в файле README вашего проекта или аналогичном файле. [ссылка]

Модули

  • Задавайте один модуль на файл, если только модуль не используется только внутри другого модуля (например, внутри теста). [ссылка]

  • Задавайте имена файлов в snake_case для имен модулей в CamelCase. [ссылка]

    # Файл называется some_module.ex.
    
    defmodule SomeModule do
    end
  • Каждый уровень вложенности в имени модуля должен быть представлен в виде отдельной директории. [ссылка]

    # file is called parser/core/xml_parser.ex
    
    defmodule Parser.Core.XMLParser do
    end
  • Список атрибутов модуля, директив и макросов должен быть упорядочен следующим образом: [ссылка]

    1. @moduledoc
    2. @behaviour
    3. use
    4. import
    5. require
    6. alias
    7. @module_attribute
    8. defstruct
    9. @type
    10. @callback
    11. @macrocallback
    12. @optional_callbacks
    13. defmacro, defmodule, defguard, def, и т.д.

    Добавляйте пустую строку между каждой группой и сортируйте термины (такие как имена модулей) в алфавитном порядке. Вот общий пример того, как должны быть упорядочены элементы в ваших модулях:

defmodule MyModule do
  @moduledoc """
  Пример модуля
  """

  @behaviour MyBehaviour

  use GenServer

  import Something
  import SomethingElse

  require Integer

  alias My.Long.Module.Name
  alias My.Other.Module.Example

  @module_attribute :foo
  @other_attribute 100

  defstruct [:name, params: []]

  @type params :: [{binary, binary}]

  @callback some_function(term) :: :ok | {:error, term}

  @macrocallback macro_name(term) :: Macro.t()

  @optional_callbacks macro_name: 1

  @doc false
  defmacro __using__(_opts), do: :no_op

  @doc """
  Определяет, когда терм равен :ok. Разрешено использование в ограничениях (guards).
  """
  defguard is_ok(term) when term == :ok

  @impl true
  def init(state), do: {:ok, state}

  # Определите другие функции здесь.
end
  • Используйте псевдопеременную __MODULE__, когда модуль ссылается на самого себя. Это позволяет избежать необходимости обновлять ссылки на себя при изменении имени модуля. [ссылка]

    defmodule SomeProject.SomeModule do
      defstruct [:name]
    
      def name(%__MODULE__{name: name}), do: name
    end
  • Если вам нужно более удобное имя для ссылки на сам модуль, можно настроить псевдоним (alias). [ссылка]

    defmodule SomeProject.SomeModule do
      alias __MODULE__, as: SomeModule
    
      defstruct [:name]
    
      def name(%SomeModule{name: name}), do: name
    end
  • Избегайте повторения фрагментов в названиях модулей и пространств имен. Это повышает общую читаемость и устраняет неоднозначность псевдонимов. [ссылка]

    # нежелательно
    defmodule Todo.Todo do
      ...
    end
    
    # предпочтительно
    defmodule Todo.Item do
      ...
    end

Документация

Документация в Elixir (когда оно либо читается в iex с помощью h, либо генерируется с помощью ExDoc), использует атрибуты модуля @moduledoc и @doc.

  • Всегда используйте атрибут @moduledoc в строке сразу после defmodule в вашем модуле. [ссылка]

    # нежелательно
    
    defmodule AnotherModule do
      use SomeModule
    
      @moduledoc """
      О модуле
      """
      ...
    end
    
    # предпочтительно
    
    defmodule AThirdModule do
      @moduledoc """
      О модуле
      """
    
      use SomeModule
      ...
    end
  • Используйте @moduledoc false, если не планируете документировать модуль. [ссылка]

    defmodule SomeModule do
      @moduledoc false
      ...
    end
  • Отделяйте код после @moduledoc пустой строкой. [ссылка]

    # нежелательно
    defmodule SomeModule do
      @moduledoc """
      О модуле
      """
      use AnotherModule
    end
    
    # предпочтительно
    defmodule SomeModule do
      @moduledoc """
      О модуле
      """
    
      use AnotherModule
    end
  • Для документирования используйте heredoc-синтаксис (код "как есть") с разметкой markdown. [ссылка]

# нежелательно
defmodule SomeModule do
  @moduledoc "О модуле"
end

defmodule SomeModule do
  @moduledoc """
  О модуле

  Examples:
  iex> SomeModule.some_function
  :result
  """
end

# предпочтительно
defmodule SomeModule do
  @moduledoc """
  О модуле

  ## Examples

      iex> SomeModule.some_function
      :result
  """
end

Аннотации типов

Аннотации типов - это нотация для объявления типов и спецификаций, используемая для документирования или для использования инструмента статического анализа Dialyzer.

Пользовательские типы должны быть определены вверху модуля вместе с другими директивами (см. Модули).

  • Располагайте определения @typedoc и @type вместе, а каждую пару разделяйте пустой строкой. [ссылка]

    defmodule SomeModule do
      @moduledoc false
    
      @typedoc "The name"
      @type name :: atom
    
      @typedoc "The result"
      @type result :: {:ok, term} | {:error, term}
    
      ...
    end
  • Для длинных объединённых типов (union type), которые не умещаются на одной строке, следует помещать каждую часть типа на отдельной строке с отступом на один уровень больше имени типа. [ссылка]

    # нежелательно
    @type long_union_type ::
            some_type | another_type | some_other_type | one_more_type | a_final_type
    
    # предпочтительно
    @type long_union_type ::
            some_type
            | another_type
            | some_other_type
            | one_more_type
            | a_final_type
  • Назовите основной тип модуля t, например типовую спецификацию структуры (struct). [ссылка]

    defstruct [:name, params: []]
    
    @type t :: %__MODULE__{
            name: String.t() | nil,
            params: Keyword.t()
          }
  • Типы и спецификации следует размещать перед определением функции, после @doc, без разделения их пустой строкой. [ссылка]

    @doc """
    Описание функции.
    """
    @spec some_function(term) :: result
    def some_function(some_data) do
      {:ok, some_data}
    end

Structs

  • Используйте список атомов для того, чтобы задать поля структур со значением по умолчанию nil, а поля с другими значениями указывайте после. [ссылка]

    # нежелательно
    defstruct name: nil, params: nil, active: true
    
    # предпочтительно
    defstruct [:name, :params, active: true]
  • Опускайте квадратные скобки, когда аргументом defstruct является ключевой список. [ссылка]

    # нежелательно
    defstruct [params: [], active: true]
    
    # предпочтительно
    defstruct params: [], active: true
    
    # required - brackets are not optional, with at least one atom in the list
    defstruct [:name, params: [], active: true]
  • Если определение структуры занимает несколько строк, разместите каждый элемент на своей собственной строке, сохраняя выравнивание элементов. [ссылка]

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

Если многострочное определение структуры требует скобок, отформатируйте его как многострочный список:

defstruct [
  :name,
  params: [],
  active: true
]

Исключения

  • Названия исключений должны заканчиваться на Error. [ссылка]

    # нежелательно
    defmodule BadHTTPCode do
      defexception [:message]
    end
    
    defmodule BadHTTPCodeException do
      defexception [:message]
    end
    
    # предпочтительно
    defmodule BadHTTPCodeError do
      defexception [:message]
    end
  • Используйте строчные буквы в сообщениях об ошибках, когда вызываете исключения, и не используйте знаки препинания.[ссылка]

    # нежелательно
    raise ArgumentError, "This is not valid."
    
    # предпочтительно
    raise ArgumentError, "this is not valid"

Коллекции

  • Всегда используйте специальный синтаксис для ключевых списков. [ссылка]

    # нежелательно
    some_value = [{:a, "baz"}, {:b, "qux"}]
    
    # предпочтительно
    some_value = [a: "baz", b: "qux"]
  • Используйте сокращенный синтаксис "ключ: значение" для ассоциативных массивов, когда все ключи являются атомами. [ссылка]

    # нежелательно
    %{:a => 1, :b => 2, :c => 0}
    
    # предпочтительно
    %{a: 1, b: 2, c: 3}
  • Используйте для ассоциативных массивов подробный синтаксис "ключ => значение", если хотя бы один ключ не является атомом. [ссылка]

    # нежелательно
    %{"c" => 0, a: 1, b: 2}
    
    # предпочтительно
    %{:a => 1, :b => 2, "c" => 0}

Строки

  • Сопоставляйте строки, используя оператор конкантенации строк (<>), а не бинарные шаблоны: [ссылка]

    # нежелательно
    <<"my"::utf8, _rest::bytes>> = "my string"
    
    # предпочтительно
    "my" <> _rest = "my string"

Регулярные выражения

Никаких рекомендаций для регулярных выражений пока не добавлено.

Метапрограммирование

  • Избегайте ненужного метапрограммирования. [ссылка]

Тестирование

  • При написании утверждений ExUnit помещайте проверяемое выражение слева от оператора, а ожидаемый результат - справа, если только утверждение не является сопоставлением с образцом. [ссылка]

    # предпочтительно
    assert actual_function(1) == true
    
    # нежелательно
    assert true == actual_function(1)
    
    # необходимо, т.к. утверждение является сопоставлением с образцом
    assert {:ok, expected} = actual_function(3)

Ресурсы

Альтернативные руководства по стилю

Инструменты

Обратитесь к разделу Awesome Elixir за библиотеками и инструментами, которые могут помочь с анализом кода и линтингом стилей.

Участие

Вклад

Мы надеемся, что это станет центральным узлом для обсуждения сообществом лучших практик Elixir. Не стесняйтесь открывать тикеты или отправлять пулл-реквесты. Заранее спасибо за вашу помощь!

Для получения дополнительной информации ознакомьтесь с руководством по участию в проекте.

Распространение

Руководство по стилю сообщества бессмысленно без поддержки сообщества. Пожалуйста, напишите в твиттере, star, и сообщите программистам Elixir об этом руководстве, чтобы они могли внести свой вклад.

Копирование

Лицензия

Creative Commons License This work is licensed under a Creative Commons Attribution 3.0 Unported License

Авторство

Структура этого руководства, фрагменты кода примеров и многие исходные положения, изложенные в этом документе, были заимствованы из руководства по стилю сообщества Ruby. Многие вещи применимы к Elixir, что позволило нам быстрее выпустить этот документ, чтобы начать дискуссию.

Вот список людей, которые внесли любезный вклад в этот проект.