Skip to content

Commit 0354cab

Browse files
authored
Merge pull request #6 from VirtualPlantLab/developers_protocols
Guidelines/protocols for package development and styling
2 parents dda6d95 + ca43049 commit 0354cab

4 files changed

Lines changed: 425 additions & 1 deletion

File tree

docs/make.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ makedocs(;
6363
],
6464
"Developers" => [
6565
"Internal organization" => "developers/organization.md"
66+
"Package and Environment Management for VPL" => "developers/use&dev_packages.md"
67+
"Styling protocol" => "developers/style.md"
6668
]
6769
],
6870
)

docs/src/developers/organization.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
In terms of implementation, VPL consists of a GitHub organization ([VirtualPlantLab](https://github.com/VirtualPlantLab/VirtualPlantLab.jl))
44
that contains 9 registered Julia packages. The packages are organized in two groups:
55

6-
- The VPL core: These are the basic packages that provide the functionality to build FSP models. The user is normally not intended to use these packages directly but rather through the interface offered by [VirtualPlantLab.jl](https://github.com/VirtualPlantLab/VirtualPlantLab.jl). Developers who want to access the source code (and potentially modify it) should first identify the package that contains the functionality they are interested in.
6+
- The *VPL core*: These are the basic packages that provide the functionality to build FSP models. The user is normally not intended to use these packages directly but rather through the interface offered by [VirtualPlantLab.jl](https://github.com/VirtualPlantLab/VirtualPlantLab.jl). Developers who want to access the source code (and potentially modify it) should first identify the package that contains the functionality they are interested in.
77

88
- The *VPLverse*: These are packages that are built on top of the VPL core or standalone packages that provide additional functionality to build FSP models. The user needs to install these packages separately and import them if they wish to use them.
99

docs/src/developers/style.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Styling protocol
2+
3+
Ana Ernst & Alejandro Morales
4+
Centre for Crop Systems Analysis - Wageningen University
5+
6+
A styling protocol is essential for code readability, consistency, and maintainability. It ensures that code follows predefined formatting rules, prevents errors, and suggests best practices for overall quality of the code. This type of protocol not only plays a crucial role in code quality but also when it comes to collaboration and long-term software project success.
7+
8+
This styling protocol was based on the [SciML Style Guide for Julia](https://docs.sciml.ai/SciMLStyle/stable/), adapted for the applications of VirtualPlantLab.
9+
10+
## Programming
11+
12+
This section outlines programming guidelines and best practices to ensure the quality, robustness, and maintainability of your codebase. These guidelines are essential for both the clarity of your code and the ease of collaboration with other users or developers.
13+
14+
* Defensive programming for public API only (not internal code)
15+
Defensive programming is a software development approach that focuses on
16+
anticipating and handling possible errors and exceptions, as well as improve
17+
the reliability and robustness of the code.
18+
*For example, if one knows that a function `f(w0, w)` will have an error unless `w0 < p`, you can throw the function with a domain specific error: `throw(DomainError())`*
19+
* Throw exceptions rather than `error("string")`
20+
* Always use recipes and let the user load the Makie backend explicitly (but document this in tutorials)
21+
* API must be documented using standard Julia docstrings (see templates)
22+
* When in doubt, a submodule should become a package (see package protocol)
23+
* Green [`@code_warntype`](https://docs.julialang.org/en/v1/manual/performance-tips/#man-code-warntype) for all functions
24+
In Julia, 'green' code indicates type-stability, which ensures better performance.
25+
* Define accessor for all fields and document these rather than the fields themselves
26+
Accessors provides controlled access to data is important as it allows for future changes to the internal structure without affecting users that rely on accessors.
27+
*For example, in the [tutorial](https://virtualplantlab.com/stable/tutorials/Tree/Tree/) to build the representation of a 3D binary tree, we can set accessor functions as it follows*
28+
````julia
29+
module TreeTypes
30+
import VirtualPlantLab
31+
# ... (previously defined types)
32+
# Accessor functions for treeparams parameters
33+
# Accessor for growth parameter
34+
function get_growth(params::treeparams)
35+
return params.growth
36+
end
37+
# ... (other previously defined functions)
38+
end
39+
````
40+
41+
## General style
42+
43+
In this section, we outline the general style guidelines to maintain consistency and readability in your code. These guidelines are exemplified using the tree tutorial as a reference. However, if there is an acronym that is domain specific (e.g., LAI, SLA), it should be kept with the format - *Readability is the most important!*
44+
45+
* 4 spaces for indentation
46+
* 92 character line length limits
47+
* `CamelCase` for modules, structs and types
48+
For example:
49+
- `module TreeTypes ... end`
50+
- `struct Meristem <: VirtualPlantLab.Node end`
51+
- `Float64, Abstract64, ...`
52+
* `snake_case` for functions and variables
53+
For example: `prob_break(bud)`
54+
* `SNAKE_CASE` or `SNAKECASE` for constants
55+
For example: `CONSTANT, CONSTANT_A`
56+
* No Unicode in public APIs
57+
As code can interact with terminals without Unicode support, such as R or Python interfaces.
58+
* `TODO` and `XXX` in comments for to do and broken code
59+
* Inline comments if within 92 character rule
60+
* Minimize whitespace, specially around brackets or certain operators.
61+
Recommended: `check, steps = has_descendant(node, condition = n -> data(n) isa TreeTypes.Meristem)` or `x^2`
62+
Not recommended: `check , steps = has_descendant ( node, condition = n -> data ( n ) isa TreeTypes.Meristem )` or `x ^ 2`
63+
* Single empty line between functions and multiline blocks (not if they are one-liners)
64+
* Function blocks end in `return`
65+
* Ternary operator if within 92 character rule
66+
67+
**Modules**
68+
---
69+
70+
- Module imports at the start of module, before any code (only use `import`)
71+
- List multiple modules in a single line
72+
73+
**Functions**
74+
---
75+
76+
- Short-form only if it fits within 92 characters
77+
- Prefer to use keyword arguments instead of positional arguments (data as first argument)
78+
- Use a named tuple for keyword arguments that are passed along to another method, rather than `kwargs...` (unless there is very little chance of ambiguity)
79+
- Avoid type piracy and ambiguities (use [`Aqua.jl`](https://docs.juliahub.com/General/Aqua/0.5.1/))
80+
- Basic rules for mutating functions (`!` and modify first argument)
81+
- Prefer instances to types as arguments (BUT check with `@code_warntype` that inference is done correctly)
82+
- Avoid one argument per line of code for functions that have a lot of arguments (an exception is the constructor for a model where each argument is a parameter with a default)
83+
- Argument precedence: function > IO stream > mutated input > type > others
84+
- Merge documentation of multiple methods if possible
85+
- You can list `kwargs...` in the function signature and list the keyword arguments in the `docstring`
86+
87+
88+
**VS Code Julia-specific syntax**
89+
---
90+
91+
```yaml
92+
{
93+
"[julia]": {
94+
"editor.detectIndentation": false,
95+
"editor.insertSpaces": true,
96+
"editor.tabSize": 4,
97+
"files.insertFinalNewline": true,
98+
"files.trimFinalNewlines": true,
99+
"files.trimTrailingWhitespace": true,
100+
"editor.rulers": [92],
101+
"files.eol": "\n"
102+
},
103+
}
104+
```
105+
106+
Use JuliaFormatter(link) with `style = "sciml"` (in the future and style for VPL will be formally defined) inside `.JuliaFormatter.toml` (at the root) then
107+
108+
```julia
109+
using JuliaFormatter, SomePackage
110+
format(joinpath(dirname(pathof(SomePackage)), ".."))
111+
```

0 commit comments

Comments
 (0)