Skip to content

Commit 7563634

Browse files
committed
Add coding guide
1 parent d74dcc1 commit 7563634

File tree

1 file changed

+353
-0
lines changed

1 file changed

+353
-0
lines changed

Coding Guide.md

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
# Coding Guide
2+
3+
This document serves as the official code standards guide for `BurnOutSharp` internal development. Please note that this is a work in progress and may not encapsulate all standards expected of new or existing code.
4+
5+
## General Code Guidelines
6+
7+
This section contains information on code standards regardless of which part of the project you are working in.
8+
9+
### Style and Naming
10+
11+
- Prefer `System` namespaces for supporting operations before external ones.
12+
13+
- Ordering of `using` statements goes:
14+
- `using System.*`
15+
- `using <Alphabetical>`
16+
- `using static <Alphabetical>`
17+
- `using X <Alphabetical> = Y`
18+
19+
- Use 4 spaces for `tab`.
20+
21+
- Curly braces should generally start on the line after but inline with the start of the previous statement, even if multiline.
22+
23+
```
24+
if (flag)
25+
{
26+
DoSomething();
27+
}
28+
else if (flag2
29+
&& flag3)
30+
{
31+
DoSomething2();
32+
}
33+
```
34+
35+
- Multi-line statements need to have following lines indented by one step at minimum.
36+
37+
```
38+
if (flag)
39+
{
40+
DoSomething();
41+
}
42+
else if (flag2
43+
&& flag3
44+
&& (flag4
45+
|| flag5))
46+
{
47+
DoSomething2();
48+
}
49+
```
50+
51+
- Methods and classes should use `PascalCase` for naming, even `internal` and `private` ones.
52+
53+
- Class properties should use `PascalCase` for naming, even `protected` and `internal` ones.
54+
55+
- Instance variables should use `camelCase` with a `_` prefix for naming, even `protected`, `internal`, and `private` ones.
56+
57+
- In-method variables should use `camelCase` without a `_` prefix for naming.
58+
59+
- Include explicit access modifiers for all class-level properties, variables, and methods.
60+
61+
- Avoid making everything `public`; only include the necessary level of access.
62+
63+
- 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.
64+
65+
- 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.
66+
67+
```
68+
if (obj?.Parameter != null) { ... }
69+
70+
bool value = DoSomething() ?? false;
71+
```
72+
73+
- `#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.
74+
75+
```
76+
#region This is the first region
77+
78+
public static void Method()
79+
{
80+
#region This is an in-code region
81+
82+
DoSomething();
83+
84+
#endregion
85+
86+
DoSomething2();
87+
}
88+
89+
#endregion
90+
```
91+
92+
- Try to avoid use of other preprocessor directives unless consulting ahead of time with the maintainers.
93+
94+
- Interfaces should be listed in alphabetical order
95+
96+
```
97+
public class Example : IBindable, IComparable, IEquatable
98+
```
99+
100+
- Use the `<inheritdoc/>` tag when possible to avoid out-of-date information.
101+
102+
```
103+
public interface IInterface
104+
{
105+
/// <summary>
106+
/// Summary to inherit
107+
/// </summary>
108+
void DoSomething();
109+
}
110+
111+
public class Example : IInterface
112+
{
113+
/// <inheritdoc/>
114+
public void DoSomething() { ... }
115+
}
116+
```
117+
118+
### Methods
119+
120+
- 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.
121+
122+
- Try to use expressive naming. e.g. use names like `PrintSectionTitles` and not `DoTheThing`.
123+
124+
- Try to avoid having too many parameters in a method signature. More parameters means more things interacting.
125+
126+
- Use method overloading to avoid unnecessary complexity in a single method.
127+
128+
```
129+
Instead of:
130+
131+
Print(string idString, byte[] idArray, int idInt) { ... }
132+
133+
You should:
134+
135+
Print(string id) { ... }
136+
137+
Print(byte[] id) { ... }
138+
139+
Print(int id) { ... }
140+
```
141+
142+
- Use optional parameters when the default value is the most common.
143+
144+
```
145+
Print(string id, bool toLower = false) { ... }
146+
```
147+
148+
### `if-else` and `switch` statement syntax
149+
150+
- If all statements in the block are single-line, do not include curly braces.
151+
152+
```
153+
if (flag)
154+
DoSomething();
155+
else if (flag2)
156+
DoSomething2();
157+
else
158+
DoSomethingElse();
159+
```
160+
161+
- If any of the statements is multi-line _or_ the `if-else` statement is multi-line, include curly braces.
162+
163+
```
164+
if (flag)
165+
{
166+
DoSomething();
167+
}
168+
else if (flag2
169+
&& flag3
170+
&& flag4)
171+
{
172+
DoSomething2();
173+
}
174+
else
175+
{
176+
DoSomethingElse();
177+
DoSomethingEvenMore();
178+
}
179+
```
180+
181+
- If comparing against values, try to use a `switch` statement instead.
182+
183+
```
184+
As an if-else statement:
185+
186+
if (value == 1)
187+
DoValue1();
188+
else if (value == 2)
189+
DoValue2();
190+
else if (value == 3)
191+
DoValue3();
192+
else
193+
DoValueDefault();
194+
195+
As a switch statement:
196+
197+
switch (value)
198+
{
199+
case 1:
200+
DoValue1();
201+
break;
202+
case 2:
203+
DoValue2();
204+
break;
205+
case 3:
206+
DoValue3();
207+
break;
208+
default:
209+
DoValueDefault();
210+
break;
211+
}
212+
```
213+
214+
- 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.
215+
216+
```
217+
switch (value)
218+
{
219+
case 1: DoValue1(); break;
220+
case 2: DoValue2(); break;
221+
case 3: DoValue3(); break;
222+
223+
default: DoValueDefault(); break;
224+
}
225+
```
226+
227+
- 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.
228+
229+
```
230+
switch (value)
231+
{
232+
case 1:
233+
DoValue1();
234+
break;
235+
case 2:
236+
DoValue2();
237+
break;
238+
case 3:
239+
DoValue3();
240+
break;
241+
242+
default:
243+
DoValueDefault();
244+
DoValueAsWell();
245+
break;
246+
}
247+
```
248+
249+
### Commenting
250+
251+
- 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.
252+
253+
```
254+
/// <summary>
255+
/// This class is an example
256+
/// </summary>
257+
/// <remarks>
258+
/// This class does nothing but it is useful to demonstrate
259+
/// coding standards.
260+
/// </remarks>
261+
public class Example
262+
{
263+
/// <summmary>
264+
/// This property is the name of the thing
265+
/// </summary>
266+
public string Name { get; private set; }
267+
268+
/// <summary>
269+
/// This method is an example method
270+
/// </summary>
271+
/// <param name="shouldPrint">Indicates if the value should be printed</param>
272+
/// <returns>A value between 1 and 10, or null on error</returns>
273+
public static int? PrintAndReturn(bool shouldPrint)
274+
{
275+
...
276+
}
277+
}
278+
```
279+
280+
- In-code comments should use the `//` syntax and not the `/* */` syntax, even for multiple lines.
281+
282+
```
283+
// This code block does something important
284+
var x = SetXFromInputs(y, z);
285+
286+
// This code block does something really,
287+
// really, really, really important and
288+
// I need multiple lines to say so
289+
var w = SetWFromInputs(x, y, z);
290+
```
291+
292+
- 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".
293+
294+
- If comments include links, they can either be included as-is or using the `<see href="value"/>` tag
295+
296+
```
297+
// This information can be found from the following site:
298+
// <see href="www.regex101.com"/>
299+
```
300+
301+
- Try to avoid using multiple, distinct comment blocks next to each other.
302+
303+
```
304+
// We want to try to avoid this situation where
305+
// we have multiple things to say.
306+
307+
// Here, the statements are not inherently linked
308+
// but still need to go in the same area.
309+
//
310+
// But here the statements are logically linked but
311+
// needed additional formatting
312+
```
313+
314+
## Project and Class Organization
315+
316+
This section contains information on project and class organization principles that depend on the part of the project you are working in. See the following table for details.
317+
318+
| Project | Description |
319+
| --- | --- |
320+
| `BurnOutSharp` | One file per class. See below for details on subdirectories. |
321+
| `BurnOutSharp/External` | One directory per external project. |
322+
| `BurnOutSharp/FileType` | One file per file type. |
323+
| `BurnOutSharp/Interfaces` | One file per interface. |
324+
| `BurnOutSharp/PackerType` | At least one file per packer type. Partial classes allowed. |
325+
| `BurnOutSharp/ProtectionType` | At least one file per protection type. Partial classes allowed. |
326+
| `BurnOutSharp/Tools` | Two files - one for extension methods and one for utilities. |
327+
| `BurnOutSharp.Builder` | One file per executable type. |
328+
| `BurnOutSharp.Matching` | Flat directory structure. Include interfaces and base classes. |
329+
| `BurnOutSharp.Models` | One directory per executable type. One file per object model. |
330+
| `BurnOutSharp.Wrappers` | One file per executable type. Common functionality goes in `WrapperBase.cs`. |
331+
| `Test` | All functionality lives in `Program.cs`. |
332+
333+
If the project or directory you are looking for is not included in the above, please consider it to be outside the context of this document.
334+
335+
## Code Organization
336+
337+
This section contains information on in-code organization principles that depend on the part of the project you are working in. See the following table for details.
338+
339+
| Project | Description |
340+
| --- | --- |
341+
| `BurnOutSharp` | Varies from file to file. |
342+
| `BurnOutSharp/FileType` | `Scan(Scanner, string)`, `Scan(Scanner, Stream, string)`, helper methods. |
343+
| `BurnOutSharp/Interfaces` | Methods ordered alphabetically. |
344+
| `BurnOutSharp/PackerType` | `IContentCheck` implementations, `INewExecutableCheck` implementations, `IPortableExecutableCheck` implementations, `IPathCheck` implementations, `IScannable` implementations, helper methods. |
345+
| `BurnOutSharp/ProtectionType` | `IContentCheck` implementations, `INewExecutableCheck` implementations, `IPortableExecutableCheck` implementations, `IPathCheck` implementations, `IScannable` implementations, helper methods.. |
346+
| `BurnOutSharp/Tools` | Methods grouped by function. Regions ordered alphabetically. |
347+
| `BurnOutSharp.Builder` | Two copies of each non-generic method: one for byte arrays and one for Streams. |
348+
| `BurnOutSharp.Matching` | Varies from file to file.. |
349+
| `BurnOutSharp.Models` | No methods at all, just properties. |
350+
| `BurnOutSharp.Wrappers` | Follow region and method grouping from existing wrappers. |
351+
| `Test` | New functionality should be added as a combination of a flag with a long and a short form, a new line in the help text, and a new method (if necessary). |
352+
353+
If the project or directory you are looking for is not included in the above, please consider it to be outside the context of this document.

0 commit comments

Comments
 (0)