Skip to content

Commit

Permalink
Updated style guide with a general game info section (#5956)
Browse files Browse the repository at this point in the history
* Updated style guide with a general game info section

at the start to explain the most important considerations for general C# developers, and improved some of the other parts of the style guide a bit

* Fix a typo that flipped the meaning of a sentence

* Reworded the sentence about automatic checks
  • Loading branch information
hhyyrylainen authored Feb 26, 2025
1 parent 44151e1 commit 8a036da
Showing 1 changed file with 54 additions and 14 deletions.
68 changes: 54 additions & 14 deletions doc/style_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,43 @@ ignore directive, should only be done in special cases. If some rule
is especially troublesome it can be discussed whether it can be
disabled entirely.

Before the specific rules, here are a few special considerations as
Thrive is a *game* and not just general software:

- Runtime cost of code that runs each frame (or very often) is very
important. And often many patterns that are faster but less readable
need to be used.
- Memory allocations should be avoided whenever possible. GUI and
editor code is more relaxed regarding this, but code running each
frame during the game should not allocate memory. Instead,
preallocated lists and other data structures should be created and
kept around across frames to avoid allocating more memory. More info
on memory allocations is in the special section about them in this
document.
- Nullable *value* types should be avoided as they require boxing
allocations in order to create them. Some persistent use of them is
fine as that spreads out the memory allocations and thus doesn't
generate as much garbage collector pressure. But in general stuff
like `Vector3?` should be avoided. Instead, use a normal variable and
a bool indicating if the value is valid.
- LINQ usage needs to be avoided as it can be very hard to avoid extra
memory allocations or lambda allocations with variable
captures. There's a [recommended
plugin](https://plugins.jetbrains.com/plugin/9223-heap-allocations-viewer)
for Rider to highlight all memory allocations.
- Foreach loops that allocate enumerators should be avoided, and
instead manual loops used whenever the compiler optimization for
`foreach` doesn't work. See the Rider plugin to easily know when
that is the case.

Note that the above doesn't apply to the extra code components that
aren't primarily used by the Thrive game project.

Code style rules
----------------

- Indentation is 4 spaces. Continued statements are indented one level
higher.
higher (per level of scope as JetBrains indents).

- Names (that includes variables, functions and classes) should be
descriptive. Avoid abbreviations. Do not shorten variable names just
Expand Down Expand Up @@ -80,23 +112,25 @@ Code style rules
namespace all using statements should be within the namespace.

- Build your code with warnings enabled to see things StyleCop
complains about. If you don't automatic checks on your code will
fail.
complains about. If you don't, automatic checks on your pull request
will fail.

- Due to StyleCop not having rules for everything, there are
additional rules implemented by a custom script (`dotnet run
--project Scripts check`) which you should run before committing to
make sure there are no issues in your code. This script can be
enabled to run automatically with pre-commit.

- All classes and their public and protected members should be
documented by XML comments. If the function's purpose is clear from
the name, then its documentation can be omitted. If there is a
comment on a single construct (class, method etc.) it must be an XML
comment. All XML comments must begin with a `summary` section to
explain what something is, and after that what it is used for. If
the usage explanation is long or there are extra information to
include, put those into a paragraph inside a `remarks` section.
- All classes and their public members should be documented by XML
comments. If the function's purpose is clear from the name, then its
documentation can be omitted. Documenting protected and private
members is more optional but if their purpose or usage by derived
classes isn't immediately obvious, they should be documented. If
there is a comment on a single construct (class, method etc.) it
must be an XML comment. All XML comments must begin with a `summary`
section to explain what something is, and after that what it is used
for. If the usage explanation is long or there are extra information
to include, put those into a paragraph inside a `remarks` section.

- In XML comments each nesting level is intended 2 spaces more than
the previous level.
Expand Down Expand Up @@ -266,7 +300,10 @@ Code style rules
namespace (check the documentation on the types for which generators
are suitable for what kinds of numeric types). General advice is to
use 128-bit generators for 32-bit types (`int`, `float`) and 256-bit
generators for 64-bit types (`long`, `double`).
generators for 64-bit types (`long`, `double`). Note that `Xoshiro`
randoms can still be passed around as `Random` references but no
direct creations of `System.Random` class should be done for
gameplay code or where state might need to be saved.

- Unrelated uses should not share the same variable. Instead they
should locally define their own variable instance.
Expand All @@ -289,7 +326,8 @@ Code style rules
- Prefer `List` and other concrete containers over `IList` and similar
interfaces. `IList` should be used only in very special cases that
require it. In many cases `IEnumerable` is the preferred type to use
to not place constraints on other code unnecessarily.
to not place constraints on other code unnecessarily. Concrete lists
allow `foreach` usage without memory allocations.

- Methods should not use `=> style` bodies, properties when they are
short should use that style bodies.
Expand All @@ -304,7 +342,9 @@ Code style rules

- Prefer to write out code rather than using very complex LINQ
chains. Use complex LINQ sparingly. If LINQ would need many nested
statements in lambdas, normal code should be used instead
statements in lambdas, normal code should be used instead. When
using LINQ take extreme care related to memory allocations if the
method using LINQ is called often.

- Prefer to use single letter variable names in LINQ statements, when
they are clear enough. Don't always use x or another generic
Expand Down

0 comments on commit 8a036da

Please sign in to comment.