Partager via


Directives de codage

style de codage CNTK

Cette page documente les conventions utilisées dans le code source de CNTK. Respectez ces conventions lors de l’écriture de nouveau code. Suivez les fonctions de bon sens et de rupture dépassant une limite raisonnable (quelques pages d’écran), utilisez des noms explicites, commentez bien et conservez les commentaires et le code synchronisés, etc.

Notions de base : retrait, espacement et accolades

Le code est constamment mis en retrait à l’aide de quatre espaces. Les caractères de tabulation ne sont pas autorisés n’importe où dans le code. Les seules exceptions sont Makefiles, d’autres systèmes de génération ou fichiers de données dans lesquels les caractères de tabulation sont obligatoires de manière syntaxique.

Les blocs de code suivants sont mis en retrait :

  • Corps des instructions de contrôle : pour, si, while, switch, etc.
  • Blocs d’instructions libres, c’est-à-dire les accolades ouvrantes et fermante qui ne suivent aucune instruction de contrôle. Celles-ci sont parfois utilisées pour limiter la durée de vie des objets.
  • Corps de classes et de fonctions.
  • Les instructions se sont poursuivies à partir de la ligne précédente.
  • Le code dans les instructions case démarre sur la ligne qui suit l’instruction case et est mis en retrait.

Les éléments suivants ne sont pas mis en retrait :

  • Contenu des espaces de noms.
  • Étiquettes case
  • Spécificateurs de contrôle d’accès.

Les déclarations de fonction avec des listes de paramètres longues peuvent être fractionnées sur plusieurs lignes. La déclaration de paramètre sur les lignes de fractionnement doit être mise en retrait vers la parenthèse ouvrante de la déclaration de fonction. Les appels aux fonctions avec des listes de paramètres longs peuvent être fractionnés sur plusieurs lignes, les lignes de fractionnement doivent être mises en retrait vers la parenthèse ouvrante de l’instruction de fonction associée.

Le code est écrit à l’aide d’accolades de style Allman ou BSD Unix. Ce style place l’accolade associée à une instruction de contrôle sur la ligne suivante, mise en retrait au même niveau que l’instruction de contrôle. Les instructions au sein des accolades sont mises en retrait au niveau suivant, il est recommandé de ne jamais omettre les accolades, même pour les petits blocs.

Les espaces sont présents dans les endroits suivants :

  • Autour de tous les opérateurs binaires, y compris les affectations
  • Entre un mot clé et des parenthèses
  • Entre un identificateur ou un mot clé et une accolade
  • Après des virgules et des points-virgules qui ne terminent pas une ligne

Les espaces sont absents dans les endroits suivants :

  • Avant les points-virgules et les virgules
  • Sur le côté intérieur des parenthèses
  • Entre un nom de fonction et sa liste d’arguments
  • Entre les opérateurs unaires et leurs opérandes
  • À l’intérieur d’une liste d’arguments vide
  • Entre une étiquette et un signe deux-points
  • Autour de l’opérateur d’étendue ::

Les listes d’initialiseurs de membres et les listes de classes de base qui contiennent plusieurs classes doivent être écrites sur une ligne distincte. Cela facilite la détection d’erreurs.

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;
}

} } }

Conventions d’affectation de noms

  • Les noms de classes et d’espaces de noms utilisent UpperCamelCase aka PascalCase.
  • Les noms couramment orthographiés en majuscules (SQL, CNTK, ...) peuvent rester dans tous les majuscules.
  • Les fonctions statiques globales et publiques, les variables de pile et les membres de classe (variables de classe) utilisent lowerCamelCase.
  • Les fonctions membres de classe (méthodes) utilisent UpperCamelCase.
  • Les macros et constantes utilisent UPPER_SNAKE_CASE.
  • Les paramètres de modèle qui sont des types utilisent UpperCamelCase.
  • Les préfixes de type, la notation hongroise, etc. ne sont pas autorisés. Utilisez des suffixes significatifs si vous devez lever l’ambiguïté, par exemple floatMatrix et normalizedDoubleMatrix.

Préfixes de nom

  • m_ pour les variables de membre
  • s_ pour les variables statiques dans n’importe quel contexte
  • g_ pour les variables globales, qui doivent être évitées au premier endroit (autant que possible)

Les noms de variables doivent être des noms. Les noms de fonction doivent être des verbes, à l’exception des getters, qui peuvent être des noms. Par exemple, une propriété de classe appelée position aurait le setter SetPosition() et le getter Position().

Conventions de nom de fichier

Les fichiers C++ doivent avoir l’extension .cpp, tandis que les fichiers d’en-tête doivent avoir l’extension .h. Les espaces et les traits de soulignement ne sont pas autorisés. L’utilisation de nombres dans les noms de fichiers est déconseillée.

#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);

Préprocesseur

La compilation conditionnelle utilisant le préprocesseur est fortement déconseillée, car elle entraîne une rotation du code. Utilisez-le uniquement lorsqu’il est inévitable, par exemple lorsqu’une dépendance facultative est utilisée. Un cas spécial utilise la compilation conditionnelle pour exclure un fichier entier en fonction de la plateforme, qui est autorisée.

Au lieu de compiler de manière conditionnelle du code spécifique à la plateforme, vous devez vous efforcer d’écrire du code portable qui fonctionne de la même façon, quelle que soit la plateforme. L’utilisation des bibliothèques Boost peut vous aider beaucoup à cet égard. Si vous devez utiliser un code différent en fonction de la plateforme, essayez de l’encapsuler dans les fonctions d’assistance afin que la quantité de code qui diffère entre les plateformes soit conservée au minimum.