Browse Source

Create guidelines.md

norm 6 years ago
parent
commit
ac6b5ae996
1 changed files with 156 additions and 0 deletions
  1. 156 0
      guidelines.md

+ 156 - 0
guidelines.md

@@ -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 commiting 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::earse
+
+##### Reason
+
+`std::vector` requires to be shrinked after using `std::remove`. To avoid forgetting about proper shrinking after removing an element the removing should always be bound to a call to `earse`.
+
+##### 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 iniated with a return value of a function call which does not indicate the type. This is only required when using the fucnction 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.