├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── README.md ├── README_ptBR.md ├── Rakefile └── mix.exs /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | deps 3 | doc 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: ruby 4 | 5 | rvm: 6 | - 2.3.0 7 | 8 | install: 9 | - gem install mdl rake 10 | 11 | script: 12 | - rake test 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Elixir Style Guide 2 | 3 | First of all, thanks for wanting to contribute! :heart: 4 | 5 | You can contribute in several ways: 6 | 7 | * open up an issue if you find something plain old wrong in the style guide 8 | (e.g., typos or formatting); 9 | * open up an issue if you find inconsistencies in the style guide. This way, we 10 | can discuss the better way to eliminate those inconsistencies; 11 | * if you have any suggestions or opinions, open up an issue or (even better!) a 12 | pull request. 13 | 14 | If you edit the `README.md` file, please stick to this set of 15 | formatting/markup/style rules so that the style remains consistent: 16 | 17 | * don't make lines longer than 80 characters (most editors have an auto-wrapping 18 | functionality, for example [Emacs][Emacs LineWrap] or [Vim][Vim word wrap]); 19 | * use reference-style links, like `[an example][Example]`. Put the links in 20 | alphabetical order at the end of the document, and capitalize the first word 21 | of the link label. 22 | 23 | Use Ruby and [Markdownlint] to check your changes: 24 | 25 | ```sh 26 | gem install mdl rake 27 | rake test 28 | ``` 29 | 30 | **IMPORTANT**: By submitting a patch, you agree that your work will be 31 | licensed under the license used by the project. 32 | 33 | ## The Project Board 34 | 35 | If you are looking for issues to work on, the [project board][Project KanBan] 36 | is the place to go. Usually, you look at the issues from right to left, as 37 | the ones in the rightmost part are the closer to get merged and have higher 38 | priority. 39 | 40 | If you just want to dive in and start writing, the backlog has the 41 | 'ready to be picked up' issues. These issues have been discussed already and 42 | are most likely just waiting for someone to make a PR. Just look for the 43 | issues with the `enhancement` and/or `help wanted` labels. 44 | 45 | ## Collaborators 46 | 47 | If you have contributed to the repository you can be appointed as a collaborator 48 | after submitting a change and getting it merged. Collaborators are invited to 49 | manage issues, make corrections to the style guide, review pull requests, and 50 | merge approved changes. 51 | 52 | 1. All changes must pass automatic checks before being merged. 53 | 1. Minor changes and corrections can be merged without review. 54 | 1. Significant changes or new style rules should be discussed and approved in a 55 | pull request. 56 | 57 | ## Translations 58 | 59 | If you would like to help translate the Style Guide, check if there is 60 | an [existing translation][Translations] to contribute to. To create a new 61 | translation: 62 | 63 | 1. [Fork] this repository. 64 | 1. Clone your fork locally. 65 | 1. Copy `README.md` to a new file named after the country/language, like 66 | `README-jaJP.md`, and commit your translations there. 67 | 1. Add the main [repo][Repo] as an upstream remote, to fetch and merge changes. 68 | 69 | 70 | [Emacs LineWrap]: http://emacswiki.org/emacs/LineWrap 71 | [Fork]: https://github.com/christopheradams/elixir_style_guide#fork-destination-box 72 | [Markdownlint]: https://github.com/mivok/markdownlint 73 | [Project KanBan]: https://github.com/christopheradams/elixir_style_guide/projects/1 74 | [Repo]: https://github.com/christopheradams/elixir_style_guide.git 75 | [Translations]: README.md#translations 76 | [Vim word wrap]: http://vim.wikia.com/wiki/Automatic_word_wrapping 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [The Elixir Style Guide][Elixir Style Guide] 2 | 3 | ## Table of Contents 4 | 5 | * __[Prelude](#prelude)__ 6 | * __[The Guide](#the-guide)__ 7 | * [Source Code Layout](#source-code-layout) 8 | * [Syntax](#syntax) 9 | * [Naming](#naming) 10 | * [Comments](#comments) 11 | * [Comment Annotations](#comment-annotations) 12 | * [Modules](#modules) 13 | * [Documentation](#documentation) 14 | * [Typespecs](#typespecs) 15 | * [Structs](#structs) 16 | * [Exceptions](#exceptions) 17 | * _Collections_ 18 | * [Strings](#strings) 19 | * _Regular Expressions_ 20 | * [Metaprogramming](#metaprogramming) 21 | * [Testing](#testing) 22 | * [Alternative Style Guides](#alternative-style-guides) 23 | * [Tools](#tools) 24 | * __[Getting Involved](#getting-involved)__ 25 | * [Contributing](#contributing) 26 | * [Spread the Word](#spread-the-word) 27 | * __[Copying](#copying)__ 28 | * [License](#license) 29 | * [Attribution](#attribution) 30 | 31 | ## Prelude 32 | 33 | > Liquid architecture. It's like jazz — you improvise, you work together, you 34 | > play off each other, you make something, they make something. 35 | > 36 | > —Frank Gehry 37 | 38 | Style matters. 39 | [Elixir] has plenty of style but like all languages it can be stifled. 40 | Don't stifle the style. 41 | 42 | ## The Guide 43 | 44 | This is community style guide for the [Elixir programming language][Elixir]. 45 | Please feel free to make pull requests and suggestions, and be a part of 46 | Elixir's vibrant community. 47 | 48 | If you're looking for other projects to contribute to please see the 49 | [Hex package manager site][Hex]. 50 | 51 | 52 | Translations of the guide are available in the following languages: 53 | 54 | * [Chinese Traditional] 55 | * [Japanese] 56 | * [Korean] 57 | * [Portuguese] 58 | * [Spanish] 59 | 60 | ### Source Code Layout 61 | 62 | * 63 | Use two **spaces** per indentation level. 64 | No hard tabs. 65 | [[link](#spaces-indentation)] 66 | 67 | ```elixir 68 | # not preferred - four spaces 69 | def some_function do 70 | do_something 71 | end 72 | 73 | # preferred 74 | def some_function do 75 | do_something 76 | end 77 | ``` 78 | 79 | * 80 | Use Unix-style line endings (\*BSD/Solaris/Linux/OSX users are covered by 81 | default, Windows users have to be extra careful). 82 | [[link](#line-endings)] 83 | 84 | * 85 | If you're using Git you might want to add the following configuration 86 | setting to protect your project from Windows line endings creeping in: 87 | [[link](#autocrlf)] 88 | 89 | ```sh 90 | git config --global core.autocrlf true 91 | ``` 92 | 93 | * 94 | Use spaces around operators, after commas, colons and semicolons. 95 | Do not put spaces around matched pairs like brackets, parentheses, etc. 96 | Whitespace might be (mostly) irrelevant to the Elixir runtime, but its proper 97 | use is the key to writing easily readable code. 98 | [[link](#spaces)] 99 | 100 | ```elixir 101 | sum = 1 + 2 102 | {a, b} = {2, 3} 103 | [first | rest] = [1, 2, 3] 104 | Enum.map(["one", <<"two">>, "three"], fn num -> IO.puts num end) 105 | ``` 106 | 107 | * 108 | Do not use spaces after non-word operators that only take one argument; or 109 | around the range operator. 110 | [[link](#no-spaces)] 111 | 112 | ```elixir 113 | 0 - 1 == -1 114 | ^pinned = some_func() 115 | 5 in 1..10 116 | ``` 117 | 118 | * 119 | Use blank lines between `def`s to break up a function into logical 120 | paragraphs. 121 | [[link](#def-spacing)] 122 | 123 | ```elixir 124 | def some_function(some_data) do 125 | altered_data = Module.function(data) 126 | end 127 | 128 | def some_function do 129 | result 130 | end 131 | 132 | def some_other_function do 133 | another_result 134 | end 135 | 136 | def a_longer_function do 137 | one 138 | two 139 | 140 | three 141 | four 142 | end 143 | ``` 144 | 145 | * 146 | ...but run single-line `def`s that match for the same function together. 147 | [[link](#single-line-defs)] 148 | 149 | ```elixir 150 | def some_function(nil), do: {:err, "No Value"} 151 | def some_function([]), do: :ok 152 | def some_function([first | rest]) do 153 | some_function(rest) 154 | end 155 | ``` 156 | 157 | * 158 | If you use the `do:` syntax with functions and the line that makes up the 159 | function body is long, put the `do:` on a new line indented one level more 160 | than the previous line. 161 | [[link](#long-dos)] 162 | 163 | ```elixir 164 | def some_function(args), 165 | do: Enum.map(args, fn(arg) -> arg <> " is on a very long line!" end) 166 | ``` 167 | 168 | When you use the convention above and you have more than one function clause 169 | using the `do:` syntax, put the `do:` on a new line for each function clause: 170 | 171 | ```elixir 172 | # not preferred 173 | def some_function([]), do: :empty 174 | def some_function(_), 175 | do: :very_long_line_here 176 | 177 | # preferred 178 | def some_function([]), 179 | do: :empty 180 | def some_function(_), 181 | do: :very_long_line_here 182 | ``` 183 | 184 | * 185 | If you have more than one multi-line `def`s do not use single-line `def`s. 186 | [[link](#multiple-function-defs)] 187 | 188 | ```elixir 189 | def some_function(nil) do 190 | {:err, "No Value"} 191 | end 192 | 193 | def some_function([]) do 194 | :ok 195 | end 196 | 197 | def some_function([first | rest]) do 198 | some_function(rest) 199 | end 200 | 201 | def some_function([first | rest], opts) do 202 | some_function(rest, opts) 203 | end 204 | ``` 205 | 206 | * 207 | Use parentheses for one-arity functions when using the pipe operator (`|>`). 208 | [[link](#parentheses-pipe-operator)] 209 | 210 | ```elixir 211 | # not preferred 212 | some_string |> String.downcase |> String.strip 213 | 214 | # preferred 215 | some_string |> String.downcase() |> String.strip() 216 | ``` 217 | 218 | * 219 | Use the pipe operator to chain functions together. 220 | [[link](#pipe-operator)] 221 | 222 | ```elixir 223 | # not preferred 224 | String.strip(String.downcase(some_string)) 225 | 226 | # preferred 227 | some_string |> String.downcase() |> String.strip() 228 | 229 | # Multiline pipelines are not further indented 230 | some_string 231 | |> String.downcase() 232 | |> String.strip() 233 | 234 | # Multiline pipelines on the right side of a pattern match 235 | # should be indented on a new line 236 | sanitized_string = 237 | some_string 238 | |> String.downcase() 239 | |> String.strip() 240 | ``` 241 | 242 | While this is the preferred method, take into account that copy-pasting 243 | multiline pipelines into IEx might result in a syntax error, as IEx will 244 | evaluate the first line without realizing that the next line has a pipeline. 245 | 246 | * 247 | Avoid using the pipe operator just once. 248 | [[link](#avoid-single-pipelines)] 249 | 250 | ```elixir 251 | # not preferred 252 | some_string |> String.downcase() 253 | 254 | # preferred 255 | String.downcase(some_string) 256 | ``` 257 | 258 | * 259 | Use _bare_ variables in the first part of a function chain. 260 | [[link](#bare-variables)] 261 | 262 | ```elixir 263 | # THE WORST! 264 | # This actually parses as String.strip("nope" |> String.downcase()). 265 | String.strip "nope" |> String.downcase() 266 | 267 | # not preferred 268 | String.strip(some_string) |> String.downcase() |> String.codepoints() 269 | 270 | # preferred 271 | some_string |> String.strip() |> String.downcase() |> String.codepoints() 272 | ``` 273 | 274 | * 275 | When assigning a list that spans multiple lines, start the list on a newline, 276 | and indent the elements to keep them aligned. 277 | [[link](#multiline-list-assign)] 278 | 279 | ```elixir 280 | # not preferred - no indentation 281 | list = [:first_item, :second_item, :next_item, 282 | :last_item] 283 | 284 | # better, but not preferred - with indentation 285 | list = [:first_item, :second_item, :next_item, 286 | :last_item] 287 | 288 | # preferred - list starts on its own line 289 | # good for shorter, more compact lists 290 | list = 291 | [:first_item, :second_item, :next_item, 292 | :last_item] 293 | 294 | # also preferred - when each element is on its own line 295 | # good for long lists, lists with long elements, or lists with comments 296 | list = [ 297 | :first_item, 298 | :second_item, 299 | :next_item, 300 | # comment 301 | :many_items, 302 | :last_item 303 | ] 304 | ``` 305 | 306 | * 307 | Avoid trailing whitespace. 308 | [[link](#trailing-whitespace)] 309 | 310 | * 311 | End each file with a newline. 312 | [[link](#newline-eof)] 313 | 314 | ### Syntax 315 | 316 | * 317 | Use parentheses when a `def` has arguments, and omit them when it doesn't. 318 | [[link](#parentheses)] 319 | 320 | ```elixir 321 | # not preferred 322 | def some_function arg1, arg2 do 323 | # body omitted 324 | end 325 | 326 | def some_function() do 327 | # body omitted 328 | end 329 | 330 | # preferred 331 | def some_function(arg1, arg2) do 332 | # body omitted 333 | end 334 | 335 | def some_function do 336 | # body omitted 337 | end 338 | ``` 339 | 340 | * 341 | Add a blank line after a multiline assignment as a 342 | visual cue that the assignment is 'over'. 343 | [[link](#add-blank-line-after-multiline-assignment)] 344 | 345 | ```elixir 346 | # not preferred 347 | some_string = 348 | "Hello" 349 | |> String.downcase() 350 | |> String.strip() 351 | another_string <> some_string 352 | 353 | # preferred 354 | some_string = 355 | "Hello" 356 | |> String.downcase() 357 | |> String.strip() 358 | 359 | another_string <> some_string 360 | ``` 361 | 362 | ```elixir 363 | # also not preferred 364 | something = 365 | if x == 2 do 366 | "Hi" 367 | else 368 | "Bye" 369 | end 370 | String.downcase(something) 371 | 372 | # preferred 373 | something = 374 | if x == 2 do 375 | "Hi" 376 | else 377 | "Bye" 378 | end 379 | 380 | String.downcase(something) 381 | ``` 382 | 383 | * 384 | Never use `do:` for multi-line `if/unless`. 385 | [[link](#do-with-multi-line-if-unless)] 386 | 387 | ```elixir 388 | # not preferred 389 | if some_condition, do: 390 | # a line of code 391 | # another line of code 392 | # note no end in this block 393 | 394 | # preferred 395 | if some_condition do 396 | # some 397 | # lines 398 | # of code 399 | end 400 | ``` 401 | 402 | * 403 | Use `do:` for single line `if/unless` statements. 404 | [[link](#do-with-single-line-if-unless)] 405 | 406 | ```elixir 407 | # preferred 408 | if some_condition, do: # some_stuff 409 | ``` 410 | 411 | * 412 | Never use `unless` with `else`. 413 | Rewrite these with the positive case first. 414 | [[link](#unless-with-else)] 415 | 416 | ```elixir 417 | # not preferred 418 | unless success? do 419 | IO.puts 'failure' 420 | else 421 | IO.puts 'success' 422 | end 423 | 424 | # preferred 425 | if success? do 426 | IO.puts 'success' 427 | else 428 | IO.puts 'failure' 429 | end 430 | ``` 431 | 432 | * 433 | Use `true` as the last condition of the `cond` special form when you need a 434 | clause that always matches. 435 | [[link](#true-as-last-condition)] 436 | 437 | ```elixir 438 | # not preferred 439 | cond do 440 | 1 + 2 == 5 -> 441 | "Nope" 442 | 1 + 3 == 5 -> 443 | "Uh, uh" 444 | :else -> 445 | "OK" 446 | end 447 | 448 | # preferred 449 | cond do 450 | 1 + 2 == 5 -> 451 | "Nope" 452 | 1 + 3 == 5 -> 453 | "Uh, uh" 454 | true -> 455 | "OK" 456 | end 457 | ``` 458 | 459 | * 460 | Never put a space between a function name and the opening parenthesis. 461 | [[link](#function-names-with-parentheses)] 462 | 463 | ```elixir 464 | # not preferred 465 | f (3 + 2) + 1 466 | 467 | # preferred 468 | f(3 + 2) + 1 469 | ``` 470 | 471 | * 472 | Use parentheses in function calls, especially inside a pipeline. 473 | [[link](#function-calls-and-parentheses)] 474 | 475 | ```elixir 476 | # not preferred 477 | f 3 478 | 479 | # preferred 480 | f(3) 481 | 482 | # not preferred and parses as rem(2, (3 |> g)), which is not what you want. 483 | 2 |> rem 3 |> g 484 | 485 | # preferred 486 | 2 |> rem(3) |> g 487 | ``` 488 | 489 | * 490 | Omit parentheses in macro calls when a do block is passed. 491 | [[link](#macro-calls-and-parentheses)] 492 | 493 | ```elixir 494 | # not preferred 495 | quote(do 496 | foo 497 | end) 498 | 499 | # preferred 500 | quote do 501 | foo 502 | end 503 | ``` 504 | 505 | * 506 | Optionally omit parentheses in function calls (outside a pipeline) when the 507 | last argument is a function expression. 508 | [[link](#parentheses-and-function-expressions)] 509 | 510 | ```elixir 511 | # preferred 512 | Enum.reduce(1..10, 0, fn x, acc -> 513 | x + acc 514 | end) 515 | 516 | # also preferred 517 | Enum.reduce 1..10, 0, fn x, acc -> 518 | x + acc 519 | end 520 | ``` 521 | 522 | * 523 | Use parentheses for calls to functions with zero arity, so they can be 524 | distinguished from variables. 525 | Starting in Elixir 1.4, the compiler will warn you about 526 | locations where this ambiguity exists. 527 | [[link](#parentheses-and-functions-with-zero-arity)] 528 | 529 | ```elixir 530 | defp do_stuff, do: ... 531 | 532 | # not preferred 533 | def my_func do 534 | do_stuff # is this a variable or a function call? 535 | end 536 | 537 | # preferred 538 | def my_func do 539 | do_stuff() # this is clearly a function call 540 | end 541 | ``` 542 | 543 | * 544 | Always use the special syntax for keyword lists. 545 | [[link](#keyword-list-syntax)] 546 | 547 | ```elixir 548 | # not preferred 549 | some_value = [{:a, "baz"}, {:b, "qux"}] 550 | 551 | # preferred 552 | some_value = [a: "baz", b: "qux"] 553 | ``` 554 | 555 | * 556 | Omit square brackets from keyword lists whenever they are optional. 557 | [[link](#keyword-list-brackets)] 558 | 559 | ```elixir 560 | # not preferred 561 | some_function(foo, bar, [a: "baz", b: "qux"]) 562 | 563 | # preferred 564 | some_function(foo, bar, a: "baz", b: "qux") 565 | ``` 566 | 567 | * 568 | Indent and align successive `with` clauses. 569 | Put the `do:` argument on a new line, indented normally. 570 | [[link](#with-clauses)] 571 | 572 | ```elixir 573 | with {:ok, foo} <- fetch(opts, :foo), 574 | {:ok, bar} <- fetch(opts, :bar), 575 | do: {:ok, foo, bar} 576 | ``` 577 | 578 | * 579 | If the `with` expression has a `do` block with more than one line, or has an 580 | `else` option, use multiline syntax. 581 | [[link](#with-else)] 582 | 583 | ```elixir 584 | with {:ok, foo} <- fetch(opts, :foo), 585 | {:ok, bar} <- fetch(opts, :bar) do 586 | {:ok, foo, bar} 587 | else 588 | :error -> 589 | {:error, :bad_arg} 590 | end 591 | ``` 592 | 593 | ### Naming 594 | 595 | * 596 | Use `snake_case` for atoms, functions and variables. 597 | [[link](#snake-case)] 598 | 599 | ```elixir 600 | # not preferred 601 | :"some atom" 602 | :SomeAtom 603 | :someAtom 604 | 605 | someVar = 5 606 | 607 | def someFunction do 608 | ... 609 | end 610 | 611 | def SomeFunction do 612 | ... 613 | end 614 | 615 | # preferred 616 | :some_atom 617 | 618 | some_var = 5 619 | 620 | def some_function do 621 | ... 622 | end 623 | ``` 624 | 625 | * 626 | Use `CamelCase` for modules (keep acronyms like HTTP, RFC, XML uppercase). 627 | [[link](#camel-case)] 628 | 629 | ```elixir 630 | # not preferred 631 | defmodule Somemodule do 632 | ... 633 | end 634 | 635 | defmodule Some_Module do 636 | ... 637 | end 638 | 639 | defmodule SomeXml do 640 | ... 641 | end 642 | 643 | # preferred 644 | defmodule SomeModule do 645 | ... 646 | end 647 | 648 | defmodule SomeXML do 649 | ... 650 | end 651 | ``` 652 | 653 | * 654 | The names of predicate macros (compile-time generated functions that return a 655 | boolean value) _that can be used within guards_ should be prefixed with `is_`. 656 | For a list of allowed expressions, see the [Guard][Guard Expressions] docs. 657 | [[link](#predicate-macro-names-with-guards)] 658 | 659 | ```elixir 660 | defmacro is_cool(var) do 661 | quote do: unquote(var) == "cool" 662 | end 663 | ``` 664 | 665 | * 666 | The names of predicate functions _that cannot be used within guards_ should 667 | have a trailing question mark (`?`) rather than the `is_` (or similar) prefix. 668 | [[link](#predicate-macro-names-no-guards)] 669 | 670 | ```elixir 671 | def cool?(var) do 672 | # Complex check if var is cool not possible in a pure function. 673 | end 674 | ``` 675 | 676 | * 677 | Private functions with the same name as public functions should start with 678 | `do_`. 679 | [[link](#private-functions-with-same-name-as-public)] 680 | 681 | ```elixir 682 | def sum(list), do: do_sum(list, 0) 683 | 684 | # private functions 685 | defp do_sum([], total), do: total 686 | defp do_sum([head | tail], total), do: do_sum(tail, head + total) 687 | ``` 688 | 689 | ### Comments 690 | 691 | * 692 | Write expressive code and try to convey your program's intention through 693 | control-flow, structure and naming. 694 | [[link](#expressive-code)] 695 | 696 | * 697 | Use one space between the leading `#` character of the comment and the text of 698 | the comment. 699 | [[link](#comment-leading-spaces)] 700 | 701 | ```elixir 702 | String.first(some_string) #not preferred 703 | String.first(some_string) # preferred 704 | ``` 705 | 706 | * 707 | Comments longer than a word are capitalized, and sentences use punctuation. 708 | Use [one space][Sentence Spacing] after periods. 709 | [[link](#comment-grammar)] 710 | 711 | ```elixir 712 | # not preferred 713 | # these lowercase comments are missing punctuation 714 | 715 | # preferred 716 | # Capitalization example 717 | # Use punctuation for complete sentences. 718 | ``` 719 | 720 | #### Comment Annotations 721 | 722 | * 723 | Annotations should usually be written on the line immediately above the 724 | relevant code. 725 | [[link](#annotations)] 726 | 727 | * 728 | The annotation keyword is uppercase, and is followed by a colon and a space, 729 | then a note describing the problem. 730 | [[link](#annotation-keyword)] 731 | 732 | ```elixir 733 | # TODO: Deprecate in v1.5. 734 | def some_function(arg), do: {:ok, arg} 735 | ``` 736 | 737 | * 738 | In cases where the problem is so obvious that any documentation would be 739 | redundant, annotations may be left at the end of the offending line with no 740 | note. 741 | This usage should be the exception and not the rule. 742 | [[link](#exceptions-to-annotations)] 743 | 744 | ```elixir 745 | start_task() 746 | Process.sleep(5000) # FIXME 747 | ``` 748 | 749 | * 750 | Use `TODO` to note missing features or functionality that should be added at a 751 | later date. 752 | [[link](#todo-notes)] 753 | 754 | * 755 | Use `FIXME` to note broken code that needs to be fixed. 756 | [[link](#fixme-notes)] 757 | 758 | * 759 | Use `OPTIMIZE` to note slow or inefficient code that may cause performance 760 | problems. 761 | [[link](#optimize-notes)] 762 | 763 | * 764 | Use `HACK` to note code smells where questionable coding practices were used 765 | and should be refactored away. 766 | [[link](#hack-notes)] 767 | 768 | * 769 | Use `REVIEW` to note anything that should be looked at to confirm it is 770 | working as intended. 771 | For example: `REVIEW: Are we sure this is how the client does X currently?` 772 | [[link](#review-notes)] 773 | 774 | * 775 | Use other custom annotation keywords if it feels appropriate, but be sure to 776 | document them in your project's `README` or similar. 777 | [[link](#custom-keywords)] 778 | 779 | ### Modules 780 | 781 | * 782 | Use one module per file unless the module is only used internally by another 783 | module (such as a test). 784 | [[link](#one-module-per-file)] 785 | 786 | * 787 | Use `snake_case` file names for `CamelCase` module names. 788 | [[link](#underscored-filenames)] 789 | 790 | ```elixir 791 | # file is called some_module.ex 792 | 793 | defmodule SomeModule do 794 | end 795 | ``` 796 | 797 | * 798 | Represent each level of nesting within a module name as a directory. 799 | [[link](#module-name-nesting)] 800 | 801 | ```elixir 802 | # file is called parser/core/xml_parser.ex 803 | 804 | defmodule Parser.Core.XMLParser do 805 | end 806 | ``` 807 | 808 | * 809 | Don't put a blank line after `defmodule`. 810 | [[link](#defmodule-spacing)] 811 | 812 | * 813 | Put a blank line after module-level code blocks. 814 | [[link](#module-block-spacing)] 815 | 816 | * 817 | List module attributes and directives in the following order: 818 | [[link](#module-attribute-ordering)] 819 | 820 | 1. `@moduledoc` 821 | 1. `@behaviour` 822 | 1. `use` 823 | 1. `import` 824 | 1. `alias` 825 | 1. `require` 826 | 1. `defstruct` 827 | 1. `@type` 828 | 1. `@module_attribute` 829 | 1. `@callback` 830 | 1. `@macrocallback` 831 | 1. `@optional_callbacks` 832 | 833 | Add a blank line between each grouping, and sort the terms (like module names) 834 | alphabetically. 835 | Here's an overall example of how you should order things in your modules: 836 | 837 | ```elixir 838 | defmodule MyModule do 839 | @moduledoc """ 840 | An example module 841 | """ 842 | 843 | @behaviour MyBehaviour 844 | 845 | use GenServer 846 | 847 | import Something 848 | import SomethingElse 849 | 850 | alias My.Long.Module.Name 851 | alias My.Other.Module.Example 852 | 853 | require Integer 854 | 855 | defstruct name: nil, params: [] 856 | 857 | @type params :: [{binary, binary}] 858 | 859 | @module_attribute :foo 860 | @other_attribute 100 861 | 862 | @callback some_function(term) :: :ok | {:error, term} 863 | 864 | @macrocallback macro_name(term) :: Macro.t 865 | 866 | @optional_callbacks macro_name: 1 867 | 868 | ... 869 | end 870 | ``` 871 | 872 | * 873 | Use the `__MODULE__` pseudo variable when a module refers to itself. This 874 | avoids having to update any self-references when the module name changes. 875 | [[link](#module-pseudo-variable)] 876 | 877 | ```elixir 878 | defmodule SomeProject.SomeModule do 879 | defstruct [:name] 880 | 881 | def name(%__MODULE__{name: name}), do: name 882 | end 883 | ``` 884 | 885 | * 886 | If you want a prettier name for a module self-reference, set up an alias. 887 | [[link](#alias-self-referencing-modules)] 888 | 889 | ```elixir 890 | defmodule SomeProject.SomeModule do 891 | alias __MODULE__, as: SomeModule 892 | 893 | defstruct [:name] 894 | 895 | def name(%SomeModule{name: name}), do: name 896 | end 897 | ``` 898 | 899 | * 900 | Avoid repeating fragments in module names and namespaces. 901 | This improves overall readability and 902 | eliminates [ambiguous aliases][Conflicting Aliases]. 903 | [[link](#repetitive-module-names)] 904 | 905 | ```elixir 906 | # not preferred 907 | defmodule Todo.Todo do 908 | ... 909 | end 910 | 911 | # preferred 912 | defmodule Todo.Item do 913 | ... 914 | end 915 | ``` 916 | 917 | ### Documentation 918 | 919 | Documentation in Elixir (when read either in `iex` with `h` or generated with 920 | [ExDoc]) uses the [Module Attributes] `@moduledoc` and `@doc`. 921 | 922 | * 923 | Always include a `@moduledoc` attribute in the line right after `defmodule` in 924 | your module. 925 | [[link](#moduledocs)] 926 | 927 | ```elixir 928 | # not preferred 929 | 930 | defmodule SomeModule do 931 | 932 | @moduledoc """ 933 | About the module 934 | """ 935 | ... 936 | end 937 | 938 | defmodule AnotherModule do 939 | use SomeModule 940 | @moduledoc """ 941 | About the module 942 | """ 943 | ... 944 | end 945 | 946 | # preferred 947 | 948 | defmodule SomeModule do 949 | @moduledoc """ 950 | About the module 951 | """ 952 | ... 953 | end 954 | ``` 955 | 956 | * 957 | Use `@moduledoc false` if you do not intend on documenting the module. 958 | [[link](#moduledoc-false)] 959 | 960 | ```elixir 961 | defmodule SomeModule do 962 | @moduledoc false 963 | ... 964 | end 965 | ``` 966 | 967 | * 968 | Separate code after the `@moduledoc` with a blank line. 969 | [[link](#moduledoc-spacing)] 970 | 971 | ```elixir 972 | # not preferred 973 | 974 | defmodule SomeModule do 975 | @moduledoc """ 976 | About the module 977 | """ 978 | use AnotherModule 979 | end 980 | 981 | # preferred 982 | defmodule SomeModule do 983 | @moduledoc """ 984 | About the module 985 | """ 986 | 987 | use AnotherModule 988 | end 989 | ``` 990 | 991 | * 992 | Use heredocs with markdown for documentation. 993 | [[link](#heredocs)] 994 | 995 | ```elixir 996 | # not preferred 997 | 998 | defmodule SomeModule do 999 | @moduledoc "About the module" 1000 | end 1001 | 1002 | defmodule SomeModule do 1003 | @moduledoc """ 1004 | About the module 1005 | 1006 | Examples: 1007 | iex> SomeModule.some_function 1008 | :result 1009 | """ 1010 | end 1011 | 1012 | # preferred 1013 | defmodule SomeModule do 1014 | @moduledoc """ 1015 | About the module 1016 | 1017 | ## Examples 1018 | 1019 | iex> SomeModule.some_function 1020 | :result 1021 | """ 1022 | end 1023 | ``` 1024 | 1025 | ### Typespecs 1026 | 1027 | Typespecs are notation for declaring types and specifications, for 1028 | documentation or for the static analysis tool Dialyzer. 1029 | 1030 | Custom types should be defined at the top of the module with the other 1031 | directives (see [Modules](#modules)). 1032 | 1033 | * 1034 | Place `@typedoc` and `@type` definitions together, and separate each 1035 | pair with a blank line. 1036 | [[link](#typedocs)] 1037 | 1038 | ```elixir 1039 | defmodule SomeModule do 1040 | @moduledoc false 1041 | 1042 | @typedoc "The name" 1043 | @type name :: atom 1044 | 1045 | @typedoc "The result" 1046 | @type result :: {:ok, term} | {:error, term} 1047 | 1048 | ... 1049 | end 1050 | ``` 1051 | 1052 | * 1053 | If a union type is too long to fit on a single line, add a newline 1054 | and indent with spaces to keep the types aligned. 1055 | [[link](#union-types)] 1056 | 1057 | ```elixir 1058 | # not preferred - no indentation 1059 | @type long_union_type :: some_type | another_type | some_other_type | 1060 | a_final_type 1061 | 1062 | # preferred 1063 | @type long_union_type :: some_type | another_type | some_other_type | 1064 | a_final_type 1065 | 1066 | # also preferred - one type per line 1067 | @type long_union_type :: some_type | 1068 | another_type | 1069 | some_other_type | 1070 | a_final_type 1071 | ``` 1072 | 1073 | * 1074 | Name the main type for a module `t`, for example: the type specification for a 1075 | struct. 1076 | [[link](#naming-main-types)] 1077 | 1078 | ```elixir 1079 | defstruct name: nil, params: [] 1080 | 1081 | @type t :: %__MODULE__{ 1082 | name: String.t | nil, 1083 | params: Keyword.t 1084 | } 1085 | ``` 1086 | 1087 | * 1088 | Place specifications right before the function definition, 1089 | without separating them by a blank line. 1090 | [[link](#spec-spacing)] 1091 | 1092 | ```elixir 1093 | @spec some_function(term) :: result 1094 | def some_function(some_data) do 1095 | {:ok, some_data} 1096 | end 1097 | ``` 1098 | 1099 | ### Structs 1100 | 1101 | * 1102 | Use a list of atoms for struct fields that default to `nil`, followed by the 1103 | other keywords. 1104 | [[link](#nil-struct-field-defaults)] 1105 | 1106 | ```elixir 1107 | # not preferred 1108 | defstruct name: nil, params: nil, active: true 1109 | 1110 | # preferred 1111 | defstruct [:name, :params, active: true] 1112 | ``` 1113 | 1114 | * 1115 | Omit square brackets when the argument of a `defstruct` is a keyword list. 1116 | [[link](#struct-def-brackets)] 1117 | 1118 | ```elixir 1119 | # not preferred 1120 | defstruct [params: [], active: true] 1121 | 1122 | # preferred 1123 | defstruct params: [], active: true 1124 | 1125 | # required - brackets are not optional, with at least one atom in the list 1126 | defstruct [:name, params: [], active: true] 1127 | ``` 1128 | 1129 | * 1130 | Indent additional lines of the struct definition, keeping the first keys 1131 | aligned. 1132 | [[link](#additional-struct-def-lines)] 1133 | 1134 | ```elixir 1135 | defstruct foo: "test", bar: true, baz: false, 1136 | qux: false, quux: 1 1137 | ``` 1138 | 1139 | ### Exceptions 1140 | 1141 | * 1142 | Make exception names end with a trailing `Error`. 1143 | [[link](#exception-names)] 1144 | 1145 | ```elixir 1146 | # not preferred 1147 | defmodule BadHTTPCode do 1148 | defexception [:message] 1149 | end 1150 | 1151 | defmodule BadHTTPCodeException do 1152 | defexception [:message] 1153 | end 1154 | 1155 | # preferred 1156 | defmodule BadHTTPCodeError do 1157 | defexception [:message] 1158 | end 1159 | ``` 1160 | 1161 | * 1162 | Use lowercase error messages when raising exceptions, with no trailing 1163 | punctuation. 1164 | [[link](#lowercase-error-messages)] 1165 | 1166 | ```elixir 1167 | # not preferred 1168 | raise ArgumentError, "This is not valid." 1169 | 1170 | # preferred 1171 | raise ArgumentError, "this is not valid" 1172 | ``` 1173 | 1174 | ### Collections 1175 | 1176 | _No guidelines for collections have been added yet._ 1177 | 1178 | ### Strings 1179 | 1180 | * 1181 | Match strings using the string concatenator rather than binary patterns: 1182 | [[link](#strings-matching-with-concatenator)] 1183 | 1184 | ```elixir 1185 | # not preferred 1186 | <<"my"::utf8, _rest>> = "my string" 1187 | 1188 | # preferred 1189 | "my" <> _rest = "my string" 1190 | ``` 1191 | 1192 | ### Regular Expressions 1193 | 1194 | _No guidelines for regular expressions have been added yet._ 1195 | 1196 | ### Metaprogramming 1197 | 1198 | * 1199 | Avoid needless metaprogramming. 1200 | [[link](#avoid-metaprogramming)] 1201 | 1202 | ### Testing 1203 | 1204 | * 1205 | When writing [ExUnit] assertions, be consistent with the order of the expected 1206 | and actual values under testing. 1207 | Prefer placing the expected result on the right, unless the assertion is a 1208 | pattern match. 1209 | [[link](#testing-assert-order)] 1210 | 1211 | ```elixir 1212 | # preferred - expected result on the right 1213 | assert actual_function(1) == true 1214 | assert actual_function(2) == false 1215 | 1216 | # not preferred - inconsistent order 1217 | assert actual_function(1) == true 1218 | assert false == actual_function(2) 1219 | 1220 | # required - the assertion is a pattern match 1221 | assert {:ok, expected} = actual_function(3) 1222 | ``` 1223 | 1224 | ### Alternative Style Guides 1225 | 1226 | * [Aleksei Magusev's Elixir Style Guide](https://github.com/lexmag/elixir-style-guide#readme) 1227 | — An opinionated Elixir style guide stemming from the coding style practiced 1228 | in the Elixir core libraries. 1229 | Developed by [Aleksei Magusev](https://github.com/lexmag) and 1230 | [Andrea Leopardi](https://github.com/whatyouhide), members of Elixir core team. 1231 | While the Elixir project doesn't adhere to any specific style guide, 1232 | this is the closest available guide to its conventions. 1233 | 1234 | * [Credo's Elixir Style Guide](https://github.com/rrrene/elixir-style-guide#readme) 1235 | — Style Guide for the Elixir language, implemented by 1236 | [Credo](http://credo-ci.org) static code analysis tool. 1237 | 1238 | ### Tools 1239 | 1240 | Refer to [Awesome Elixir][Code Analysis] for libraries and tools that can help 1241 | with code analysis and style linting. 1242 | 1243 | ## Getting Involved 1244 | 1245 | ### Contributing 1246 | 1247 | It's our hope that this will become a central hub for community discussion on 1248 | best practices in Elixir. 1249 | Feel free to open tickets or send pull requests with improvements. 1250 | Thanks in advance for your help! 1251 | 1252 | Check the [contributing guidelines][Contributing] 1253 | and [code of conduct][Code Of Conduct] for more information. 1254 | 1255 | ### Spread the Word 1256 | 1257 | A community style guide is meaningless without the community's support. Please 1258 | tweet, [star][Stargazers], and let any Elixir programmer know 1259 | about [this guide][Elixir Style Guide] so they can contribute. 1260 | 1261 | ## Copying 1262 | 1263 | ### License 1264 | 1265 | ![Creative Commons License](http://i.creativecommons.org/l/by/3.0/88x31.png) 1266 | This work is licensed under a 1267 | [Creative Commons Attribution 3.0 Unported License][License] 1268 | 1269 | ### Attribution 1270 | 1271 | The structure of this guide, bits of example code, and many of the initial 1272 | points made in this document were borrowed from the [Ruby community style guide]. 1273 | A lot of things were applicable to Elixir and allowed us to get _some_ document 1274 | out quicker to start the conversation. 1275 | 1276 | Here's the [list of people who have kindly contributed][Contributors] to this 1277 | project. 1278 | 1279 | 1280 | [Chinese Traditional]: https://github.com/elixirtw/elixir_style_guide/blob/master/README_zhTW.md 1281 | [Code Analysis]: https://github.com/h4cc/awesome-elixir#code-analysis 1282 | [Code Of Conduct]: https://github.com/christopheradams/elixir_style_guide/blob/master/CODE_OF_CONDUCT.md 1283 | [Conflicting Aliases]: https://elixirforum.com/t/using-aliases-for-fubar-fubar-named-module/1723 1284 | [Contributing]: https://github.com/elixir-lang/elixir/blob/master/CODE_OF_CONDUCT.md 1285 | [Contributors]: https://github.com/christopheradams/elixir_style_guide/graphs/contributors 1286 | [Elixir Style Guide]: https://github.com/christopheradams/elixir_style_guide 1287 | [Elixir]: http://elixir-lang.org 1288 | [ExDoc]: https://github.com/elixir-lang/ex_doc 1289 | [ExUnit]: https://hexdocs.pm/ex_unit/ExUnit.html 1290 | [Guard Expressions]: http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses 1291 | [Hex]: https://hex.pm/packages 1292 | [Japanese]: https://github.com/kenichirow/elixir_style_guide/blob/master/README-jaJP.md 1293 | [Korean]: https://github.com/marocchino/elixir_style_guide/blob/new-korean/README-koKR.md 1294 | [License]: http://creativecommons.org/licenses/by/3.0/deed.en_US 1295 | [Module Attributes]: http://elixir-lang.org/getting-started/module-attributes.html#as-annotations 1296 | [Portuguese]: https://github.com/gusaiani/elixir_style_guide/blob/master/README_ptBR.md 1297 | [Ruby community style guide]: https://github.com/bbatsov/ruby-style-guide 1298 | [Sentence Spacing]: http://en.wikipedia.org/wiki/Sentence_spacing 1299 | [Spanish]: https://github.com/albertoalmagro/elixir_style_guide/blob/spanish/README_esES.md 1300 | [Stargazers]: https://github.com/christopheradams/elixir_style_guide/stargazers 1301 | 1302 | -------------------------------------------------------------------------------- /README_ptBR.md: -------------------------------------------------------------------------------- 1 | # [O Guia de Estilo Elixir][Guia de Estilo Elixir] 2 | 3 | ## Índice 4 | 5 | * __[Introdução](#introducao)__ 6 | * __[O Guia de Estilo Elixir](#o-guia)__ 7 | * [Layout do Código](#layout-codigo) 8 | * [Sintaxe](#sintaxe) 9 | * [Nomenclatura](#nomenclatura) 10 | * [Comentários](#comentarios) 11 | * [Anotações em Comentários](#anotacoes-comentarios) 12 | * [Módulos](#modulos) 13 | * [Documentação](#documentacao) 14 | * [Typespecs](#typespecs) 15 | * [Structs](#structs) 16 | * [Exceções](#excecoes) 17 | * _Coleções_ 18 | * [Strings](#strings) 19 | * _Expressões Regulares_ 20 | * [Metaprogramação](#metaprogramming) 21 | * [Testes](#testes) 22 | * [Guias de Estilo Alternativos](#guias-estilo-alternativos) 23 | * [Ferramentas](#ferramentas) 24 | * __[Participando](#participando)__ 25 | * [Contribuindo](#contribuindo) 26 | * [Espalhe](#espalhe) 27 | * __[Cópias](#copias)__ 28 | * [Licença](#licenca) 29 | * [Atribuição](#atribuicao) 30 | 31 | ## Introdução 32 | 33 | > Arquitetura líquida. É como o jazz - você improvisa, você trabalha junto, 34 | > você se inspira nos outros, você cria alguma coisa, eles criam alguma coisa. 35 | > 36 | > —Frank Gehry 37 | 38 | Estilo é importante. 39 | [Elixir] tem muito estilo, mas como todas as linguagens, ele pode ser estragado. 40 | Não estrague o estilo. 41 | 42 | ## O Guia 43 | 44 | Este é o guia de estilo da comunidade para a [Linguagem de Programação Elixir][Elixir]. 45 | Sinta-se à vontade para enviar pull requests e sugestões, e seja parte da 46 | vibrante comunidade do Elixir. 47 | 48 | Se você está procurando outros projetos para contribuir, por gentileza confira o [site do gerenciador de pacotes Hex][Hex]. 49 | 50 | 51 | Traduções deste guia estão disponíveis nas seguintes línguas: 52 | 53 | * [Chinês Tradicional] 54 | * [Coreano] 55 | * [Espanhol] 56 | * [Inglês] 57 | * [Japonês] 58 | * [Português] 59 | 60 | ### Layout do Código Fonte 61 | 62 | * 63 | Use dois **espaços** por nível de recuo. 64 | Não use hard tabs. 65 | [[link](#indentacao-com-espacos)] 66 | 67 | ```elixir 68 | # não recomendado - quatro espaços 69 | def alguma_funcao do 70 | fazer_algo 71 | end 72 | 73 | # recomendado 74 | def alguma_funcao do 75 | fazer_algo 76 | end 77 | ``` 78 | 79 | * 80 | Use quebra de linha estilo Unix (\*Usuários de BSD/Solaris/Linux/OSX por padrão 81 | estão cobertos, usuários Windows tem que tomar muito cuidado). 82 | [[link](#quebra-de-linha)] 83 | 84 | * 85 | Se você está usando Git talvez você queira adicionar a seguinte 86 | configuração para evitar quebras de linha Windows adicionadas acidentalmente: 87 | [[link](#autocrlf)] 88 | 89 | ```sh 90 | git config --global core.autocrlf true 91 | ``` 92 | 93 | * 94 | Use espaço ao redor de operadores, depois de vírgulas, dois pontos e ponto e vírgulas. 95 | Não coloque espaço ao redor de pares correspondentes como parênteses, colchetes e chaves. 96 | Espaço pode ser (na maioria das vezes) irrelevante no runtime do Elixir, mas 97 | seu uso apropriado é essencial para se escrever código leǵivel. 98 | [[link](#espacos)] 99 | 100 | ```elixir 101 | soma = 1 + 2 102 | {a, b} = {2, 3} 103 | [primeiro | resto] = [1, 2, 3] 104 | Enum.map(["um", <<"dois">>, "três"], fn num -> IO.puts num end) 105 | ``` 106 | 107 | * 108 | Não use espaço depois de operadores que não são palavras e recebem um argumento; 109 | ou ao redor do operador range. 110 | [[link](#sem-espacos)] 111 | 112 | ```elixir 113 | 0 - 1 == -1 114 | ^pinned = alguma_funcao() 115 | 5 in 1..10 116 | ``` 117 | 118 | * 119 | Use linhas em branco entre `def`s para quebrar uma função em seus parágrafos 120 | lógicos. 121 | [[link](#espacamento-def)] 122 | 123 | ```elixir 124 | def alguma_funcao(algum_dado) do 125 | dado_alterado = Module.function(algum_dado) 126 | end 127 | 128 | def alguma_funcao do 129 | resultado 130 | end 131 | 132 | def alguma_outra_funcao do 133 | outro_resultado 134 | end 135 | 136 | def uma_funcao_mais_longa do 137 | um 138 | dois 139 | 140 | três 141 | quatro 142 | end 143 | ``` 144 | 145 | * 146 | ...mas coloque junto `def`s de uma linha só que correspondam à mesma função. 147 | [[link](#defs-de-uma-linha)] 148 | 149 | ```elixir 150 | def alguma_funcao(nil), do: {:err, "Nenhum Valor"} 151 | def alguma_funcao([]), do: :ok 152 | def alguma_funcao([primeiro | resto]) do 153 | alguma_funcao(resto) 154 | end 155 | ``` 156 | 157 | * 158 | Se você usar a sintaxe `do:` em funções, e o corpo da função tiver uma linha longa, coloque o `do:` em uma nova linha com um nível de indentação a mais do que a linha anterior. 159 | [[link](#dos-longos)] 160 | 161 | ```elixir 162 | def alguma_funcao(args), 163 | do: Enum.map(args, fn(arg) -> arg <> " está em uma linha muito longa!" end) 164 | ``` 165 | 166 | Quando você usar a convenção acima e tiver mais que uma cláusula 167 | usando a sintaxe `do:`, coloque o `do:` em uma nova linha para cada cláusula: 168 | 169 | ```elixir 170 | # não recomendado 171 | def alguma_funcao([]), do: :vazio 172 | def alguma_funcao(_), 173 | do: :linha_muito_longa_aqui 174 | 175 | # recomendado 176 | def alguma_funcao([]), 177 | do: :vazio 178 | def alguma_funcao(_), 179 | do: :linha_muito_longa_aqui 180 | ``` 181 | 182 | * 183 | Se você tiver mais que um `def` multilinha, não use `def`s de uma linha. 184 | [[link](#multiplos-defs-funcao)] 185 | 186 | ```elixir 187 | def alguma_funcao(nil) do 188 | {:err, "Nenhum Valor"} 189 | end 190 | 191 | def alguma_funcao([]) do 192 | :ok 193 | end 194 | 195 | def alguma_funcao([primeiro | resto]) do 196 | alguma_funcao(resto) 197 | end 198 | 199 | def alguma_funcao([primeiro | resto], opts) do 200 | alguma_funcao(resto, opts) 201 | end 202 | ``` 203 | 204 | * 205 | Use parênteses em funções de aridade um ao usar o operador 206 | pipe (`|>`) 207 | [[link](#operador-pipe-parenteses)] 208 | 209 | ```elixir 210 | # não recomendado 211 | alguma_string |> String.downcase |> String.strip 212 | 213 | # recomendado 214 | alguma_string |> String.downcase() |> String.strip() 215 | ``` 216 | 217 | * 218 | Use o operador pipe (`|>`) para encadear funções. 219 | [[link](#operador-pipe)] 220 | 221 | ```elixir 222 | # não recomendado 223 | String.strip(String.downcase(alguma_string)) 224 | 225 | # recomendado 226 | alguma_string |> String.downcase |> String.strip 227 | 228 | # Pipelines multilinha não recebem indentação extra 229 | alguma_string 230 | |> String.downcase 231 | |> String.strip 232 | 233 | # Pipelines multilinha do lado direito de um pattern match 234 | # devem ser indentados em uma nova linha 235 | string_sanitizada = 236 | alguma_string 237 | |> String.downcase 238 | |> String.strip 239 | ``` 240 | 241 | Mesmo este sendo o método recomendado, lembre-se que copiar e colar 242 | pipelines multilinha no IEx pode resultar em erro de sintaxe, já que o 243 | IEx vai avaliar a primeira linha sem perceber que a próxima linha tem um pipeline. 244 | 245 | * 246 | Evite usar o operador pipe uma vez só. 247 | [[link](#evite-pipelines-solitarios)] 248 | 249 | ```elixir 250 | # não recomendado 251 | alguma_string |> String.downcase 252 | 253 | # recomendado 254 | String.downcase(alguma_string) 255 | ``` 256 | 257 | * 258 | Use variáveis _sozinhas_ na primeira parte de uma cadeia de funções. 259 | [[link](#variaveis-sozinhas)] 260 | 261 | ```elixir 262 | # PIOR JEITO! 263 | # Isto é interpretado como String.strip("não" |> String.downcase). 264 | String.strip "não" |> String.downcase() 265 | 266 | # não recomendado 267 | String.strip(alguma_string) |> String.downcase() |> String.codepoints() 268 | 269 | # recomendado 270 | alguma_string |> String.strip() |> String.downcase() |> String.codepoints() 271 | ``` 272 | 273 | * 274 | Ao declarar uma linha que abrange múltiplas linhas, comece a lista em uma nova linha, 275 | e indente os elementos para mantê-los alinhados. 276 | [[link](#declaracao-list-multilinha)] 277 | 278 | ```elixir 279 | # não recomendado - sem indentação 280 | lista = [:primeiro_item, :segundo_item, :proximo_item, 281 | :ultimo_item] 282 | 283 | # melhor, mas não recomendado - com indentação 284 | lista = [:primeiro_item, :segundo_item, :proximo_item, 285 | :ultimo_item] 286 | 287 | # recomendado - lista começa em uma linha própria 288 | # bom para listas menores 289 | lista = 290 | [:primeiro_item, :segundo_item, :proximo_item, 291 | :ultimo_item] 292 | 293 | # também recomendado - com cada elemento em uma linha 294 | # bom para listas longas, listas com elementos longos ou listas com comentários 295 | lista = [ 296 | :primeiro_item, 297 | :segundo_item, 298 | :proximo_item, 299 | # comentário 300 | :muitos_itens, 301 | :ultimo_item 302 | ] 303 | ``` 304 | 305 | * 306 | Evite espaço em branco no fim das linhas 307 | [[link](#espaco-branco-direita)] 308 | 309 | * 310 | Termine todos os arquivos com uma nova linha. 311 | [[link](#eof-nova-linha)] 312 | 313 | ### Sintaxe 314 | 315 | * 316 | Use parênteses quando um `def` tiver argumentos, e omita os parênteses quando ele não tiver argumentos. 317 | [[link](#parenteses)] 318 | 319 | ```elixir 320 | # não recomendado 321 | def alguma_funcao arg1, arg2 do 322 | # corpo omitido 323 | end 324 | 325 | def alguma_funcao() do 326 | # corpo omitido 327 | end 328 | 329 | # recomendado 330 | def alguma_funcao(arg1, arg2) do 331 | # corpo omitido 332 | end 333 | 334 | def alguma_funcao do 335 | # corpo omitido 336 | end 337 | ``` 338 | 339 | * 340 | Adicione uma linha em branco após uma declaração multilinha 341 | sinalizando que a declaração terminou. 342 | [[link](#adicione-linha-em-branco-apos-declaracao-multilinha)] 343 | 344 | ```elixir 345 | # não recomendado 346 | alguma_string = 347 | "Oi" 348 | |> String.downcase 349 | |> String.strip 350 | outra_string <> alguma_string 351 | 352 | # recomendado 353 | alguma_string = 354 | "Oi" 355 | |> String.downcase 356 | |> String.strip 357 | 358 | outra_string <> alguma_string 359 | ``` 360 | 361 | ```elixir 362 | # também não recomendado 363 | alguma_coisa = 364 | if x == 2 do 365 | "Oi" 366 | else 367 | "Tchau" 368 | end 369 | String.downcase(alguma_coisa) 370 | 371 | # recomendado 372 | alguma_coisa = 373 | if x == 2 do 374 | "Oi" 375 | else 376 | "Tchau" 377 | end 378 | 379 | String.downcase(alguma_coisa) 380 | ``` 381 | 382 | * 383 | Nunca use `do:` para `if` ou `unless` multilinha. 384 | [[link](#do-com-if-unless-multilinha)] 385 | 386 | ```elixir 387 | # não recomendado 388 | if alguma_condicao, do: 389 | # uma linha de código 390 | # outra linha de código 391 | # note que este bloco não tem end 392 | 393 | # recomendado 394 | if alguma_condicao do 395 | # algumas 396 | # linhas 397 | # de código 398 | end 399 | ``` 400 | 401 | * 402 | Use `do:` para `if/unless` de uma linha só. 403 | [[link](#do-de-uma-linha-só-if-unless)] 404 | 405 | ```elixir 406 | # recomendado 407 | if alguma_condicao, do: # alguma_coisa 408 | ``` 409 | 410 | * 411 | Nunca use `unless` com `else`. 412 | Reescreva estes com apenas casos positivos. 413 | [[link](#unless-com-else)] 414 | 415 | ```elixir 416 | # não recomendado 417 | unless successo? do 418 | IO.puts 'falha' 419 | else 420 | IO.puts 'successo' 421 | end 422 | 423 | # recomendado 424 | if successo? do 425 | IO.puts 'successo' 426 | else 427 | IO.puts 'falha' 428 | end 429 | ``` 430 | 431 | * 432 | Use `true` como a última condição do `cond` quando você precisa de uma 433 | cláusula que sempre dê match. 434 | [[link](#true-como-ultima-condicao)] 435 | 436 | ```elixir 437 | # não recomendado 438 | cond do 439 | 1 + 2 == 5 -> 440 | "Não" 441 | 1 + 3 == 5 -> 442 | "Oh, oh" 443 | :else -> 444 | "OK" 445 | end 446 | 447 | # recomendado 448 | cond do 449 | 1 + 2 == 5 -> 450 | "Não" 451 | 1 + 3 == 5 -> 452 | "Oh, oh" 453 | true -> 454 | "OK" 455 | end 456 | ``` 457 | 458 | * 459 | Nunca coloque um espaço entre o nome da função e a abertura dos parênteses. 460 | [[link](#nomes-de-funcao-com-parenteses)] 461 | 462 | ```elixir 463 | # não recomendado 464 | f (3 + 2) + 1 465 | 466 | # recomendado 467 | f(3 + 2) + 1 468 | ``` 469 | 470 | * 471 | Use parênteses em chamadas de função, especialmente dentro de uma pipeline. 472 | [[link](#chamada-de-funcao-com-parentese)] 473 | 474 | ```elixir 475 | # não recomendado 476 | f 3 477 | 478 | # recomendado 479 | f(3) 480 | 481 | # não recomendado e é convertido como rem(2, (3 |> g)), que não é o que você quer. 482 | 2 |> rem 3 |> g 483 | 484 | # recomendado 485 | 2 |> rem(3) |> g 486 | ``` 487 | 488 | * 489 | Omita parênteses em chamadas de macro onde um bloco `do` é passado. 490 | [[link](#chamadas-de-macro-e-parênteses)] 491 | 492 | ```elixir 493 | # não recomendado 494 | quote(do 495 | foo 496 | end) 497 | 498 | # recomendado 499 | quote do 500 | foo 501 | end 502 | ``` 503 | 504 | * 505 | Parênteses são opcionais em chamadas de função (fora de pipelines) quando o 506 | último argumento é uma expressão de função. 507 | [[link](#parenteses-e-expressoes-de-funcoes)] 508 | 509 | ```elixir 510 | # recomendado 511 | Enum.reduce(1..10, 0, fn x, acc -> 512 | x + acc 513 | end) 514 | 515 | # também recomendado 516 | Enum.reduce 1..10, 0, fn x, acc -> 517 | x + acc 518 | end 519 | ``` 520 | 521 | * 522 | Use parênteses quando chamar funções de aridade zero, para que elas 523 | fiquem distintas de variáveis. 524 | A partir do Elixir 1.4 o compilador vai emitir `warnings` em lugares onde 525 | esta ambiguidade existir. 526 | [[link](#parenteses-e-funcoes-aridade-zero)] 527 | 528 | ```elixir 529 | defp fazer_algo, do: ... 530 | 531 | # não recomendado 532 | def minha_funcao do 533 | fazer_algo # isto é uma variável ou uma chamada de função? 534 | end 535 | 536 | # recomendado 537 | def minha_funcao do 538 | fazer_algo() # isto claramente é uma chamada de função 539 | end 540 | ``` 541 | 542 | * 543 | Sempre use a sintaxe simplificada para listas de palavras-chave. 544 | [[link](#sintaxe-listas-palavra-chave)] 545 | 546 | ```elixir 547 | # não recomendado 548 | algum_valor = [{:a, "baz"}, {:b, "qux"}] 549 | 550 | # recomendado 551 | algum_valor = [a: "baz", b: "qux"] 552 | ``` 553 | 554 | * 555 | Omita colchetes de listas de palavras-chave sempre que eles forem opcionais. 556 | [[link](#colchetes-listas-palavras-chave)] 557 | 558 | ```elixir 559 | # não recomendado 560 | alguma_funcao(foo, bar, [a: "baz", b: "qux"]) 561 | 562 | # recomendado 563 | alguma_funcao(foo, bar, a: "baz", b: "qux") 564 | ``` 565 | 566 | * 567 | Indente e alinhe cláusulas `with` sucessivas. 568 | Coloque o argumento `do:` em uma nova linha, indentada normalmente. 569 | [[link](#clausulas-with)] 570 | 571 | ```elixir 572 | with {:ok, foo} <- fetch(opts, :foo), 573 | {:ok, bar} <- fetch(opts, :bar), 574 | do: {:ok, foo, bar} 575 | ``` 576 | 577 | * 578 | Se a expressão `with` tiver um bloco `do` com mais de uma linha, ou tem uma 579 | opção `else`, use a sintaxe multilinha. 580 | [[link](#with-else)] 581 | 582 | ```elixir 583 | with {:ok, foo} <- fetch(opts, :foo), 584 | {:ok, bar} <- fetch(opts, :bar) do 585 | {:ok, foo, bar} 586 | else 587 | :error -> 588 | {:error, :bad_arg} 589 | end 590 | ``` 591 | 592 | ### Nomenclatura 593 | 594 | * 595 | Use `snake_case` para átomos, funções e variáveis. 596 | [[link](#snake-case)] 597 | 598 | ```elixir 599 | # não recomendado 600 | :"algum átomo" 601 | :AlgumAtomo 602 | :algumAtomo 603 | 604 | algumaVar = 5 605 | 606 | def algumaFuncao do 607 | ... 608 | end 609 | 610 | def AlgumaFuncao do 611 | ... 612 | end 613 | 614 | # recomendado 615 | :algum_atom 616 | 617 | alguma_var = 5 618 | 619 | def alguma_funcao do 620 | ... 621 | end 622 | ``` 623 | 624 | * 625 | Use `CamelCase` para módulos (mantenha siglas como HTTP, RFC, XML em maiúsculo). 626 | [[link](#camel-case)] 627 | 628 | ```elixir 629 | # não recomendado 630 | defmodule Algummodulo do 631 | ... 632 | end 633 | 634 | defmodule Algum_Modulo do 635 | ... 636 | end 637 | 638 | defmodule AlgumXml do 639 | ... 640 | end 641 | 642 | # recomendado 643 | defmodule AlgumModulo do 644 | ... 645 | end 646 | 647 | defmodule AlgumXML do 648 | ... 649 | end 650 | ``` 651 | 652 | * 653 | Os nomes das macros com predicado (funções geradas na hora da compilação que retornam um 654 | valor booleano) _que podem ser usadas dentro de guards_ devem ser prefixados com `is_`. 655 | Para uma lista de expressões permitidas, veja nos documentos [Guard][Guard Expressions]. 656 | [[link](#nome-de-macro-com-predicado-em-guards)] 657 | 658 | ```elixir 659 | defmacro is_cool(var) do 660 | quote do: unquote(var) == "cool" 661 | end 662 | ``` 663 | 664 | * 665 | Os nomes de funções com predicados _que não podem ser usadas em guards_ devem 666 | ter um ponto de interrogação à direita (`?`) em vez do prefixo `is_` (ou similar). 667 | [[link](#nome-de-macro-de-predicado-sem-guards)] 668 | 669 | ```elixir 670 | def cool?(var) do 671 | # Verificação complexa se var for cool não é possível em uma função pura. 672 | end 673 | ``` 674 | 675 | * 676 | Funções privadas com o mesmo nome de funções públicas devem começar com `do_`. 677 | [[link](#funcoes-privadas-com-mesmo-nome-de-publicas)] 678 | 679 | ```elixir 680 | def soma(list), do: do_soma(list, 0) 681 | 682 | # funções privadas 683 | defp do_soma([], total), do: total 684 | defp do_soma([head | tail], total), do: do_soma(tail, head + total) 685 | ``` 686 | 687 | ### Comentários 688 | 689 | * 690 | Escreva código expressivo e busque transmitir a intenção do seu programa 691 | através de fluxo de controle, estrutura e nomenclaturas. 692 | [[link](#codigo-expressivo)] 693 | 694 | * 695 | Use um espaço entre o `#` do comentário e o texto do comentário. 696 | [[link](#comentários-espacos-esquerda)] 697 | 698 | ```elixir 699 | String.first(alguma_string) #não recomendado 700 | String.first(alguma_string) # recomendado 701 | ``` 702 | 703 | * 704 | Comentários de mais de uma palavra começam com maiúscula, e frases recebem pontuação. 705 | Use [um espaço][Sentence Spacing] depois dos pontos finais. 706 | [[link](#gramatica-comentario)] 707 | 708 | ```elixir 709 | # não recomendado 710 | # este comentário em minúsculas não tem pontuação 711 | 712 | # recomendado 713 | # Exemplo com maiúscula 714 | # Use pontuação em frases completas. 715 | ``` 716 | 717 | #### Anotações em Comentários 718 | 719 | * 720 | Anotações normalmente devem vir na linha imediatamente acima do 721 | respectivo código. 722 | [[link](#anotacoes)] 723 | 724 | * 725 | A palavra-chave de anotação é inteira em maiúsculas, seguida por dois-pontos e espaço, 726 | e então uma descrição do problema. 727 | [[link](#palavra-chave-anotacao)] 728 | 729 | ```elixir 730 | # TODO: Deprecate in v2.0. 731 | def alguma_funcao(arg), do: {:ok, arg} 732 | ``` 733 | 734 | * 735 | Nos casos em que o problema é tão óbvio que qualquer documentação seria 736 | redundante, as anotações podem vir no fim da linha em questão sem comentário adicional. 737 | Esta forma deve ser a exceção e não a regra. 738 | [[link](#excecoes-anotacoes)] 739 | 740 | ```elixir 741 | start_task() 742 | Process.sleep(5000) # FIXME 743 | ``` 744 | 745 | * 746 | Use `TODO` para anotar funcionalidades que faltam ou funcionalidades que devem 747 | ser acrescentadas no futuro. 748 | [[link](#notas-todo)] 749 | 750 | * 751 | Use `FIXME` para anotar código quebrado que precisa ser corrigido. 752 | [[link](#notas-fixme)] 753 | 754 | * 755 | Use `OPTIMIZE` para anotar código lento ou ineficiente que pode causar 756 | problemas de desempenho. 757 | [[link](#notas-optimize)] 758 | 759 | * 760 | Use `HACK` para anotar lugares onde existem práticas questionáveis e que 761 | deveriam ser refatoradas. 762 | [[link](#notas-hack)] 763 | 764 | * 765 | Use `REVIEW` para anotar qualquer coisa que precise ser revista para confirmar 766 | que está funcionando conforme pretendido. 767 | Exemplo: `REVIEW: Temos certeza que é assim que o cliente faz X hoje em dia?` 768 | [[link](#notas-review)] 769 | 770 | * 771 | Use outras palavras-chave customizadas se apropriado, mas se certifique de 772 | documentá-las no `README` do seu projeto ou algo similar. 773 | [[link](#palavras-chave-customizadas)] 774 | 775 | ### Módulos 776 | 777 | * 778 | Use um módulo por arquivo, a não ser que o módulo seja usado apenas 779 | internamente por outro módulo (um teste, por exemplo). 780 | [[link](#um-modulo-por-arquivo)] 781 | 782 | * 783 | Use nomes de arquivo em `snake_case` e nomes de módulo em`CamelCase`. 784 | [[link](#nomes-de-arquivo-underscore)] 785 | 786 | ```elixir 787 | # arquivo chamado algum_modulo.ex 788 | 789 | defmodule AlgumModulo do 790 | end 791 | ``` 792 | 793 | * 794 | Expresse cada nível de aninhamento em um nome de módulo como um diretório. 795 | [[link](#aninhamento-nomes-modulo)] 796 | 797 | ```elixir 798 | # arquivo chamado parser/core/xml_parser.ex 799 | 800 | defmodule Parser.Core.XMLParser do 801 | end 802 | ``` 803 | 804 | * 805 | Não use uma linha em branco após um `defmodule`. 806 | [[link](#espacamento-defmodule)] 807 | 808 | * 809 | Use uma linha em branco após blocos de código em módulos. 810 | [[link](#espacamento-blocos-module)] 811 | 812 | * 813 | Liste atributos e diretivas de módulo na seguinte ordem: 814 | [[link](#ordenacao-atributos-modulo)] 815 | 816 | 1. `@moduledoc` 817 | 1. `@behaviour` 818 | 1. `use` 819 | 1. `import` 820 | 1. `alias` 821 | 1. `require` 822 | 1. `defstruct` 823 | 1. `@type` 824 | 1. `@module_attribute` 825 | 1. `@callback` 826 | 1. `@macrocallback` 827 | 1. `@optional_callbacks` 828 | 829 | Adicione uma linha em branco entre cada agrupamento, e ordene os termos 830 | (como nomes de módulos) alfabeticamente. 831 | Abaixo um exemplo geral de como você deve ordenar as coisas em seus módulos: 832 | 833 | ```elixir 834 | defmodule MeuModulo do 835 | @moduledoc """ 836 | Exemplo de módulo 837 | """ 838 | 839 | @behaviour MeuBehaviour 840 | 841 | use GenServer 842 | 843 | import AlgumaCoisa 844 | import OutraCoisa 845 | 846 | alias Meu.Nome.Comprido.Modulo 847 | alias Meu.Outro.Exemplo.Modulo 848 | 849 | require Integer 850 | 851 | defstruct name: nil, params: [] 852 | 853 | @type params :: [{binary, binary}] 854 | 855 | @module_attribute :foo 856 | @other_attribute 100 857 | 858 | @callback alguma_funcao(termo) :: :ok | {:error, termo} 859 | 860 | @macrocallback nome_macro(termo) :: Macro.t 861 | 862 | @optional_callbacks nome_macro: 1 863 | 864 | ... 865 | end 866 | ``` 867 | 868 | * 869 | Use a pseudo variável `__MODULE__` quando um módulo se referir a si mesmo. 870 | Isto previne que tenhamos que atualizar auto-referências quando o nome do módulo mudar. 871 | [[link](#pseudo-variavel-modulo)] 872 | 873 | ```elixir 874 | defmodule AlgumProjeto.AlgumModulo do 875 | defstruct [:nome] 876 | 877 | def nome(%__MODULE__{nome: nome}), do: nome 878 | end 879 | ``` 880 | 881 | * 882 | Se você quiser um nome mais bonito para uma auto-referência de módulo, 883 | crie um alias. 884 | [[link](#alias-modulos-auto-referentes)] 885 | 886 | ```elixir 887 | defmodule AlgumProjeto.AlgumModulo do 888 | alias __MODULE__, as: AlgumModulo 889 | 890 | defstruct [:nome] 891 | 892 | def nome(%AlgumModulo{nome: nome}), do: nome 893 | end 894 | ``` 895 | 896 | * 897 | Evite repetir fragmentos em nomes e namespaces de módulos. 898 | Isto melhora a legibilidade e elimina [aliases ambíguos][Conflicting Aliases]. 899 | [[link](#nomes-modulo-repetitivos)] 900 | 901 | ```elixir 902 | # não recomendado 903 | defmodule Todo.Todo do 904 | ... 905 | end 906 | 907 | # recomendado 908 | defmodule Todo.Item do 909 | ... 910 | end 911 | ``` 912 | 913 | ### Documentação 914 | 915 | Documentação em Elixir (quando lida seja no `iex` com `h` seja gerada com 916 | [ExDoc]) usa os [Atributos de Módulo] `@moduledoc` e `@doc`. 917 | 918 | * 919 | Inclua sempre um atributo `@moduledoc` na linha imediatamente posterior ao `defmodule` 920 | em seu módulo. 921 | [[link](#moduledocs)] 922 | 923 | ```elixir 924 | # não recomendado 925 | 926 | defmodule AlgumModulo do 927 | 928 | @moduledoc """ 929 | Informação sobre o módulo. 930 | """ 931 | ... 932 | end 933 | 934 | defmodule OutroModulo do 935 | use AlgumModulo 936 | @moduledoc """ 937 | Informação sobre o módulo. 938 | """ 939 | ... 940 | end 941 | 942 | # recomendado 943 | 944 | defmodule AlgumModulo do 945 | @moduledoc """ 946 | Informação sobre o módulo. 947 | """ 948 | ... 949 | end 950 | ``` 951 | 952 | * 953 | Use `@moduledoc false` se você não pretende documentar o módulo. 954 | [[link](#moduledoc-false)] 955 | 956 | ```elixir 957 | defmodule AlgumModulo do 958 | @moduledoc false 959 | ... 960 | end 961 | ``` 962 | 963 | * 964 | Separe o código que vem depois do `@moduledoc` com uma linha em branco. 965 | [[link](#espacamento-moduledoc)] 966 | 967 | ```elixir 968 | # não recomendado 969 | 970 | defmodule AlgumModulo do 971 | @moduledoc """ 972 | Informação sobre o módulo. 973 | """ 974 | use OutroModulo 975 | end 976 | 977 | # recomendado 978 | defmodule AlgumModulo do 979 | @moduledoc """ 980 | Informação sobre o módulo. 981 | """ 982 | 983 | use OutroModulo 984 | end 985 | ``` 986 | 987 | * 988 | Use heredocs com markdown na documentação. 989 | [[link](#heredocs)] 990 | 991 | ```elixir 992 | # não recomendado 993 | 994 | defmodule AlgumModulo do 995 | @moduledoc "Informação sobre o módulo." 996 | end 997 | 998 | defmodule AlgumModulo do 999 | @moduledoc """ 1000 | Informação sobre o módulo. 1001 | 1002 | Exemplos: 1003 | iex> AlgumModulo.alguma_funcao 1004 | :resultado 1005 | """ 1006 | end 1007 | 1008 | # recomendado 1009 | defmodule AlgumModulo do 1010 | @moduledoc """ 1011 | Informação sobre o módulo. 1012 | 1013 | ## Exemplos 1014 | 1015 | iex> AlgumModulo.alguma_funcao 1016 | :resultado 1017 | """ 1018 | end 1019 | ``` 1020 | 1021 | ### Typespecs 1022 | 1023 | Typespecs são notações para declarar tipos e especificações, 1024 | para documentação ou para o Dialyzer (ferramenta de 1025 | análise estática). 1026 | 1027 | Tipos customizados devem ser definidos no topo do módulo com as outras 1028 | diretivas (veja [Módulos](#modulos)). 1029 | 1030 | * 1031 | Aplique definições `@typedoc` e `@type` juntas, e separe cada par 1032 | com uma linha em branco. 1033 | [[link](#typedocs)] 1034 | 1035 | ```elixir 1036 | defmodule AlgumModulo do 1037 | @moduledoc false 1038 | 1039 | @typedoc "O nome" 1040 | @type name :: atom 1041 | 1042 | @typedoc "O resultado" 1043 | @type result :: {:ok, termo} | {:error, termo} 1044 | 1045 | ... 1046 | end 1047 | ``` 1048 | 1049 | * 1050 | Se um tipo de união for longo demais para caber em um só linha, adicione 1051 | uma nova linha e indente com espaços para alinhar os tipos. 1052 | [[link](#tipos-uniao)] 1053 | 1054 | ```elixir 1055 | # não recomendado - sem indentação 1056 | @type tipo_de_uniao_longo :: algum_tipo | outro_tipo | algum_outro_tipo | 1057 | um_ultimo_tipo 1058 | 1059 | # recomendado 1060 | @type tipo_de_uniao_longo :: algum_tipo | outro_tipo | algum_outro_tipo | 1061 | um_ultimo_tipo 1062 | 1063 | # também recomendado - um tipo por linha 1064 | @type tipo_de_uniao_longo :: algum_tipo | 1065 | outro_tipo | 1066 | algum_outro_tipo | 1067 | um_ultimo_tipo 1068 | ``` 1069 | 1070 | * 1071 | Nomeie como `t` o tipo principal de um módulo, por exemplo: a especificação 1072 | de tipo para um struct. 1073 | [[link](#nomeando-tipos-principais)] 1074 | 1075 | ```elixir 1076 | defstruct nome: nil, params: [] 1077 | 1078 | @type t :: %__MODULE__{ 1079 | nome: String.t | nil, 1080 | params: Keyword.t 1081 | } 1082 | ``` 1083 | 1084 | * 1085 | Escreva especificações logo acima da definicação de uma função, sem separá-los 1086 | com linha em branco. 1087 | [[link](#espacamento-specs)] 1088 | 1089 | ```elixir 1090 | @spec alguma_funcao(termo) :: result 1091 | def alguma_funcao(algum_dado) do 1092 | {:ok, algum_dado} 1093 | end 1094 | ``` 1095 | 1096 | ### Structs 1097 | 1098 | * 1099 | Use uma lista de átomos para campos de struct que tenham default de `nil`, 1100 | seguidos por outras palavras-chave. 1101 | [[link](#defaults-campos-struct-nil)] 1102 | 1103 | ```elixir 1104 | # não recomendado 1105 | defstruct nome: nil, params: nil, ativo: true 1106 | 1107 | # recomendado 1108 | defstruct [:nome, :params, ativo: true] 1109 | ``` 1110 | 1111 | * 1112 | Omita colchetes quando o argumento de um `defstruct` for uma lista 1113 | de palavras-chave. 1114 | [[link](#colchetes-defstruct)] 1115 | 1116 | ```elixir 1117 | # não recomendado 1118 | defstruct [params: [], ativo: true] 1119 | 1120 | # recomendado 1121 | defstruct params: [], ativo: true 1122 | 1123 | # obrigatório - colchetes não são opcionais, com ao menos um átomo na lista 1124 | defstruct [:nome, params: [], ativo: true] 1125 | ``` 1126 | 1127 | * 1128 | Indente linhas adicionais de defstruct, mantendo as primeiras chaves alinhadas. 1129 | aligned. 1130 | [[link](#linhas-defstruct-adicionais)] 1131 | 1132 | ```elixir 1133 | defstruct foo: "teste", bar: true, baz: false, 1134 | qux: false, quux: 1 1135 | ``` 1136 | 1137 | ### Exceções 1138 | 1139 | * 1140 | Adicione o sufixo `Error` aos nomes de exceções. 1141 | [[link](#nomes-excecoes)] 1142 | 1143 | ```elixir 1144 | # não recomendado 1145 | defmodule BadHTTPCode do 1146 | defexception [:mensagem] 1147 | end 1148 | 1149 | defmodule BadHTTPCodeException do 1150 | defexception [:mensagem] 1151 | end 1152 | 1153 | # recomendado 1154 | defmodule BadHTTPCodeError do 1155 | defexception [:mensagem] 1156 | end 1157 | ``` 1158 | 1159 | * 1160 | Use minúsculas em mensagens de erro quando emitindo exceções, sem pontuação 1161 | ao final. 1162 | [[link](#mensagens-erro-minusculas)] 1163 | 1164 | ```elixir 1165 | # não recomendado 1166 | raise ArgumentError, "Isto não é válido." 1167 | 1168 | # recomendado 1169 | raise ArgumentError, "isto é válido" 1170 | ``` 1171 | 1172 | ### Coleções 1173 | 1174 | A secão de Coleções do guia ainda não foi adicionada. 1175 | 1176 | ### Strings 1177 | 1178 | * 1179 | Dê match em strings usando o concatenador de strings, e não 1180 | padrões binários. 1181 | [[link](#match-strings-com-concatenador)] 1182 | 1183 | ```elixir 1184 | # não recomendado 1185 | <<"minha"::utf8, _resto>> = "minha string" 1186 | 1187 | # recomendado 1188 | "minha" <> _resto = "minha string" 1189 | ``` 1190 | 1191 | ### Expressões Regulares 1192 | 1193 | _A secão de Coleções do guia ainda não foi adicionada._ 1194 | 1195 | ### Metaprogramação 1196 | 1197 | * 1198 | Evite metaprogramação desnecessária. 1199 | [[link](#evite-metaprogramacao)] 1200 | 1201 | ### Testes 1202 | 1203 | * 1204 | Ao escrever asserções [ExUnit], mantenha a consistência entre a ordem dos 1205 | valores esperados e reais que estão sob teste. 1206 | Prefira usar o resultado esperado à direita, a não ser que a asserção 1207 | seja um pattern match. 1208 | [[link](#testando-ordem-assert)] 1209 | 1210 | ```elixir 1211 | # recomendado - resultado esperado à direita 1212 | assert minha_funcao(1) == true 1213 | assert minha_funcao(2) == false 1214 | 1215 | # não recomendado - ordem inconsistente 1216 | assert minha_funcao(1) == true 1217 | assert false == minha_funcao(2) 1218 | 1219 | # obrigatório - a asserção é um pattern match 1220 | assert {:ok, expected} = minha_funcao(3) 1221 | ``` 1222 | 1223 | ### Guias de Estilo Alternativos 1224 | 1225 | * [Aleksei Magusev's Elixir Style Guide](https://github.com/lexmag/elixir-style-guide#readme) 1226 | — Um guia de estilo Elixir opiniático inspirado nas práticas encontradas 1227 | nas bibliotecas 'core' do Elixir. 1228 | Desenvolvido por [Aleksei Magusev](https://github.com/lexmag) e 1229 | [Andrea Leopardi](https://github.com/whatyouhide), membros da equipe principal do Elixir. 1230 | Apesar do projeto do Elixir não aderir a um guia de estilo específico, 1231 | este é o guia mais próximo de suas convenções. 1232 | 1233 | * [Credo's Elixir Style Guide](https://github.com/rrrene/elixir-style-guide#readme) 1234 | — Guia de Estilo para a linguagem Elixir, implementada pelo 1235 | [Credo](http://credo-ci.org), ferramenta de análise estática de código. 1236 | 1237 | ### Ferramentas 1238 | 1239 | Confira o [Awesome Elixir][Code Analysis] para encontrar bibliotecas e 1240 | ferramentas para te ajudar em análise e linting de código. 1241 | 1242 | ## Participando 1243 | 1244 | ### Contribuindo 1245 | 1246 | Esperamos que este se torne um ponto de encontro para discussões da comunidade 1247 | sobre as melhores práticas em Elixir. 1248 | Sinta-se bem-vindo(a) a abrir issues ou enviar pull requests com melhorias. 1249 | Obrigado desde já por sua ajuda! 1250 | 1251 | Confira as [dicas de contribuição - em inglês][Contribuindo] 1252 | e o [código de conduta][Code Of Conduct] para saber mais. 1253 | 1254 | ### Espalhe 1255 | 1256 | Um guia de estilo de uma comunidade não faz sentido sem o apoio da comunidade. 1257 | Por gentileza tuíte, [dê estrelas][Stargazers] e compartilhe [este guia][Elixir Style Guide] com todos, para que todos possam contribuir. 1258 | 1259 | ## Cópias 1260 | 1261 | ### Licença 1262 | 1263 | ![Licença Creative Commons](http://i.creativecommons.org/l/by/3.0/88x31.png) 1264 | Este trabalho é licenciada sob uma 1265 | [Licença Creative Commons Attribution 3.0 Unported][Licença] 1266 | 1267 | ### Atribuição 1268 | 1269 | A estrutura deste guia, alguns trechos de código dos exemplos, e muito pontos 1270 | iniciais deste documento foram empresados do [Guia de Estilo da Comunidade Ruby]. 1271 | Muitas coisas se aplicavam ao Elixir e nos permitiram publicar _algum_ documento 1272 | mas rápido e dar início ao projeto. 1273 | out quicker to start the conversation. 1274 | 1275 | Aqui está a [lista das pessoas que gentilmente contribuíram][Contributors] com este 1276 | projeto. 1277 | 1278 | 1279 | [Chinês Tradicional]: https://github.com/elixirtw/elixir_style_guide/blob/master/README_zhTW.md 1280 | [Code Analysis]: https://github.com/h4cc/awesome-elixir#code-analysis 1281 | [Code Of Conduct]: https://github.com/christopheradams/elixir_style_guide/blob/master/CODE_OF_CONDUCT.md 1282 | [Conflicting Aliases]: https://elixirforum.com/t/using-aliases-for-fubar-fubar-named-module/1723 1283 | [Contribuindo]: https://github.com/elixir-lang/elixir/blob/master/CODE_OF_CONDUCT.md 1284 | [Contributors]: https://github.com/christopheradams/elixir_style_guide/graphs/contributors 1285 | [Coreano]: https://github.com/marocchino/elixir_style_guide/blob/new-korean/README-koKR.md 1286 | [Elixir]: http://elixir-lang.org 1287 | [Espanhol]: https://github.com/albertoalmagro/elixir_style_guide/blob/spanish/README_esES.md 1288 | [ExDoc]: https://github.com/elixir-lang/ex_doc 1289 | [ExUnit]: https://hexdocs.pm/ex_unit/ExUnit.html 1290 | [Guard Expressions]: http://elixir-lang.org/getting-started/case-cond-and-if.html#expressions-in-guard-clauses 1291 | [Guia de Estilo Elixir]: https://github.com/christopheradams/elixir_style_guide 1292 | [Hex]: https://hex.pm/packages 1293 | [Inglês]: https://github.com/christopheradams/elixir_style_guide/blob/master/README.md 1294 | [Japonês]: https://github.com/kenichirow/elixir_style_guide/blob/master/README-jaJP.md 1295 | [Licença]: http://creativecommons.org/licenses/by/3.0/deed.en_US 1296 | [Atributos de Módulo]: http://elixir-lang.org/getting-started/module-attributes.html#as-annotations 1297 | [Português]: https://github.com/gusaiani/elixir_style_guide/blob/master/README_ptBR.md 1298 | [Guia de Estilo da Comunidade Ruby]: https://github.com/bbatsov/ruby-style-guide 1299 | [Sentence Spacing]: http://en.wikipedia.org/wiki/Sentence_spacing 1300 | [Stargazers]: Use://github.com/christopheradams/elixir_style_guide/stargazers 1301 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | task :test do 2 | exit_code = 0 3 | files = ["README.md", "CONTRIBUTING.md"] 4 | # 'MD036' # Emphasis used instead of a header 5 | # 'MD033' # Inline HTML - allow for anchor links in each bullet point 6 | rules = ['~MD036', '~MD033'].join(",") 7 | files.each do |file| 8 | begin 9 | sh "mdl --rules #{rules} #{file}" 10 | rescue Exception => ex 11 | exit_code = 1 12 | end 13 | end 14 | 15 | exit exit_code 16 | end 17 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule ElixirStyleGuide.Mixfile do 2 | use Mix.Project 3 | 4 | @project_description """ 5 | A community driven style guide for Elixir 6 | """ 7 | 8 | @version "0.1.0" 9 | @source_url "https://github.com/christopheradams/elixir_style_guide" 10 | 11 | def project do 12 | [app: :elixir_style_guide, 13 | version: @version, 14 | elixir: "~> 1.0", 15 | build_embedded: Mix.env == :prod, 16 | start_permanent: Mix.env == :prod, 17 | docs: docs(), 18 | description: @project_description, 19 | source_url: @source_url, 20 | package: package(), 21 | deps: deps()] 22 | end 23 | 24 | def application do 25 | [applications: [:logger]] 26 | end 27 | 28 | defp deps do 29 | [] 30 | end 31 | 32 | defp docs() do 33 | [ 34 | source_ref: "v#{@version}", 35 | main: "readme", 36 | extras: [ 37 | "README.md": [title: "README"] 38 | ] 39 | ] 40 | end 41 | 42 | defp package do 43 | [ 44 | name: :elixir_style_guide, 45 | maintainers: ["Christopher Adams"], 46 | licenses: ["CC-by"], 47 | links: %{ 48 | "GitHub" => @source_url 49 | } 50 | ] 51 | end 52 | end 53 | --------------------------------------------------------------------------------