update readme with coding guidelines

This commit is contained in:
Skarn
2021-12-12 16:56:44 +03:00
parent 227d455600
commit 7ec40c53ba

223
README.md
View File

@@ -2,15 +2,13 @@
This software is open source software licensed under GPL3, as found in
the COPYING file.
# DISCORD #
You can follow Noggit's development and get the latest build here: https://discord.gg/UbdFHyM
# BUILDING #
This project requires CMake to be built. It also requires the
following libraries:
* OpenGL
* StormLib (by Ladislav Zezula)
* CascLib (by Ladislav Zezula)
* Boost
* Qt 5
@@ -113,101 +111,140 @@ To pull the latest version of submodules use the following command at the root d
git submodule update --recursive --remote
```
# DEVELOPMENT #
Feel free to ask the owner of the official repository
(https://github.com/wowdev/noggit3) for write access or
fork and post a pull request.
There is a bug tracker at https://github.com/wowdev/noggit3/issues which should be used.
Discord, as linked above, may be used for communication.
# CODING GUIDELINES #
Following is an example for file `src/noggit/ui/foo_ban.hpp`. `.cpp` files
are similar.
File naming rules:
```.hpp``` - is used for header files (C++ language).
```.h``` - is used **only** for header files or modules written in C language.
```.c``` - is used **only** for implementation files or modules written in C language.
```.cpp``` - is used for project implementation files.
```.inl``` - is used for include files providing template instantiations.
```.ui``` - is used for QT UI definitions (output of QtDesigner/QtCreator).
### Project structure: ###
```/src/Noggit``` - is the main directory hosting .cpp, .hpp, .inl, .ui files of the project.
Within this directory the subdirs should correspond to namespace names (case sensitive).
File names should use PascalCase (e.g. ```FooBan.hpp```) and either correspond to the type defined in the file,
or represent sematics of the module.
```/src/External``` - is the directory of hosting included libraries and subprojects. This is external or modified
external code, so no rules from Noggit project apply to its content.
```/src/Glsl``` - is the directory to store .glsl shaders for the OpenGL renderer. It is not recommended,
but not strictly prohibited to inline shader code as strings to ```.cpp``` implementation files.
### Code style ###
Following is an example for file `src/Noggit/Ui/FooBan.hpp`.
```cpp
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
//! \note Include guard shall be using #pragma once
#pragma once
//! \note Use fully qualified paths rather than "../relative". Order
//! includes with own first, then external dependencies, then c++ STL.
#include <noggit/bar.hpp>
//! \note Namespaces equal directories. (java style packages.)
namespace noggit
{
namespace ui
{
//! \note Lower case, underscore separated.
class foo_ban : public QWidget
{
Q_OBJECT;
public:
//! \note Long parameter list. Would be more than 80 chars.
//! chars. Break with comma in front. Use spaces to be
//! aligned below the braces.
foo_ban ( type name
, type_2 const& name_2
, type const& name3
)
: QWidget (nullptr)
//! \note Prefer initialization lists over assignment.
, _var (std::move (name))
{}
#ifndef INCLUDE_GUARD_BASED_ON_FILENAME
#define INCLUDE_GUARD_BASED_ON_FILENAME
// We do not use #pragma once in headers as it is technically not cross-platform.
// Use include guards instead. For example, CLion IDE creates them automatically on .hpp file creation.
//! \note Use const where possible. No space between name and
//! braces when no arguments are given.
void render() const;
//! \note If you really need getters and setters, your design
//! might be broken. Please avoid them or consider just a
//! public data member, or use proper methods with semantics.
type const& var() const
{
return _var;
}
void var (type var_)
{
_var = std::move (var_);
}
//! \note Prefer const where possible. If you need to copy,
//! just take a `T`. Otherwise prefer taking a `T const&`.
//! Don't bother when it comes to tiny types.
baz_type count_some_numbers ( std::size_t begin
, std::size_t end
) const
{
bazs_type bazs;
//! \note Prefer construction over assignment. Prefer
//! preincrement.
for (size_t it (begin); it != end; ++it)
{
bazs.emplace_back (it);
}
//! \note Prefer STL algorithms over hand written code.
assert (!bazs.empty());
auto const smallest
(std::min_element (bazs.begin(), bazs.end()));
return *smallest;
}
// <> are prefered for includes.
// Local imports go here
#include <SomeLocalFile.hpp>
// Lib imports go here
#include <external/SomeLibCode.hpp
// STL imports go here
#include <string>
#include <mutex>
#include <vector> // etc
// Forward declarations in headers are encouraged. That prevents type leaking into bigger scopes
// Also reduces compile time
namespace Parent::SomeOtherChild
{
class ForwardDeclaredClass;
}
// Namespaces are defined as PascalCase names. Namespace concatenation for nested namespaces
// is adviced, but not strictly enforced.
namespace Parent::Child
{
// types are name in PascalCase,
class Test : public TestBase
{
public:
Test();
int x; // public fields like that are discourged, but occur here and there through the project.
// Subject to refactoring.
// methods are named in camelCase.
// trivial getter methods are declared in the header file.
int somePrivateMember() { return _some_private_member; } const;
// trivial setters are declared in the header file. Preceded by "set" prefix.
void setSomePrivateMember(int a) { _some_private_member = a; };
// private members are snake lower case, separated by underscore, preceded by underscore to indicate they're private.
private:
int _some_private_member;
ForwardDeclaredClass* _some_other_private_member_using_forward_decl;
std::mutex _mutex;
// static methods
private:
//! \note Member variables are prefixed with an underscore.
type _var;
//! \note Typedef when using complex types. Fully qualify
//! types.
using baz_type = type_2;
using bazs_type = std::vector<baz_type>;
bazs_type _bazs;
}
}
static void someStaticMethod();
};
}
#endif
```
Following is an example for file `src/Noggit/Ui/FooBan.cpp`.
```cpp
// the header of this .cpp comes first
// <> are prefered for includes.
#include <Noggit/Ui/FooBan.hpp>
// same order of includes as in header.
using namespace Parent::Child;
Test::Test()
: TestBase("some_arg")
, _some_private_member(0)
, _some_other_private_member_using_forward_decl(new ForwardDeclaredClass()) // do not forget to import ForwardDeclaredClass in .cpp
{
// body of ctor
}
void Test::someStaticMethod()
{
// local variables are named in snake_case, no preceding underscore.
int local_var = 0;
// preceding underscore is used on variables that are used for RAII patterns, such as scoped stuff (e.g. a scoped mutex)
std::lock_guard<std::mutex> _lock (_mutex); // _lock is never accessed later, it just needs to live as long as the scope lives.
// So, it has an underscore prefix.
someFunc(local_var); // free floating functions use the same naming rules as methods
}
```
Additional examples:
```cpp
constexpr unsigned SOME_CONSTANT = 10; // constants are named in SCREAMING_CASE
#define SOME_MACRO // macro definitions are named in SCREAMING_CASE
```