|
| 1 | +--- |
| 2 | +title: Style Guide |
| 3 | +engine: julia |
| 4 | +--- |
| 5 | + |
| 6 | +Most Turing code follows the [Invenia](https://invenia.ca/labs/)'s style guide. We would like to thank them for allowing us to access and use it. Please don't let not having read it stop you from contributing to Turing! No one will be annoyed if you open a PR with style that doesn't follow these conventions; we will just help you correct it before it gets merged. |
| 7 | + |
| 8 | +These conventions were originally written at Invenia, taking inspiration from a variety of sources including Python's [PEP8](http://legacy.python.org/dev/peps/pep-0008), Julia's [Notes for Contributors](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md), and Julia's [Style Guide](https://docs.julialang.org/en/v1/manual/style-guide/). |
| 9 | + |
| 10 | +What follows is a mixture of a verbatim copy of Invenia's original guide and some of our own modifications. |
| 11 | + |
| 12 | +## A Word on Consistency |
| 13 | + |
| 14 | +When adhering to this style it's important to realize that these are guidelines and not rules. This is [stated best in the PEP8](http://legacy.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds): |
| 15 | + |
| 16 | +> A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important. |
| 17 | +
|
| 18 | +> But most importantly: know when to be inconsistent – sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask! |
| 19 | +
|
| 20 | +## Synopsis |
| 21 | + |
| 22 | +Attempt to follow the [Julia Contribution Guidelines](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md#general-formatting-guidelines-for-julia-code-contributions), the [Julia Style Guide](https://docs.julialang.org/en/v1/manual/style-guide/), and this guide. When convention guidelines conflict, this guide takes precedence (known conflicts will be noted in this guide). |
| 23 | + |
| 24 | + - Use 4 spaces per indentation level, no tabs. |
| 25 | + - Try to adhere to a 92 character line length limit. |
| 26 | + - Use upper camel case convention for [modules](https://docs.julialang.org/en/v1/manual/modules/) and [types](https://docs.julialang.org/en/v1/manual/types/). |
| 27 | + - Use lower case with underscores for method names (note: Julia code likes to use lower case without underscores). |
| 28 | + - Comments are good, try to explain the intentions of the code. |
| 29 | + - Use whitespace to make the code more readable. |
| 30 | + - No whitespace at the end of a line (trailing whitespace). |
| 31 | + - Avoid padding brackets with spaces. ex. `Int64(value)` preferred over `Int64( value )`. |
| 32 | + |
| 33 | +## Editor Configuration |
| 34 | + |
| 35 | +### Sublime Text Settings |
| 36 | + |
| 37 | +If you are a user of Sublime Text we recommend that you have the following options in your Julia syntax specific settings. To modify these settings first open any Julia file (`*.jl`) in Sublime Text. Then navigate to: `Preferences > Settings - More > Syntax Specific - User` |
| 38 | + |
| 39 | +```{json} |
| 40 | +{ |
| 41 | + "translate_tabs_to_spaces": true, |
| 42 | + "tab_size": 4, |
| 43 | + "trim_trailing_white_space_on_save": true, |
| 44 | + "ensure_newline_at_eof_on_save": true, |
| 45 | + "rulers": [92] |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +### Vim Settings |
| 50 | + |
| 51 | +If you are a user of Vim we recommend that you add the following options to your `.vimrc` file. |
| 52 | + |
| 53 | +``` |
| 54 | +set tabstop=4 " Sets tabstops to a width of four columns. |
| 55 | +set softtabstop=4 " Determines the behaviour of TAB and BACKSPACE keys with expandtab. |
| 56 | +set shiftwidth=4 " Determines the results of >>, <<, and ==. |
| 57 | +
|
| 58 | +au FileType julia setlocal expandtab " Replaces tabs with spaces. |
| 59 | +au FileType julia setlocal colorcolumn=93 " Highlights column 93 to help maintain the 92 character line limit. |
| 60 | +``` |
| 61 | + |
| 62 | +By default, Vim seems to guess that `.jl` files are written in Lisp. To ensure that Vim recognizes Julia files you can manually have it check for the `.jl` extension, but a better solution is to install [Julia-Vim](https://github.com/JuliaLang/julia-vim), which also includes proper syntax highlighting and a few cool other features. |
| 63 | + |
| 64 | +## Test Formatting |
| 65 | + |
| 66 | +### Testsets |
| 67 | + |
| 68 | +Julia provides [test sets](https://docs.julialang.org/en/v1/stdlib/Test/#Working-with-Test-Sets-1) which allows developers to group tests into logical groupings. Test sets can be nested and ideally packages should only have a single "root" test set. It is recommended that the "runtests.jl" file contains the root test set which contains the remainder of the tests: |
| 69 | + |
| 70 | +```{julia} |
| 71 | +#| eval: false |
| 72 | +@testset "PkgExtreme" begin |
| 73 | + include("arithmetic.jl") |
| 74 | + include("utils.jl") |
| 75 | +end |
| 76 | +``` |
| 77 | + |
| 78 | +The file structure of the `test` folder should mirror that of the `src` folder. Every file in `src` should have a complementary file in the `test` folder, containing tests relevant to that file's contents. |
| 79 | + |
| 80 | +### Comparisons |
| 81 | + |
| 82 | +Most tests are written in the form `@test x == y`. Since the `==` function doesn't take types into account, tests like the following are valid: `@test 1.0 == 1`. Avoid adding visual noise into test comparisons: |
| 83 | + |
| 84 | +```{julia} |
| 85 | +#| eval: false |
| 86 | +# Yes: |
| 87 | +@test value == 0 |
| 88 | +
|
| 89 | +# No: |
| 90 | +@test value == 0.0 |
| 91 | +``` |
| 92 | + |
| 93 | +In cases where you are checking the numerical validity of a model's parameter estimates, please use the `check_numerical` function found in `test/test_utils/numerical_tests.jl`. This function will evaluate a model's parameter estimates using tolerance levels `atol` and `rtol`. Testing will only be performed if you are running the test suite locally or if Travis is executing the "Numerical" testing stage. |
| 94 | + |
| 95 | +Here is an example of usage: |
| 96 | + |
| 97 | +```{julia} |
| 98 | +#| eval: false |
| 99 | +# Check that m and s are plus or minus one from 1.5 and 2.2, respectively. |
| 100 | +check_numerical(chain, [:m, :s], [1.5, 2.2]; atol=1.0) |
| 101 | +
|
| 102 | +# Checks the estimates for a default gdemo model using values 1.5 and 2.0. |
| 103 | +check_gdemo(chain; atol=0.1) |
| 104 | +
|
| 105 | +# Checks the estimates for a default MoG model. |
| 106 | +check_MoGtest_default(chain; atol=0.1) |
| 107 | +``` |
0 commit comments