From 45b9863c83e968fba2c1cc17e61271f275b35d73 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Fri, 15 May 2026 11:01:54 -0400 Subject: [PATCH] Add CONTRIBUTING document --- CONTRIBUTING.md | 352 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6f2c3e8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,352 @@ +# Coding Guide + +This document serves as the official code standards guide development. Please note that this is a work in progress and may not encapsulate all standards expected of new or existing code. The included `.editorconfig` file can help enforce some of the standards mentioned below. + +## General Code Guidelines + +This section contains information on code standards regardless of which part of the project you are working in. + +### Style and Naming + +- Prefer `System` namespaces for supporting operations before external ones. + +- Ordering of `using` statements goes: + - `using System.*` + - `using ` + - `using static ` + - `using X = Y` + +- Use 4 spaces for `tab`. + +- Curly braces should generally start on the line after but inline with the start of the previous statement, even if multiline. + + ```c# + if (flag) + { + DoSomething(); + } + else if (flag2 + && flag3) + { + DoSomething2(); + } + ``` + +- Multi-line statements need to have following lines indented by one step at minimum. + + ```c# + if (flag) + { + DoSomething(); + } + else if (flag2 + && flag3 + && (flag4 + || flag5)) + { + DoSomething2(); + } + ``` + +- Methods and classes should use `PascalCase` for naming, even `internal` and `private` ones. + +- Class properties should use `PascalCase` for naming, even `protected` and `internal` ones. + +- Instance variables should use `camelCase` with a `_` prefix for naming, even `protected`, `internal`, and `private` ones. + +- In-method variables should use `camelCase` without a `_` prefix for naming. + +- Include explicit access modifiers for all class-level properties, variables, and methods. + +- Avoid making everything `public`; only include the necessary level of access. + +- Avoid making every method and class instance-based. Use `static` if your method does not need to access instance variables. Use `static` if your class only contains extensions or methods used by other classes. + +- Null-coalescing and null-checking operators can be used to make more readable statements and better get across what a statement or string of statements is doing. + + ```c# + if (obj?.Parameter is not null) { ... } + + bool value = DoSomething() ?? false; + ``` + +- `#region` tags, including nested ones, can be used to both segment methods within a class and statements within a method. Indentation follows the surrounding code. + + ```c# + #region This is the first region + + public static void Method() + { + #region This is an in-code region + + DoSomething(); + + #endregion + + DoSomething2(); + } + + #endregion + ``` + +- Try to avoid use of other preprocessor directives unless consulting ahead of time with the maintainers. + +- Interfaces should be listed in alphabetical order + + ```c# + public class Example : IBindable, IComparable, IEquatable + ``` + +- Use the `` tag when possible to avoid out-of-date information. + + ```c# + public interface IInterface + { + /// + /// Summary to inherit + /// + void DoSomething(); + } + + public class Example : IInterface + { + /// + public void DoSomething() { ... } + } + ``` + +### Methods + +- Try to avoid including too much duplicate code across methods and classes. If you have duplicate code that spans more than ~5 lines, consider writing a helper method. + +- Try to use expressive naming. e.g. use names like `PrintSectionTitles` and not `DoTheThing`. + +- Try to avoid having too many parameters in a method signature. More parameters means more things interacting. + +- Use method overloading to avoid unnecessary complexity in a single method. + + ```c# + Instead of: + + Print(string idString, byte[] idArray, int idInt) { ... } + + You should: + + Print(string id) { ... } + + Print(byte[] id) { ... } + + Print(int id) { ... } + ``` + +- Use optional parameters when the default value is the most common. + + ```c# + Print(string id, bool toLower = false) { ... } + ``` + +### `if-else` and `switch` statement syntax + +- If all statements in the block are single-line, do not include curly braces. + + ```c# + if (flag) + DoSomething(); + else if (flag2) + DoSomething2(); + else + DoSomethingElse(); + ``` + +- If any of the statements is multi-line _or_ the `if-else` statement is multi-line, include curly braces. + + ```c# + if (flag) + { + DoSomething(); + } + else if (flag2 + && flag3 + && flag4) + { + DoSomething2(); + } + else + { + DoSomethingElse(); + DoSomethingEvenMore(); + } + ``` + +- If comparing against values, try to use a `switch` statement instead. + + ```c# + As an if-else statement: + + if (value == 1) + DoValue1(); + else if (value == 2) + DoValue2(); + else if (value == 3) + DoValue3(); + else + DoValueDefault(); + + As a switch statement: + + switch (value) + { + case 1: + DoValue1(); + break; + case 2: + DoValue2(); + break; + case 3: + DoValue3(); + break; + default: + DoValueDefault(); + break; + } + ``` + +- If comparing against values for assignment, try to use a `switch` expression instead. + + ```c# + As an if-else statement: + + int x; + if (value == 1) + x = 0; + else if (value == 2) + x = 1; + else if (value == 3) + x = 2; + else + x = -1; + + As a switch statement: + + int x = value switch + { + 1 => 0, + 2 => 1, + 3 => 2, + _ => -1, + } + ``` + +- When using a `switch` statement, if all switch cases are single-expression, they can be written in-line. You can also add newlines between cases for segmentation or clarity.If the expressions are too complex, they should not be. + + ```c# + switch (value) + { + case 1: DoValue1(); break; + case 2: DoValue2(); break; + case 3: DoValue3(); break; + + default: DoValueDefault(); break; + } + ``` + +- When using a `switch` expression, cases that lead to the same value can be combined using `or`. This is not required, especially if readability would be sacrificed. + + ```c# + int x = value switch + { + 1 or 2 => 0, + 3 or 4 => 1, + 5 or 6 => 2, + _ => -1, + } + ``` + +- If any of the switch cases are multi-expression, write all on separate lines. You can also add newlines between cases for segmentation or clarity. + + ```c# + switch (value) + { + case 1: + DoValue1(); + break; + case 2: + DoValue2(); + break; + case 3: + DoValue3(); + break; + + default: + DoValueDefault(); + DoValueAsWell(); + break; + } + ``` + +### Commenting + +- All classes and methods should contain a `summary` block at bare minimum to explain the purpose. For methods, it is highly recommended to also include `param` tags for each parameter and a `return` tag if the method returns a value. Do not hesitate to use `remarks` as well to include additional information. + + ```c# + /// + /// This class is an example + /// + /// + /// This class does nothing but it is useful to demonstrate + /// coding standards. + /// + public class Example + { + /// + /// This property is the name of the thing + /// + public string Name { get; private set; } + + /// + /// This method is an example method + /// + /// Indicates if the value should be printed + /// A value between 1 and 10, or null on error + public static int? PrintAndReturn(bool shouldPrint) + { + ... + } + } + ``` + +- In-code comments should use the `//` syntax and not the `/* */` syntax, even for multiple lines. + + ```c# + // This code block does something important + var x = SetXFromInputs(y, z); + + // This code block does something really, + // really, really, really important and + // I need multiple lines to say so + var w = SetWFromInputs(x, y, z); + ``` + +- Comments should be expressive and fully explain what is being described. Try to avoid using slang, "pointed comments" such as "you should" or "we do". + +- Comments should avoid the use of first-person writing, such as "I think" or "We found". + +- If comments include links, they can either be included as-is or using the `` tag + + ```c# + // This information can be found from the following site: + // + ``` + +- Try to avoid using multiple, distinct comment blocks next to each other. + + ```c# + // We want to try to avoid this situation where + // we have multiple things to say. + + // Here, the statements are not inherently linked + // but still need to go in the same area. + // + // But here the statements are logically linked but + // needed additional formatting + ```