{"id":19055514,"url":"https://github.com/rrrene/elixir-style-guide","last_synced_at":"2025-04-07T07:11:28.871Z","repository":{"id":66239276,"uuid":"47823362","full_name":"rrrene/elixir-style-guide","owner":"rrrene","description":"Style Guide for the Elixir language, implemented by Credo","archived":false,"fork":false,"pushed_at":"2017-09-01T20:39:54.000Z","size":23,"stargazers_count":399,"open_issues_count":0,"forks_count":21,"subscribers_count":19,"default_branch":"master","last_synced_at":"2025-03-31T05:08:58.543Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rrrene.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2015-12-11T11:35:22.000Z","updated_at":"2025-02-27T08:15:10.000Z","dependencies_parsed_at":"2023-02-20T16:31:49.193Z","dependency_job_id":null,"html_url":"https://github.com/rrrene/elixir-style-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrrene%2Felixir-style-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrrene%2Felixir-style-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrrene%2Felixir-style-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rrrene%2Felixir-style-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rrrene","download_url":"https://codeload.github.com/rrrene/elixir-style-guide/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247608153,"owners_count":20965952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T23:45:40.369Z","updated_at":"2025-04-07T07:11:28.848Z","avatar_url":"https://github.com/rrrene.png","language":"Elixir","funding_links":[],"categories":["Styleguides"],"sub_categories":[],"readme":"# [Credo](https://github.com/rrrene/credo)'s Elixir Style Guide [![Deps Status](https://beta.hexfaktor.org/badge/all/github/rrrene/elixir-style-guide.svg)](https://beta.hexfaktor.org/github/rrrene/elixir-style-guide)\n\n## Prelude\n\nThere are two reasons for this document to exist:\n\n- It is my personal style guide and consists both of the way I write Elixir today, but more importantly of things I've seen in the wild and adapted because they make Elixir more readable for open source Alchemists everywhere.\n- Secondly, it is the [basis for Credo](https://github.com/rrrene/credo) and reflects the principles promoted by its code analysis.\n\nLike all of my work, this style guide stands on the shoulders of giants: It is influenced by the Ruby style guides by [bbatsov](https://github.com/bbatsov/ruby-style-guide) and [GitHub](https://github.com/styleguide/ruby) as well as more [public](http://elixir.community/styleguide) [attempts](https://github.com/niftyn8/elixir_style_guide) at Elixir Style Guides.\n\n\n\n## Philosophy\n\nContrary to other guides I've seen, this one is not very dogmatic. The overall principles are\n\n* be consistent in your choices (i.e. apply the same rules everywhere),\n* care about the readability of your code (e.g. when in doubt, spread text vertically rather than horizontally),\n* and care about easier maintenance (avoid confusing names, etc.).\n\nThis is especially important because we are such a young community. All the **code we put out there is worth its weight in gold** if it is easy to comprehend and invites people to learn and contribute.\n\n\n\n## Contribute\n\nIf you want to add to this document, please submit a pull request or open an issue to discuss specific points.\n\n\n## The Actual Guide\n\n### Code Readability\n\n* \u003ca name=\"spaces-indentation\"\u003e\u003c/a\u003e\n  Use tabs consistently (2 spaces soft-tabs are **preferred**).\n  \u003csup\u003e[[link](#spaces-indentation)]\u003c/sup\u003e\n\n* \u003ca name=\"line-endings\"\u003e\u003c/a\u003e\n  Use line-endings consistently (Unix-style line endings are **preferred**, but we should not exclude our brothers and sisters riding the Redmond dragon).\n  \u003csup\u003e[[link](#line-endings)]\u003c/sup\u003e\n\n* \u003ca name=\"no-trailing-whitespace\"\u003e\u003c/a\u003e\n  Don't leave trailing white-space at the end of a line.\n  \u003csup\u003e[[link](#no-trailing-whitespace)]\u003c/sup\u003e\n\n* \u003ca name=\"newline-eof\"\u003e\u003c/a\u003e\n  End each file with a newline (some editors [don't do this by default](https://robots.thoughtbot.com/no-newline-at-end-of-file)).\n  \u003csup\u003e[[link](#newline-eof)]\u003c/sup\u003e\n\n* \u003ca name=\"spaces-operators\"\u003e\u003c/a\u003e\n  Use spaces around operators and after commas.\n  \u003csup\u003e[[link](#spaces-operators)]\u003c/sup\u003e\n\n* \u003ca name=\"spaces-braces\"\u003e\u003c/a\u003e\n  Don't use spaces after `(`, `[`, and `{` or before `}`, `]`, and `)`. This is the **preferred** way, although other styles are possible, as long as they are applied consistently.\n  \u003csup\u003e[[link](#spaces-braces)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  Helper.format({1, true, 2}, :my_atom)\n\n  # also okay - carefully choose a style and use it consistently\n  Helper.format( { 1, true, 2 }, :my_atom )\n  ```\n\n* \u003ca name=\"character-per-line-limit\"\u003e\u003c/a\u003e\n  Keep lines fewer than 80 characters whenever possible, although this is not a strict rule.\n  \u003csup\u003e[[link](#character-per-line-limit)]\u003c/sup\u003e\n\n* \u003ca name=\"semicolon-between-statements\"\u003e\u003c/a\u003e\n  Don't use `;` to separate statements and expressions.\n  \u003csup\u003e[[link](#semicolon-between-statements)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  IO.puts \"Waiting for:\"\n  IO.inspect object\n\n  # NOT okay\n  IO.puts \"Waiting for:\"; IO.inspect object\n  ```\n\n* \u003ca name=\"no-space-bang\"\u003e\u003c/a\u003e\n  Don't put a space after `!` to negate an expression.\n  \u003csup\u003e[[link](#no-space-bang)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  denied = !allowed?\n\n  # NOT okay\n  denied = ! allowed?\n  ```\n\n* \u003ca name=\"group-function-definitions\"\u003e\u003c/a\u003e\n  Group function definitions. Keep the same function with different signatures together without separating blank lines. In all other cases, use blank lines to separate different functions/parts of your module (to maximize readability through \"vertical white-space\").\n  \u003csup\u003e[[link](#group-function-definitions)]\u003c/sup\u003e\n\n  ```elixir\n  defp find_properties(source_file, config) do\n    {property_for(source_file, config), source_file}\n  end\n\n  defp property_for(source_file, _config) do\n    Enum.map(lines, \u0026tabs_or_spaces/1)\n  end\n\n  defp tabs_or_spaces({_, \"\\t\" \u003c\u003e line}), do: :tabs\n  defp tabs_or_spaces({_, \"  \" \u003c\u003e line}), do: :spaces\n  defp tabs_or_spaces({_, line}), do: nil\n  ```\n\n* \u003ca name=\"vertical-space\"\u003e\u003c/a\u003e\n  Generally use vertical-space to improve readability of sections of your code.\n  \u003csup\u003e[[link](#vertical-space)]\u003c/sup\u003e\n\n  ```elixir\n  # it is preferred to employ a mixture of parentheses, descriptive variable\n  # names and vertical white space to improve readability\n\n  def run(%SourceFile{} = source_file, params \\\\ []) do\n    source_file\n    |\u003e Helper.find_unused_calls(params, [:String], nil)\n    |\u003e Enum.reduce([], \u0026add_to_issues/2)\n  end\n\n  defp add_to_issues(invalid_call, issues) do\n    {trigger, meta, _} = invalid_call\n\n    issues ++ [issue(meta[:line], trigger, source_file)]\n  end\n\n  # this function does the same as above, but is less comprehensible\n\n  def run(%SourceFile{} = source_file, params \\\\ []) do\n    Helper.find_unused_calls(source_file, params, [:String], nil)\n    |\u003e Enum.reduce [], fn {_, meta, _} = invalid_call, issues -\u003e\n      trigger = invalid_call |\u003e Macro.to_string |\u003e String.split(\"(\") |\u003e List.first\n      issues ++ [issue(meta[:line], trigger, source_file)]\n    end\n  end\n\n  ```\n\n* \u003ca name=\"pipe-chains\"\u003e\u003c/a\u003e\n  It is **preferred** to start pipe chains with a \"pure\" value rather than a function call.\n  \u003csup\u003e[[link](#pipe-chains)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way - this is very readable due to the clear flow of data\n  username\n  |\u003e String.strip\n  |\u003e String.downcase\n\n  # also okay - but often slightly less readable\n  String.strip(username)\n  |\u003e String.downcase\n  ```\n\n* \u003ca name=\"multi-line-call\"\u003e\u003c/a\u003e\n  When assigning to a multi-line call, begin a new line after the `=`. Indent the assigned value's calculation by one level. This is the **preferred** way.\n  \u003csup\u003e[[link](#multi-line-call)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  result =\n    lines\n    |\u003e Enum.map(\u0026tabs_or_spaces/1)\n    |\u003e Enum.uniq\n\n  # also okay - align the first assignment and subsequent lines\n  result = lines\n           |\u003e Enum.map(\u0026tabs_or_spaces/1)\n           |\u003e Enum.uniq\n  ```\n\n* \u003ca name=\"underscores-in-numerics\"\u003e\u003c/a\u003e\n  Add underscores to large numbers for better readability.\n  \u003csup\u003e[[link](#underscores-in-numerics)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way - very easy to read\n  num = 10_000_000\n\n  # NOT okay - how many zeros are there?\n  num = 10000000\n  ```\n\n* \u003ca name=\"function-parens\"\u003e\u003c/a\u003e\n  Use `def`, `defp`, and `defmacro` with parentheses when the function takes parameters. Omit the parentheses when the function doesn't accept any parameters. This is the **preferred** way.\n  \u003csup\u003e[[link](#function-parens)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way - omit parentheses for functions without parameters\n  def time do\n    # ...\n  end\n\n  # use parentheses if parameters are present\n  def convert(x, y) do\n    # ...\n  end\n  ```\n\n* \u003ca name=\"function-calling-parens\"\u003e\u003c/a\u003e\n  Most of the time when calling functions that take parameters, it is **preferred** to use parentheses.\n  \u003csup\u003e[[link](#function-calling-parens)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way - the more boring forms are preferred since it's easier to see what goes where\n  Enum.reduce(1..100, 0, \u0026(\u00261 + \u00262))\n\n  Enum.reduce(1..100, 0, fn(x, acc) -\u003e\n    x + acc\n  end)\n\n  # also okay - carefully choose a style and use it consistently\n  Enum.reduce 1..100, 0, \u0026 \u00261 + \u00262\n\n  Enum.reduce 1..100, 0, fn x, acc -\u003e\n    x + acc\n  end\n\n  ```\n\n* \u003ca name=\"macro-parens\"\u003e\u003c/a\u003e\n  For macros we see the contrary behaviour. The **preferred** way is to not use parentheses.\n  \u003csup\u003e[[link](#macro-parens)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  defmodule MyApp.Service.TwitterAPI do\n    use MyApp.Service, social: true\n\n    alias MyApp.Service.Helper, as: H\n  end\n  ```\n\n* \u003ca name=\"conditional-parens\"\u003e\u003c/a\u003e\n  Conclusively, never use parentheses around the condition of `if` or `unless` (since they are macros as well).\n  \u003csup\u003e[[link](#conditional-parens)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  if valid?(username) do\n    # ...\n  end\n\n  # NOT okay\n  if( valid?(username) ) do\n    # ...\n  end\n  ```\n\n#### Naming\n\n* \u003ca name=\"camelcase-modules\"\u003e\u003c/a\u003e\n  Use CamelCase for module names. It is **preferred** to keep acronyms like HTTP, XML uppercase.\n  \u003csup\u003e[[link](#camelcase-modules)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  defmodule MyApp.HTTPService do\n  end\n\n  # also okay - carefully choose a style and use it consistently\n  defmodule MyApp.HttpService do\n  end\n  ```\n\n* \u003ca name=\"snake-case-attributes-functions-macros-vars\"\u003e\u003c/a\u003e\n  Use snake_case for module attribute, function, macro and variable names.\n  \u003csup\u003e[[link](#snake-case-attributes-functions-macros-vars)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  defmodule MyApp.HTTPService do\n    @some_setting :my_value\n\n    def my_function(param_value) do\n      variable_value1 = \"test\"\n    end\n  end\n\n  # NOT okay\n  defmodule MyApp.HTTPService do\n    @someSetting :my_value\n\n    def myFunction(paramValue) do\n      variableValue1 = \"test\"\n    end\n  end\n  ```\n\n* \u003ca name=\"exception-naming\"\u003e\u003c/a\u003e\n  Exception names should have a common prefix or suffix. While this can be anything you like, esp. for small libraries, a common choice seems to have all of them end in `Error`.\n  \u003csup\u003e[[link](#exception-naming)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way - common suffix Error\n  defmodule BadHTTPHeaderError do\n    defexception [:message]\n  end\n\n  defmodule HTTPRequestError do\n    defexception [:message]\n  end\n\n  # also okay - consistent prefix Invalid\n  defmodule InvalidHTTPHeader do\n    defexception [:message]\n  end\n\n  defmodule InvalidUserRequest do\n    defexception [:message]\n  end\n\n  # bad - there is no common naming scheme for exceptions\n  defmodule InvalidHeader do\n    defexception [:message]\n  end\n\n  defmodule RequestFailed do\n    defexception [:message]\n  end\n  ```\n\n* \u003ca name=\"predicates\"\u003e\u003c/a\u003e\n  Predicate functions/macros should return a boolean value.\n  \u003csup\u003e[[link](#predicates)]\u003c/sup\u003e\n\n  For functions, they should end in a question mark.\n\n  ```elixir\n  # preferred way\n  def valid?(username) do\n    # ...\n  end\n\n  # NOT okay\n  def is_valid?(username) do\n    # ...\n  end\n  ```\n\n  For guard-safe macros they should have the prefix `is_` and not end in a question mark.\n\n  ```elixir\n  # preferred way\n  defmacro is_valid(username) do\n    # ...\n  end\n\n  # NOT okay\n  defmacro valid?(username) do\n    # ...\n  end\n  ```\n\n\n\n#### Sigils\n\n* \u003ca name=\"sigils\"\u003e\u003c/a\u003e\n  Use sigils where it makes sense, but don't use them in a dogmatic way.\n  \u003csup\u003e[[link](#sigils)]\u003c/sup\u003e\n\n  Example: Don't automatically use `~S` just because there is *one* `\"` in your string, but start using it when you would have to escape a lot of double-quotes.\n\n  ```elixir\n  # preferred way - use normal quotes even if one has to be escaped\n  legend = \"single quote ('), double quote (\\\")\"\n\n  # use sigils when you would have to escape several quotes otherwise\n  html = ~S(\u003ca href=\"http://elixir-lang.org\" target=\"_blank\" rel=\"external\"\u003eHomepage\u003c/a\u003e)\n\n  # also okay, but not preferred - important: choose a common sigil and stick with it\n  # avoid using ~S{} in one place while using ~S(), ~S[] and ~S\u003c\u003e in others\n  legend = ~S{single quote ('), double quote (\")}\n  html = \"\u003ca href=\\\"http://elixir-lang.org\\\" target=\\\"_blank\\\" rel=\\\"external\\\"\u003eHomepage\u003c/a\u003e\"\n  ```\n\n#### Regular Expressions\n\n* \u003ca name=\"regex-sigils\"\u003e\u003c/a\u003e\n  Use `~r//` as your \"go-to sigil\" when it comes to Regexes as they are the easiest to read for people new to Elixir. That said, feel free to use other `~r` sigils when you have several slashes in your expression.\n  \u003csup\u003e[[link](#regex-sigils)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way - use slashes because they are familiar regex delimiters\n  regex = ~r/\\d+/\n\n  # use sigils when you would have to escape several quotes otherwise\n  regex = ~r{http://elixir-lang.org/getting-started/mix-otp/(.+).html}\n  ```\n\n* \u003ca name=\"caret-and-dollar-regex\"\u003e\u003c/a\u003e\n  Be careful with `^` and `$` as they match start/end of line, not string endings. If you want to match the whole string use: `\\A` and `\\z`.\n  \u003csup\u003e[[link](#caret-and-dollar-regex)]\u003c/sup\u003e\n\n\n\n\n### Documentation\n\n* \u003ca name=\"documentation\"\u003e\u003c/a\u003e\n  First, try to see documentation in a positive light. It is not a chore that you put off for as long as possible (forever). At some point in your project, starting to document parts of your project is an opportunity to communicate important things with future-maintainers, potential users of your API and even your future self.\n  \u003csup\u003e[[link](#documentation)]\u003c/sup\u003e\n\n* \u003ca name=\"doc-false\"\u003e\u003c/a\u003e\n  When that point in time comes, every module and function should either be documented or marked via `@moduledoc false`/`@doc false` to indicate that there is no intent to document the object in question.\n  \u003csup\u003e[[link](#doc-false)]\u003c/sup\u003e\n\n* \u003ca name=\"exdoc\"\u003e\u003c/a\u003e\n  Use ExDoc for this, it's great.\n  \u003csup\u003e[[link](#exdoc)]\u003c/sup\u003e\n\n* \u003ca name=\"doc-style\"\u003e\u003c/a\u003e\n  As for style, put an empty line after `@moduledoc`. Don't put an empty line between `@doc` and its function/macro definition.\n  \u003csup\u003e[[link](#doc-style)]\u003c/sup\u003e\n\n  ```elixir\n  defmodule MyApp.HTTPService do\n    @moduledoc false\n\n    @doc \"Sends a POST request to the given `url`.\"\n    def post(url) do\n      # ...\n    end\n  end\n  ```\n\n* \u003ca name=\"doc-comments\"\u003e\u003c/a\u003e\n  Although Elixir favors `@moduledoc` and `@doc` as first-class citizens, don't be afraid to communicate via normal code comments as well. But remember: don't use this to explain bad code!\n  \u003csup\u003e[[link](#doc-comments)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way - provide useful additional information\n  defmodule Credo.Issue do\n    defstruct category:     nil,\n              message:      nil,\n              filename:     nil,\n              line_no:      nil,\n              column:       nil,\n              trigger:      nil,  # optional: the call that triggered the issue\n              metadata:     [],   # optional: filled in by the failing check\n  end\n\n  # NOT okay - \"explaining\" confusing code and ambiguous names\n  defmodule AbstractCredoIssueInterfaceFactory do\n    def build(input, params \\\\ []) do\n      Helper.find_values(input, params) # input is either a username or pid\n      |\u003e Enum.reduce %{}, fn {_, meta, _} = value, list -\u003e\n        if valid?(value) do\n          case Map.get(list, :action) do # remember: list is a map!!!!111\n            nil -\u003e nil # why does this break sometimes?\n            val -\u003e Map.put(list, val, true)\n          end\n        else\n          list\n        end\n      end\n    end\n  end\n  ```\n\n* \u003ca name=\"doc-comments-on-own-lines\"\u003e\u003c/a\u003e\n  If necessary, put longer, more descriptive comments on their own line rather than at the end of a line of code.\n  \u003csup\u003e[[link](#doc-comments-on-own-lines)]\u003c/sup\u003e\n\n\n\n### Refactoring Opportunities\n\n\n* \u003ca name=\"no-nested-conditionals\"\u003e\u003c/a\u003e\n  Never nest `if`, `unless`, and `case` more than 1 time. If your logic demands it, spread it over multiple functions.\n  \u003csup\u003e[[link](#no-nested-conditionals)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  defp perform_task(false, hash, config) do\n    nil\n  end\n  defp perform_task(true, hash, config) do\n    hash\n    |\u003e Map.get(:action)\n    |\u003e perform_action(config)\n  end\n\n  defp perform_action(nil, _config) do\n    nil\n  end\n  defp perform_action(:create, _config) do\n    # ...\n  end\n  defp perform_action(:delete, config) do\n    if config[:id] do\n      # ...\n    else\n      # ...\n    end\n  end\n\n  # NOT okay - rule of thumb: it starts to hurt at 3 levels of nesting\n  defp perform_task(valid, hash, config) do\n    if valid do\n      case Map.get(hash, :action) do\n        :create -\u003e\n          # ...\n        :delete -\u003e\n          if sid do   # \u003c-- we reach three levels of nesting here :(\n            # ...\n          else\n            # ...\n          end\n        nil -\u003e\n          nil\n      end\n    end\n  end\n\n  ```\n\n* \u003ca name=\"no-unless-with-else\"\u003e\u003c/a\u003e\n  Never use `unless` with else. Rewrite these with `if`, putting the positive case first.\n  \u003csup\u003e[[link](#no-unless-with-else)]\u003c/sup\u003e\n\n  ```elixir\n  # without an else block:\n  unless allowed? do\n    raise \"Not allowed!\"\n  end\n\n  # preferred way to \"add\" an `else` block here: rewrite using `if`\n  if allowed? do\n    proceed_as_planned\n  else\n    raise \"Not allowed!\"\n  end\n\n  # NOT okay\n  unless allowed? do\n    raise \"Not allowed!\"\n  else\n    proceed_as_planned\n  end\n  ```\n\n* \u003ca name=\"avoid-double-negations\"\u003e\u003c/a\u003e\n  Never use `unless` with a negated expression as condition. Rewrite with `if`.\n  \u003csup\u003e[[link](#avoid-double-negations)]\u003c/sup\u003e\n\n  ```elixir\n  # preferred way\n  if allowed? do\n    proceed_as_planned\n  end\n\n  # NOT okay - rewrite using `if`\n  unless !allowed? do\n    proceed_as_planned\n  end\n  ```\n\n* \u003ca name=\"reference-current-module\"\u003e\u003c/a\u003e\n  Always use `__MODULE__` when referencing the current module.\n  \u003csup\u003e[[link](#reference-current-module)]\u003c/sup\u003e\n\n\n### Software Design\n\n* \u003ca name=\"fixme\"\u003e\u003c/a\u003e\n  Use `FIXME:` comments to mark issues/bugs inside your code.\n  \u003csup\u003e[[link](#fixme)]\u003c/sup\u003e\n\n  ```elixir\n  defmodule MyApp do\n    # FIXME: this breaks for x \u003e 1000\n    def calculate(x) do\n      # ...\n    end\n  end\n  ```\n\n* \u003ca name=\"todo\"\u003e\u003c/a\u003e\n  Use `TODO:` comments to plan changes to your code.\n  \u003csup\u003e[[link](#todo)]\u003c/sup\u003e\n\n  ```elixir\n  defmodule MyApp do\n    # TODO: rename into something more clear\n    def generic_function_name do\n      # ...\n    end\n  end\n  ```\n  \n  This way tools have a chance to find and report both `FIXME:` and `TODO:` comments.\n\n* \u003ca name=\"alias-modules\"\u003e\u003c/a\u003e\n  When developing applications, try to alias all used modules. This improves readability and makes it easier to reason about the dependencies of a module inside your project. There are obvious exceptions for modules from Elixir's stdlib (e.g. `IO.ANSI`) or if your submodule has a name identical to an existing name (e.g. don't alias `YourProject.List` because that would override `List`). Like most other points in this guide, this is just a suggestion, not a strict rule.\n  \u003csup\u003e[[link](#alias-modules)]\u003c/sup\u003e\n\n  ```elixir\n  # While this is completely fine:\n\n  defmodule Test do\n    def something do\n      MyApp.External.TwitterAPI.search(...)\n    end\n  end\n\n  # ... you might want to refactor it to look like this:\n\n  defmodule Test do\n    alias MyApp.External.TwitterAPI\n\n    def something do\n      TwitterAPI.search(...)\n    end\n  end\n  ```\n\n  The thinking behind this is that you can see the dependencies of your module at a glance. So if you are attempting to build a medium to large project, **this can help you to get your boundaries/layers/contracts right**.\n\n\n\n### Pitfalls\n\n* \u003ca name=\"iex-pry\"\u003e\u003c/a\u003e\n  Never leave a call to `IEx.pry` in production code.\n  \u003csup\u003e[[link](#iex-pry)]\u003c/sup\u003e\n\n* \u003ca name=\"io-inspect\"\u003e\u003c/a\u003e\n  Be wary of calls to `IO.inspect` in production code. If you want to actually log useful information for later debugging, use a combination of `Logger` and `\u0026inspect/1` instead.\n  \u003csup\u003e[[link](#io-inspect)]\u003c/sup\u003e\n\n* \u003ca name=\"debugging-conditionals\"\u003e\u003c/a\u003e\n  Conditionals should never contain an expression that always evaluates to the same value (such as `true`, `false`, `x == x`). They are most likely leftovers from a debugging session.\n  \u003csup\u003e[[link](#debugging-conditionals)]\u003c/sup\u003e\n\n* \u003ca name=\"kernel-functions\"\u003e\u003c/a\u003e\n  Be wary of naming variables and functions the same as functions defined in `Kernel`, especially in cases where the function has arity 0.\n  \u003csup\u003e[[link](#kernel-functions)]\u003c/sup\u003e\n\n* \u003ca name=\"stdlib-modules\"\u003e\u003c/a\u003e\n  Be wary of naming modules the same as modules in the stdlib. Sometimes `YourProject.DataTypeString` is a less error-prone choice as the seemingly cleaner `YourProject.DataType.String` because aliasing the latter in a module makes the *normal* `String` module unavailable.\n  \u003csup\u003e[[link](#stdlib-modules)]\u003c/sup\u003e\n\n\n\n### Above all else\n\nFollow your instincts. Write coherent code by applying a consistent style.\n\n\n\n## License\n\nThis work is licensed under [the CC BY 4.0 license](https://creativecommons.org/licenses/by/4.0).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frrrene%2Felixir-style-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frrrene%2Felixir-style-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frrrene%2Felixir-style-guide/lists"}