Estándares de forma y estilo de código - SeriousGamesStudio/Serious-Train-2-3D GitHub Wiki

Estándares de forma y estilo de código

Normas de creación de código y VCS

  • Don’t push master. Trabaja siempre en la rama propia del feature del cual te estás encargando, el master por definición es la última versión estable del juego, sólo se ‘pushea’ mediante ‘merges’.
  • Don’t merge with master Los merges son un proceso complicado del cual pueden surgir muchos problemas. Si has terminado el desarrollo de tu rama notifícalo al lead programmer, él se encargará de decidir cómo se hace. Pero sí puedes hacer merge entre tus ramas, tú (o tu equipo) debe ser responsable de que la versión resultante sea funcional.
  • Comenta tu código. En serio, es gratis y así todos podremos entender tu fantástico trabajo. Aunque*.
  • Sigue los estándares de programación. Un código uniforme ayuda a que se entienda mejor, haciendo que el trabajo sea más fácil para todos.
  • No seas cutre Los apaños son sólo eso, apaños, no son soluciones, y por lo tanto nunca tienen que estar en una versión final.

Si no sabes algo, aprende. Si no sabes cómo hacer algo investiga cómo hacerlo, mira en internet, pregunta, llora, reza, pero sácalo hacia adelante.

Estándares de Programación

  • Capitaliza los nombres de clase
  • Las variables van en minúscula
  • El nombre de variable ha de ser inferior a 20 chars y representativo
  • Si el nombre de variable consta de varias palabras utiliza camelCase
  • Trata de ser const correct, es decir: utiliza constsiempre que puedas.
  • Se prefiere siempre la referencia al puntero. Son igual de eficientes pero producen muchos menos errores.
  • No uses break, si tienes que terminar un bucle antes de tiempo utiliza una condición de parada. A excepción de que sepas lo que haces y que el código quede suficientemente claro con él (self-explanatory).
  • Si tienes que hacer un recorrido completo sobre una colección de objetos utiliza for each, permitiéndose la tipificación mediante auto. De esta forma la iteracción es independiente del tipo de container que se utilice.
  • Se prefiere el uso de class enum al de enum, salvo que quieras utilizar casting implícito sabiendo lo que haces.
  • Si tienes pensado hacer un Objeto/Tipo con todos los atributos y metodos públicos, decláralo como struct, no como class.
  • Nunca se inicializa una variable en su .h.
  • Se permite la definición de getters y/o setters en el .h, pero siempre precedido con su correspondiente inline
  • Siempre que sea posible utilizar lista de inicialización en las constructoras. De esta forma nos aseguramos que todas las variables están inicializadas antes de ejecutar cualquier otro código. Por ejemplo:
Personaje(Position pos_, Sprite& sprite_): pos(pos_), sprite(sprite_)
{
}
  • Se permite y se alenta a la utilización de los valores booleanos implícitos en el control de flujo de código, así como la aritmética booleana.
  • Los operadores ternarios son bien.
  • Se restringe el uso de using namespace a métodos concretos, prohibiendo el uso al principio de archivo para así evitar colisiones de nomenclatura

Para poder identificar de forma facil y sencilla la naturaleza de las variables y tipos se ha de utilizar el siguiente canon de codificación:

  • Ninguna variable empieza por un número.
  • Las variables privadas llevan ‘_’ (guión bajo) como prefijo.
  • Las clases siempre empiezan por MAYÚSCULA y las variables por minúscula.
  • Si vas a llamar de la misma forma a un parámetro que al parámetro que inicializa usa un guión bajo '_' como sufijo del parámetro . Ejemplo: Asumimos:
class Personaje{
    ...
    Position pos;
    ...
}

Entonces:

Personaje (Position pos_, ...): pos(pos_), ...
{
}
  • el sufijo _c en el nombre de la clase indica que es un componente. Ejemplo:RigidBody_c
  • Queda prohibido el uso de magic numbers. Se debe reemplazar cada constante por su respectivo #define o su definición como const (más c++ correct) que identifique lo que representa en código.
  • Siempre se debe usar indentación en cada bloque de código. Estandardizado a 4 espacios.
  • Cada #define deberá ser escrito en letras mayúsculas sin excepción. Si la definición consiste en más de una palabra, estas deberán separarse por guiones bajos ('_') POR_EJEMPLO_ASI.
  • Los nombres de las definiciones que previene la re-inclusión de archivos deberá ser escrita en mayúsculas y deberá de coincidir con el nombre asignado al archivo (.h) Para el archivo hotDriver.h
#ifndef _HOT_DRIVER_H_
#define _HOT_DRIVER_H
...
...
#endif //!_HOT_DRIVER_H_
  • Comenta los métodos indicando el valor de return y en el caso de tomar argumentos comentar cada uno. Por ejemplo.
/* 
*  \brief Funcion que mueve un objeto en una dirección
*  \return: devuelve true si se ha podido efectuar el movimento, false en caso contrario
*  \args:
*    - obj: referencia al objeto que se quiere mover
*    - dir: direccion en la que se debe mover el objeto
*/
bool moveTo(Object & obj, Direcction dir);

Estos comentarios deben ir en el .h nunca en el .cpp .

  • Las clases, en los .h deben mantener esta la siguiente forma
class Example: public ExampleFather
{
public:
//Lo primero constructoras en orden creciente de número de argumentos seguido por la destructora
    Example();
    Example(/*args*/);
    ~Example();
// A continuación API publica sobre operaciones q
    int move(int x, int y);
    bool update();
//Seguido por sobrecarga de operadores (si es necesario)
/////////////////////OPERATORS//////////////////////////////
   bool operator==(const Example& other);

////////////////////////////////////////////////////////////
//Por último en esta sección getters y setters con el formato
///////////GETTERS AND SETTERS//////////////////////////////
    //bool _active
    inline bool getActive() { return _active; };
    inline void setActive(bool value) { _active = value; };

    //Position _pos
    inline Position getPosition() {return _pos;};
    inline void setPosition(Position& pos) { _pos = pos;};
/////////////////////////////////////////////////////////////
//A continuación atributos públicos (aunque no suelen haber por el encapsulamiento)
public:
    Message* msg;
//Ahora los métodos privados
private:
    void CalculatePosition();
    bool blablabla();

//Seguido de los atributos privados
private:
    bool _active;
    Position _pos;
//En el caso de ser necesario por último irían los protected
protected:
    int id;
protected:
    int getId();
}

*Aunque se alenta al comentario del código, éste debe ser lo más estático posible. Es decir, se comenta la funcionalidad del código, pero no el cómo. Ya que las implementación de un método puede cambiar muchas veces los comentarios se suele quedar obsoletos y confundir más que ayudar, se prefiere el paradigma del self-explanatory code. Los comentarios se deben minimizar a las API, donde suelen tener un ciclo de vida mucho mayor (puede que cambies la implementación de un método 50 veces, pero seguirá haciendo la función que debe hacer, y casi seguro tomará los mismos argumentos y devolverá el mismo valor, por lo que su descripción no debería quedar obsoleta). Es decir: comentarios en .h -> bien; comentarios en .cpp -> mal.