Instrucciones de codificación
Estilo de codificación de CNTK
En esta página se documentan las convenciones usadas en el código fuente de CNTK. Siga estas convenciones al escribir código nuevo. Siga el sentido común y divida las funciones que superen un límite razonable (un par de páginas de pantalla), use nombres significativos, comentarios bien y mantenga los comentarios y el código sincronizados, etc.
Conceptos básicos: sangría, espaciado y llaves
El código se sangría de forma coherente mediante cuatro espacios. No se permiten caracteres de tabulación en ningún lugar del código. Las únicas excepciones son Archivos Make, otro sistema de compilación o archivos de datos en los que se requieren caracteres de tabulación sintácticamente.
Los siguientes bloques de código tienen sangría:
- Cuerpos de instrucciones de control: for, if, while, switch, etc.
- Bloques de instrucciones libres, es decir, llaves de apertura y cierre que no siguen ninguna instrucción de control. A veces se usan para limitar la duración de los objetos.
- Cuerpos de clases y funciones.
- Las instrucciones continuaron desde la línea anterior.
- El código en las instrucciones case se inicia en la línea que sigue a la instrucción case y se sangría.
Las siguientes cosas no tienen sangría:
- Contenido de los espacios de nombres.
- Etiquetas case
- Especificadores de control de acceso.
Las declaraciones de función con listas de parámetros largos pueden dividirse en varias líneas. La declaración de parámetros de las líneas divididas se debe aplicar sangría al paréntesis de apertura de la declaración de función. Las llamadas a funciones con listas de parámetros largos pueden dividirse en varias líneas, las líneas divididas se deben aplicar sangría al paréntesis de apertura de la instrucción de función asociada.
El código se escribe mediante llaves de estilo Allman o BSD Unix. Este estilo coloca la llave asociada a una instrucción de control en la siguiente línea, con sangría en el mismo nivel que la instrucción de control. Las instrucciones dentro de las llaves se aplican al siguiente nivel, se recomienda no omitir nunca llaves, incluso para bloques pequeños.
Los espacios están presentes en los siguientes lugares:
- Alrededor de todos los operadores binarios, incluidas las asignaciones
- Entre una palabra clave y paréntesis
- Entre un identificador o una palabra clave y una llave
- Después de comas y punto y coma que no terminan una línea
Los espacios están ausentes en los siguientes lugares:
- Antes de punto y coma y comas
- En el lado interno de paréntesis
- Entre un nombre de función y su lista de argumentos
- Entre operadores unarios y sus operandos
- Dentro de una lista de argumentos vacía
- Entre una etiqueta y dos puntos
- Alrededor del operador de ámbito ::
Las listas de inicializadores de miembros y las listas de clases base que contienen más de una clase deben escribirse en una línea independiente. Esto facilita la detección de errores.
namespace Microsoft { namespace MSR { namespace CNTK {
Matrix ImplodeSelf(int x);
int ConfuseUs(float y);
class MainPart:
public Head,
protected Heart
{
public:
MainPart():
m_weight(99),
m_height(180)
{}
private:
void EatMore();
int m_consume, m_repeater;
};
template <typename Box>
void Inspect(Box & container)
{
switch (container)
{
case 1:
PrepareIt();
break;
case 2:
Finish();
break;
default:
break;
}
for (int i = 0; i < 30; ++i)
{
container << EatMore();
}
return container;
}
} } }
Convenciones de nomenclatura
- Los nombres de clase y espacio de nombres usan UpperCamelCase también conocido como PascalCase.
- Los nombres comúnmente escritos en mayúsculas (SQL, CNTK, ...) pueden permanecer en todos los casos superiores.
- Las funciones estáticas globales y públicas, las variables de pila y los miembros de clase (variables de clase) usan lowerCamelCase.
- Las funciones miembro de clase (métodos) usan UpperCamelCase.
- Las macros y constantes usan UPPER_SNAKE_CASE.
- Los parámetros de plantilla que son tipos usan UpperCamelCase.
- No se permiten prefijos de tipo, notación húngara, etc. Use sufijos significativos si necesita desambiguar, por ejemplo, floatMatrix y normalizedDoubleMatrix.
Prefijos de nombre
m_
para variables miembros_
para variables estáticas en cualquier contextog_
para variables globales, que deben evitarse en primer lugar (tanto como sea posible)
Los nombres de variable deben ser nombres. Los nombres de función deben ser verbos, a excepción de los captadores, que pueden ser sustantivos. Por ejemplo, una propiedad de clase denominada position tendría el establecedor SetPosition() y el getter Position().
Convenciones de nombre de archivo
Los archivos de C++ deben tener la extensión .cpp, mientras que los archivos de encabezado deben tener la extensión .h. No se permiten espacios ni caracteres de subrayado. No se recomienda usar números en nombres de archivo.
#define GOOD_MACRO(x) x
void CallOut();
unsigned const g_theAnswer = 42;
class SolveAllProblems
{
public:
void DoWhatWeNeed();
static void SetBugsOff();
int m_countReasons;
protected:
void NeverWorking();
static void GetReason();
int internalCounter;
private:
void InternalNeeds();
static void ShowReason();
int m_countShows;
};
template <typename TypeParam, int numberOfReasons>
void CallGlobal(boost::array<TypeParam, numberOfReasons> const &array);
Preprocesador
Se desaconseja la compilación condicional mediante el preprocesador, ya que conduce a la pudrición del código. Úselo solo cuando sea inevitable, por ejemplo, cuando se usa una dependencia opcional. Un caso especial usa la compilación condicional para excluir un archivo completo basado en la plataforma, que se permite.
En preferencia para compilar condicionalmente, código específico de la plataforma, debe apuntar a escribir código portátil que funcione igual independientemente de la plataforma. El uso de las bibliotecas boost puede ayudar mucho en este sentido. Si debe usar código diferente en función de la plataforma, intente encapsularlo en funciones auxiliares, de modo que la cantidad de código que difiere entre las plataformas se mantenga como mínimo.