mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2024-12-22 20:17:24 +08:00
refactor: Updating CONTRIB to be more relevant (#568)
This commit is contained in:
parent
32c3a75d5d
commit
08502a2cd4
329
CONTRIBUTING.md
329
CONTRIBUTING.md
@ -1,92 +1,291 @@
|
||||
# Contributing
|
||||
# Contrib
|
||||
|
||||
## Table of contents
|
||||
### Commit convention
|
||||
|
||||
* [Committing](#committing)
|
||||
* [When to commit?](#when-to-commit)
|
||||
* [What sort of message should I use?](#what-sort-of-commit-message-should-i-use)
|
||||
* [Other Types](#other-types)
|
||||
* [Code Style](#code-style)
|
||||
* [Brackets](#brackets)
|
||||
* [Distinction between related code](#distinction-between-related-code)
|
||||
**Don't overthink it, we can edit the final commit message if it doesn't describe the changes correctly!**
|
||||
|
||||
## Committing
|
||||
Types:
|
||||
- feat: The new feature you're adding to a particular application
|
||||
- fix: To fix a bug
|
||||
- style: Feature and updates related to styling
|
||||
- refactor: Refactoring a specific section of the codebase
|
||||
- test: Everything related to testing
|
||||
- docs: Everything related to documentation
|
||||
- chore: Regular code maintanance
|
||||
|
||||
### When to commit?
|
||||
A scope is a phrase descibing parts of the code affected by the changes. For example "(userservice)"
|
||||
|
||||
Whenever you commit make sure your commit is related to one feature or change, don't commit multiple unrelated things at once.
|
||||
You don't **have** to commit every 5 minutes, only commit whenever you've got a working code base with a finished feature.
|
||||
Body (optional) can provide additional contextual information. For breaking changes the body MUST start with "BREAKING CHANGE".
|
||||
|
||||
Footer (optional) is used to reference issues effected bt the code changes. For example "Fixes #13". Can also be used to indicate breaking changes by starting with "BREAKING CHANGE".
|
||||
#### Structure
|
||||
|
||||
### What sort of commit message should I use?
|
||||
|
||||
If you're committing a new feature or change something existing to act differently use the following syntax:
|
||||
```
|
||||
feat(subject): Added new method of destroying children
|
||||
<type>(scope): <description>
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer]
|
||||
```
|
||||
|
||||
If your commit is related to fixing an issue:
|
||||
```
|
||||
fix(subject): Fixed issue related to children multiplying endlessly
|
||||
#### Examples
|
||||
- `feat(order): add purchase order button`
|
||||
- `docs(readme): document coding conventions`
|
||||
|
||||
Closes #1337 <-- mention a related issue to automatically close it when making this commit
|
||||
|
||||
# C++ Coding Standards
|
||||
## Naming Style
|
||||
|
||||
Avoid Hun-garian notation.
|
||||
This means, we never want to use variable names that contain the type.
|
||||
|
||||
| Entities | Naming | Preview |
|
||||
| ----------- | ----------- | ---------- |
|
||||
| NameSpaces | snake_case | namespace `ex_namespace` |
|
||||
| Classes and Structs | snake_case | Class `ex_class` |
|
||||
| Enums | UpperCamelCase | Enum `ExEnum` |
|
||||
| Enum Members | ALL_UPPER | ExNum::`NONE`; ExNum::`FIRST_HALF`; ...
|
||||
| Global Variables| g_snake_case | bool `g_running` |
|
||||
| Macros | ALL_UPPER | #define `USE_OPENGL` |
|
||||
| Template Parameter | UpperCamelCase | template<`typename T`> |
|
||||
| Parameters | snake_case | ex_method(int `number`) |
|
||||
| Local Variables | snake_case | int `number{}` |
|
||||
| Member Variables | m_snake_case | int `m_number` |
|
||||
| Member Methods | snake_case | void `ex_method`(int param1, int param2); |
|
||||
|
||||
<br><br><br>
|
||||
|
||||
## Formatting Style
|
||||
### **Indents**
|
||||
prefer Tabs for indents
|
||||
|
||||
### **Braces**
|
||||
|
||||
With `if` statements and `for` loops we drop the brackets if it only has to execute 1 line of code or if it calls a method
|
||||
```c++
|
||||
if (true)
|
||||
execute_method();
|
||||
|
||||
int num;
|
||||
if (true)
|
||||
num += 5;
|
||||
|
||||
for (;;)
|
||||
execute_method();
|
||||
|
||||
for (;;)
|
||||
num += 5;
|
||||
```
|
||||
|
||||
#### Other Types
|
||||
|
||||
Aside from `feat` and `fix`, you can also use the following types `build`, `docs`, `style`, `refactor` and `test` whenever you deem these more useful in the context.
|
||||
|
||||
## Code Style
|
||||
|
||||
1. Be consistent
|
||||
2. Use 4 spaces for tab indentation, don't ever use HARD tabs
|
||||
|
||||
### Brackets
|
||||
|
||||
```cpp
|
||||
for (int i = 1; i < 5; i++)
|
||||
Example for namespaces, classes, etc...
|
||||
```c++
|
||||
namespace ex_namesspace
|
||||
{
|
||||
//code here;
|
||||
class ex_class
|
||||
{
|
||||
public:
|
||||
ex_class()
|
||||
{
|
||||
}
|
||||
|
||||
void ex_method();
|
||||
|
||||
int GetNum() const
|
||||
{
|
||||
return m_num;
|
||||
}
|
||||
private:
|
||||
int m_num;
|
||||
}
|
||||
}
|
||||
|
||||
ex_namesspace::ex_class::ex_method()
|
||||
{
|
||||
auto lambda = []()
|
||||
{
|
||||
int x = 0;
|
||||
return x;
|
||||
};
|
||||
|
||||
switch (expression)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
// do stuff
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
// do stuff
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// do stuff
|
||||
} while (true);
|
||||
}
|
||||
```
|
||||
### **Regarding if statements**
|
||||
|
||||
Prefer default initialized variables that will be set in an if
|
||||
|
||||
Bad example:
|
||||
```c++
|
||||
int value;
|
||||
if(true)
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = 2
|
||||
}
|
||||
```
|
||||
Instead we prefer this:
|
||||
```c++
|
||||
int value{2};
|
||||
if(true)
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
```
|
||||
|
||||
### Distinction between related code
|
||||
|
||||
Create a clear line of separation between lines, don't just put everything right next each other.
|
||||
Prefer using guarding `if` statements for readability
|
||||
|
||||
How not to do it:
|
||||
```cpp
|
||||
void foo() {
|
||||
int x = fribbery;
|
||||
y.attack(frabbet(x));
|
||||
z.attack(frobbet(x));
|
||||
bejooger[0].scramboozle(y);
|
||||
bejooger[1].scramboozle(y);
|
||||
bejooger[2].scramboozle(z);
|
||||
bejooger[3].scramboozle(z);
|
||||
if (curdleblogpod.getAlive() <= 5) {
|
||||
//Yikes!
|
||||
}
|
||||
Bad Example:
|
||||
```c++
|
||||
void method()
|
||||
{
|
||||
bool val1 = true;
|
||||
bool val2 = false;
|
||||
bool val3 = true;
|
||||
|
||||
if(val1)
|
||||
{
|
||||
if(val2)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if(val3)
|
||||
{
|
||||
// code part
|
||||
// where tf are we at
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
How you should do it:
|
||||
```cpp
|
||||
void foo() {
|
||||
Guarded if Example:
|
||||
```c++
|
||||
void method()
|
||||
{
|
||||
bool val1 = true;
|
||||
bool val2 = false;
|
||||
bool val3 = true;
|
||||
|
||||
//Start the attack on the fribs.
|
||||
int x = fribbery;
|
||||
y.attack(frabbet(x));
|
||||
z.attack(frobbet(x));
|
||||
|
||||
//Now send the bejoogers out...
|
||||
bejooger[0].scramboozle(y);
|
||||
bejooger[1].scramboozle(y);
|
||||
bejooger[2].scramboozle(z);
|
||||
bejooger[3].scramboozle(z);
|
||||
if(!val1)
|
||||
return;
|
||||
|
||||
//Make sure the curdleblogs are still alive.
|
||||
if (curdleblogpod.getAlive() <= 5) {
|
||||
//Yikes!
|
||||
}
|
||||
if (val2)
|
||||
return;
|
||||
|
||||
if (!val3)
|
||||
return;
|
||||
|
||||
// here comes the code part
|
||||
}
|
||||
```
|
||||
|
||||
### **Member variables in classes**
|
||||
|
||||
1. Seperate every variable to a single line
|
||||
2. Initialize all member variables
|
||||
3. Use the same order of initialization as in the header file
|
||||
4. Order data types from big to low
|
||||
|
||||
```c++
|
||||
// Header File
|
||||
class ex_class
|
||||
{
|
||||
public:
|
||||
ex_class();
|
||||
|
||||
private:
|
||||
float m_Length;
|
||||
int m_Number;
|
||||
bool m_Enabled;
|
||||
}
|
||||
|
||||
// Cpp File
|
||||
ex_class::ex_class() :
|
||||
m_Length{ 1.f },
|
||||
m_Number{ 5 },
|
||||
m_Enabled { true }
|
||||
{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### use of auto
|
||||
1. Not for numeric types: `int, bool, char, float, ...`
|
||||
2. When methods return a value
|
||||
3. Only when r-value type is evident
|
||||
4. Prefer using `auto&` to avoid copies
|
||||
```c++
|
||||
// 1.
|
||||
int a{ 0 };
|
||||
float b{ 0.5f };
|
||||
// 2.
|
||||
const auto& data = exClass->GetData();
|
||||
// 3.
|
||||
auto timer = new TimerClass();
|
||||
```
|
||||
|
||||
### using keyword
|
||||
|
||||
- **Never use `using namespace std`!**
|
||||
- Never use `using namespace` in a header file. This can mess with code that includes the header file wich contains `using namespace`.
|
||||
- Never use `using namespace` before any `#include`s. This can mess with the meaning of code in someone else's header.
|
||||
- Use `using` instead of typedef! Modernized c++
|
||||
```c++
|
||||
// bad example
|
||||
typedef int my_int;
|
||||
|
||||
// good example
|
||||
using my_float = float;
|
||||
```
|
||||
- Prefer specified using over namespace using.
|
||||
```c++
|
||||
// bad example
|
||||
using namepace std::chrono;
|
||||
|
||||
// good examples
|
||||
using std::chrono::high_resolution_clock;
|
||||
using std::chrono::duration;
|
||||
```
|
||||
|
||||
Nested Namespaces
|
||||
Example:
|
||||
```c++
|
||||
// bad example
|
||||
namespace a
|
||||
{
|
||||
namespace b {}
|
||||
}
|
||||
|
||||
// good example
|
||||
namespace a::b {}
|
||||
```
|
||||
|
||||
### overriding methods
|
||||
1. Use `virtual` in Base classes
|
||||
2. Use `virtual` and `override` in Derived classes
|
||||
3. Use `virtual` and `= 0` for an abstract(instantiable) class
|
||||
4. Always make destructors `virtual`
|
Loading…
Reference in New Issue
Block a user