-
Notifications
You must be signed in to change notification settings - Fork 320
Code Style
A project like Armory with multiple people involved needs a maintainable codebase. To prevent chaos, there exist some simple rules you should follow to make your code more readable and thus maintable. You will be thankful for others if you can understand their code while working on it.
These guidelines are not completely strict. You should always find solutions that fit to the needs of your code. The important thing is that you should keep everything readable and fast!
The current codebase does not fully comply to these rules yet, but you can help to improve it!
-
Comment your code!
Don't overdo it, but make sure that others can follow your thoughts. If there is some background information, for example why you've chosen a certain approach to a problem or where some values are taken from, write it down.
-
Give variables descriptive (but not too long) names!
stepsPerSecond
is much clearer than justs
. If you choose good descriptive variable names, the code mostly "comments itself". -
Always consider the performance of your code!
Extra points for you if you write both fast and clear code ;)
-
Don't mix tabs and spaces.
For Python we use 4 spaces for indentation, for Haxe we use tabs. Please setup your code editor accordingly. Also, make sure that there is no trailing whitespace at the end of lines (code editors can also do that for you).
-
Give your code a meaningful structure.
Keep things organized and modular, but don't over-generalize where you don't need to.
Armory follows the PEP 8 style guide which is the de facto standard code style for Python. There are linter plug-ins available for most code editors to help you stick to these rules.
Also have a look at The Zen of Python.
-
Use
snake_case
for variable and function names andUpperCamelCase
for class names. -
Use immutable tuples
()
instead of mutable lists[]
if the data is read-only. -
Check if a value is
None
withis
oris not
, do not use==
or!=
.# Good if val is not None: do_something() # Bad if val != None: do_something()
-
Use type hints where it makes sense. Type hints have no effect during runtime but they make code much more readable and enable auto-completion in your IDE of choice.
# Good def foo(name: str, mesh: bpy.types.Mesh) -> int: return 42 # If the function has no return value, `-> None` is not required. def foo(name: str, mesh: bpy.types.Mesh): return # Bad def foo(name, mesh): return 3.14
-
Use f-strings if they improve readability.
# Good my_string = f'Values: {a}, {a + b}, {foo()}.' # Bad my_string = 'Values: ' + str(a) + ', ' + str(a + b) + ', ' + foo() + '.'
Keep in mind that f-strings don't support escape sequences like
\n
. -
Group imports in the following categories (blank lines in between, see PEP 8: Imports) and sort them alphabetically:
- Python standard library
- Third-party modules (
numpy
for example) and Blender (bpy
etc.) - Armory-related modules (
arm
).
-
Use two blank lines between module-level functions and classes.
-
Add docstrings to functions if the functions itself are not descriptive enough. Module docstrings are a good idea as well so that other people know what a module is used for.
"""This is a module docstring at the top of the file. It explains what functionality the module contains. """ def foo(): """This docstring explains what foo() does. If it spans multiple lines, put the closing quotes on a new line. """
For Haxe the code style is specified in checkstyle.json
. The file format is explained in detail here.
-
Use
lowerCamelCase
for variable and function names. -
Use the following modifier order:
macro override public static inline function foo() {}
-
Add docstrings to
public
functions and classes as they become visible in the API Documentation. Docstrings forprivate
functions can make sense as well if the function needs additional description./** This docstring explains what foo() does. You can also use *Markdown* syntax here. @param value Description of the `value` parameter @return Description of the return value **/ public function foo(value: Int): Int {}