stylesheet - GesielFreitas/CrossRoads-IJE-UnB GitHub Wiki
This document is the style guide of the crossRoads's project, developed for the discipline of digital games and improved for the discipline of programming techniques, both ministered in Universidade de Brasília.Google C++ Style Guide stylesheet was used as the base, and the needed adaptations were presented on this document.
1. Declarations
2. Indentation
3. Scope
4. Whitespaces
5. Lines
6. Statements
7. Exceptions
8. Comments
9. Documentation
10. Good habits
Each initial letter of each word should be uppercase. In case of a compound name, the words should be together without underscore between them.
class game_object {
}
class button {
}
enum class audiostate {
}
class GameObject {
}
class Button {
}
enum class AudioState {
}
Variables and functions names should be lowercase with underscores between words.
void MonsterAI::processPos() {
...
}
void MonsterAI::Process_pos() {
...
}
hasDamage = false;
hasdamage = false;
void MonsterAI::process_pos() {
...
}
has_damage = false;
Constant names should be uppercase with underscores between words.
const int player_distance = 850;
const int PlayerDistance = 850;
const int Player_distance = 850;
const int PLAYER_DISTANCE = 850;
Use 4 spaces per indentation level.
void Game::set_properties( std::string name, std::pair<int, int> window_size ) {
main_name = name;
main_window_size = window_size;
}
void Game::set_properties( std::string name, std::pair<int, int> window_size ) {
main_name = name;
main_window_size = window_size;
}
void Game::set_properties(std::string name, std::pair<int, int> window_size) {
main_name = name;
main_window_size = window_size;
}
When start a new code block use braces for emulating pure blocks.The opening brace must appear on the same line of the structure who contains it, separated by one whitespace after its end. The closing brace must appear on the line after the block end.
bool Game::start_sdl()
{
...
}
bool Game::start_sdl() { ... }
bool Game::start_sdl(){
...
}
bool Game::start_sdl() {
...
}
When starting a new code block, braces must be used to delimit it.
if( start_sdl() && create_window() )
Log::instance.info("Iniciando o jogo");
if( start_sdl() && create_window() ) Log::instance.info("Iniciando o jogo");
if( start_sdl() && create_window() ) {
Log::instance.info("Iniciando o jogo");
}
If the content within the frame conditions is not empty, a whitespace should be added after opening the parenthesis and another before closing.
if(life == 3) {
...
}
while(value < max ) {
}
if( life == 3 ) {
...
}
while( value < max ) {
}
The opening of the parentheses must be immediately after the sentence calling it not having.
if ( life == 3 ) {
...
}
if( life == 3 ) {
...
}
Empty parentheses should not have whitespaces inside.
move_monster( );
move_monster();
Parameters of functions should not contain spaces in relation to parenthesis. If there is more than one parameter, a whitespace should be included after each separating comma.
m_monster_controler->play_animation("monster_walk",true);
m_monster_controler->play_animation( "monster_walk", true );
m_monster_controler->play_animation( "monster_damage" );
m_monster_controler->play_animation("monster_walk", true);
m_monster_controler->play_animation("monster_damage");
All the operators must be separated from the operands by a whitespace in both sides.
if( life==3 ) {
...
}
move_time= Game::instance.timer->getTicks()+900;
if( life == 3 ) {
...
}
move_time = Game::instance.timer->getTicks() + 900;
The operator accessing a pointer must be adjacent to the referent variable, containing a whitespace before and not after the operator.
GameObject * ground;
GameObject* ground;
Player(GameObject & main_game_object);
GameObject *ground;
Player(GameObject &main_game_object);
Dynamic cast should not have spaces inside the '<' and '>' operators and should contain a whitespace after the cast is closed.
AudioComponent *boss_dash_audio = (dynamic_cast<AudioComponenti*>());
AudioComponent *boss_dash_audio = (dynamic_cast< AudioComponenti* > ());
AudioComponent *boss_dash_audio = (dynamic_cast<AudioComponenti *> ());
AudioComponent *boss_dash_audio = (dynamic_cast<AudioComponenti*> ());
Include statements must contain a space between the include and the call library.
#include"monsterAI.hpp"
#include<stdio.h>
#include "monsterAI.hpp"
#include <stdio.h>
The code must be separated into logical paragraphs by a blank line, so as to make clear the identification of parts of the code, such as initialization of variables, execution of a particular procedure, etc.
Matrix4x4 matrix = new Matrix4x4();
double cosAngle = Math.cos(angle);
double sinAngle = Math.sin(angle);
matrix.setElement(1, 1, cosAngle);
matrix.setElement(1, 2, sinAngle);
matrix.setElement(2, 1, -sinAngle);
matrix.setElement(2, 2, cosAngle);
multiply(matrix);
Matrix4x4 matrix = new Matrix4x4();
double cosAngle = Math.cos(angle);
double sinAngle = Math.sin(angle);
matrix.setElement(1, 1, cosAngle);
matrix.setElement(1, 2, sinAngle);
matrix.setElement(2, 1, -sinAngle);
matrix.setElement(2, 2, cosAngle);
multiply(matrix);
Add one blank line after functions and class declaration and before last key.
bool Boss::init(){
life = 10;
timestep = 0;
move_time = 0;
fireball_time = 0;
side = false;
return true;
}
class Button : public GameObject {
public:
Button();
void update(float timer = 0);
Sprite *button_sprite;
};
bool Boss::init() {
life = 10;
timestep = 0;
move_time = 0;
fireball_time = 0;
side = false;
return true;
}
class Button : public GameObject {
public:
Button();
void update(float timer = 0);
Sprite *button_sprite;
};
In decision structures and loop, the statements should begin in next line after structure declaration.
if( life == 3 ) {
boss_full_putasso_audio->play(0, -1);
}
while( value < max ) {
cout << value << endl;
}
if( life == 3 ) {
boss_full_putasso_audio->play(0, -1);
}
while( value < max ) {
cout << value << endl;
}
If statements should always mark the block with keys. In the case of keywords else and else if you should always start them on the next line after the key is closed.
if( !has_ground() ) {
...
} else {
...
}
if( !has_ground() ) {
...
}
else {
...
}
A line can be a maximum of 80 characters. If it is necessary to break the line it must be indented according to its the origin of its sentence.
if( _main_game_object->main_positionX<0 || _main_game_object->main_positionX+_main_game_object->main_width>800 )
if( _main_game_object->main_positionX<0 ||
_main_game_object->main_positionX+_main_game_object->main_width>800 )
A line should break after a binary operator.
compound_key = (registration
+ id);
compound_key = (registration +
id);
The initialization of variances of a class by passing a list of parameters to the constructor must have a blank before and after the colon - if it fits on a single line. If more than one line is required, the list must start on the next line and be indented according to the parameters of the constructor method.
Heart(GameObject &main_game_objecte): Component(main_game_object, id) {}
Heart(GameObject &main_game_objecte) :
Component(main_game_object, id) {}
Heart(GameObject &main_game_object, std::string id, Player* player, int life):
Component(main_game_object, id), m_player(player), m_life(life) {}
Heart(GameObject &main_game_objecte) : Component(main_game_object, id) {}
Heart(GameObject &main_game_object, std::string id, Player* player, int life) :
Component(main_game_object, id), m_player(player), m_life(life) {}
All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be H. To guarantee uniqueness, they should be based on the full path in a project's source tree.
#define BAZ_H_
...
#endif // BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_
If statements must follow the standard logical flow and must have else statement even if it does not have logical content. If there is no content a comment should be placed with "Do nothing".
if( m_life > m_player->life_points ) {
_main_game_object->setState(GameObject::State::disabled);
}
if( m_life > m_player->life_points ) {
}
else {
_main_game_object->setState(GameObject::State::disabled);
}
if( m_life > m_player->life_points ) {
_main_game_object->setState(GameObject::State::disabled);
}
else {
// Do nothing
}
Assert liberally to document internal assumptions and invariants.
assert(false);
assert( !variable );
Prefer to use exceptions to report errors.
Reasons why exceptions is better than errors:
- Exceptions can't be silently ignored;
- Exceptions propagate automatically;
- Exception handling removes error handling and recovery from the main line of control flow;
- Exception handling is better than the alternatives for reporting errors from constructors and operators.
catch( MyException& e ) {
e.AppendContext("Passed through here");
throw e;
}
catch( MyException& e ) {
e.AppendContext("Passed through here");
throw;
}
All comments should follow the following practices:
- Comments should be complete sentences
- All comments must have a blank line before and after
- Comments must have a maximum of 80 characters per line
- All comments must be idented with the code
- All comments must begin with first letter capitalized
- All comments must be written in English
- Single line comments must be written with // (space) (comment)
- Block comments - two or more lines - shoul d begin / * followed the comment and closed with * / in new line. The content of the comment sho uld be idented in relation to bookmarks /* */.
// Loop to iterate in the range of table
for (i in range 0,10) {
...
};
//Imprimindo a interação
std::cout << i;
// Returns an iterator for this table. It is the client's responsibility to delete the iterator when it is done with it, and it must not use the iterator once the GargantuanTable object on which the iterator was created has been deleted.
// Returns an iterator for this table. It is the client's
// responsibility to delete the iterator when it is done with it,
// and it must not use the iterator once the GargantuanTable object
// on which the iterator was created has been deleted.
/*
Returns an iterator for this table. It is the client's
responsibility to delete the iterator when it is done with it,
and it must not use the iterator once the GargantuanTable object
on which the iterator was created has been deleted.
*/
// Loop to iterate in the range of table
for (i in range 0,10) {
...
};
// Printing the iterator
std::cout << i;
/*
Returns an iterator for this table. It is the client's
responsibility to delete the iterator when it is done with it,
and it must not use the iterator once the GargantuanTable object
on which the iterator was created has been deleted.
*/
The documentation of the code will be done using the Doxygen tool, and the documentation of the tool itself will be used as a basis for structuring the comments of classes, methods and files.
All classes should be commented immediately before their declaration, following the following structure:
/// Short description about class
/**
\class NameClass
Detailed description of the class.
*/
/// Clase for control of player commands
/**
\class Button
Class for communicating the player's input commands with the application
*/
class Button : public GameObject{
...
};
The methods should be commented immediately before their implemantation, following the following structure:
/**
Description of method if necessary
\param param_name this param is considerations about the parameter
\param param_name_2 description this param
\return return this method
*/
If more than one row is required to describe the function parameters, follow the following structure:
/**
Description of method if necessary
\param param_name
\parblock
First paragraph of the param description.
Second paragraph of the param description.
\endparblock
\param param_name_2 description this param
\return return this method
*/
Note: Limits, valid values and units of measure of each parameter should be described as necessary.
/**
\param id
\parblock
This value can not be null
\endparblock
\return Returns the GameObject relative to id
*/
GameObject &Scene::get_game_object(const std::string &id);
All files must contain an initial header following the following structure:
/**
\file nameFile.ext
Description
*/
/**
\file scene.cpp
Scene class implementation
*/
All variables must contain an description following the following structure:
/**
This is the description of a variable
*/
std::string main_path;
/**
This is the description of a second variable
*/
SDL_Texture *main_texture;
Macros can be placed in comments using the \note, \warning \bug, and \tags when necessary to flag some of these situations.
/**
\note My note about this code
\warning this is a critical section
\todo to implement
\bug problem in project
*/
In the case of milestones in a specific line of code you can follow the following pattern in the comment:
/// \note My note about this code
scene_objects[id] = &obj;
This section aims describe good habits that should be adopted on a daily basis in programmer routine for the purpose of generate code safe, clean and principally easy to maintain.
- Follow the style sheet;
- Prioritize clarity rather than conciseness:
- Prioritize simple resolutions;
- Break the code into smaller pieces;
- Break arithmetic expressions;
- Reduce scope
- Protect data and internal functions;
- Avoid using global variables;
- Never ignore compiler warnings;
- Use secure data structures;
- Check all return values;
- Fix errors received
- Release the resources(memory, threads, files, locks...) that are no more used;
- Initialize all variables in declaration;
- Declare the variables as close to their use as possible;
- Don't reuse the auxiliary variables name;
- Don't abbreviate the names of variables, functions, classes, and constants
- Use standard language sentences and resources.