Compare commits

...

3 Commits

Author SHA1 Message Date
Aleos
e1997bc11f
Small typos
* Fixed a couple other small typos.
2019-04-23 10:06:29 -04:00
norm
9fd95bf006
Fixed typo 2019-04-10 22:48:36 +02:00
norm
ac6b5ae996
Create guidelines.md 2019-04-10 20:09:29 +02:00

156
guidelines.md Normal file
View File

@ -0,0 +1,156 @@
# Welcome
Welcome to the rAthena Code Guidelines.
This is here to help all developers in creating safe, maintainable, easily readable and understandable code.
# References
These guidelines are inspired by the CppCoreGuidelines. Some of the examples below maybe taken directly from there.
If you need more information that may not be listed here, please be sure to check out [CppCoreGuidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md).
If your questions are still unanswered after consulting this or CppCoreGuidelines, consider consulting the [rAthena forum](https://rathena.org/board/), [rAthena's Discord](https://rathena.org/discord/), or add your concerns directly to a pull request.
# Code Guidelines
### 1. Don't unnecessarily remove or add blank lines when committing new code
##### Reason
Commits should be on point, documented and as small as possible.
##### Enforcement
Check for removed or added blank lines on each commit.
### 2. Use std::remove_if, std::remove & ... within std::vector::erase
##### Reason
`std::vector` requires to be shrunk after using `std::remove`. To avoid forgetting about proper shrinking after removing an element the removing should always be bound to a call to `erase`.
##### Note
If using a `std::list` one should rely on `std::list::remove` instead of `std::remove`.
##### Example
vec.erase(std::remove_if(vec.begin(), vec.end(), [](int a) {return a % 2 == 0;}), vec.end()); // good
##### Enforcement
Check for `std::remove` on datatype `std::vector` without being surrounded by an `erase`.
### 3. Don't add redundant `==` or `!=` to conditions
##### Reason
Doing so avoids verbosity and eliminates some opportunities for mistakes.
Helps make style consistent and conventional.
##### Example
By definition, a condition in an `if`-statement, `while`-statement, or a `for`-statement selects between `true` and `false`.
A numeric value is compared to `0` and a pointer value to `nullptr`.
// These all mean "if `p` is not `nullptr`"
if (p) { ... } // good
if (p != 0) { ... } // redundant `!=0`; bad: don't use 0 for pointers
if (p != nullptr) { ... } // redundant `!=nullptr`, not recommended
Often, `if (p)` is read as "if `p` is valid" which is a direct expression of the programmers intent,
whereas `if (p != nullptr)` would be a long-winded workaround.
##### All examples
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es87-dont-add-redundant--or--to-conditions
##### Note
Explicit comparison of an integer to `0` is in general not redundant.
The reason is that (as opposed to pointers and Booleans) an integer often has more than two reasonable values.
Furthermore `0` (zero) is often used to indicate success.
Consequently, it is best to be specific about the comparison.
void f(int i)
{
if (i) // suspect
// ...
if (i == success) // possibly better
// ...
}
Always remember that an integer can have more than two values.
##### Enforcement
Easy, just check for redundant use of `!=` and `==` in conditions.
### 5. Avoid "magic constants"; use symbolic constants
##### Reason
Unnamed constants embedded in expressions are easily overlooked and often hard to understand:
##### Example
for (int m = 1; m <= 12; ++m) // don't: magic constant 12
cout << month[m] << '\n';
No, we don't all know that there are 12 months, numbered 1..12, in a year. Better:
// months are indexed 1..12
constexpr int first_month = 1;
constexpr int last_month = 12;
for (int m = first_month; m <= last_month; ++m) // better
cout << month[m] << '\n';
Better still, don't expose constants:
for (auto m : month)
cout << m << '\n';
##### Enforcement
Flag literals in code. Give a pass to `0`, `1`, `nullptr`, `\n`, `""`, and others on a positive list.
### 4. Use `auto` to avoid redundant repetition of type names
##### Reason
* Simple repetition is tedious and error-prone.
* When you use `auto`, the name of the declared entity is in a fixed position in the declaration, increasing readability.
* In a template function declaration the return type can be a member type.
##### Example
Consider:
auto p = v.begin(); // vector<int>::iterator
auto h = t.future();
auto q = make_unique<int[]>(s);
auto f = [](int x){ return x + 10; };
In each case, we save writing a longish, hard-to-remember type that the compiler already knows but a programmer could get wrong.
##### Exception
Avoid 'auto' when declaring a variable which is directly initiated with a return value of a function call which does not indicate the type. This is only required when using the function call the first time within a method.
Also avoid `auto` for initializer lists and in cases where you know exactly which type you want and where an initializer might require conversion.
##### Example (bad)
auto lst = { 1, 2, 3 }; // lst is an initializer list
auto x{1}; // x is an int (in C++17; initializer_list in C++11)
##### Example (good)
void some_function()
{
my_type a = my_function();
auto b = my_function(); // here we already know the return type of 'my_function'
...
}
##### All examples
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es11-use-auto-to-avoid-redundant-repetition-of-type-names
##### Enforcement
Flag redundant repetition of type names in a declaration.