Dela via


Riktlinjer för kodning

CNTK kodningsformat

Den här sidan dokumenterar de konventioner som används i källkoden för CNTK. Följ dessa konventioner när du skriver ny kod. Följ sunt förnuft och dela upp funktioner som överskrider en rimlig gräns (ett par skärmsidor), använd meningsfulla namn, kommentera väl och håll kommentarer och kod synkroniserade osv.

Grunder: indrag, avstånd och klammerparenteser

Koden är konsekvent indragen med hjälp av fyra blanksteg. Tabbtecken tillåts inte någonstans i koden. De enda undantagen är Makefiles, andra byggsystem eller datafiler där tabbtecken krävs syntaktiskt.

Följande kodblock är indragna:

  • Organ av kontrollinstruktioner: för, om, medan, växla, etc.
  • Fri satsblock, dvs. inledande och avslutande klammerparenteser som inte följer någon kontrollsats. Dessa används ibland för att begränsa livslängden för objekt.
  • Organ av klasser och funktioner.
  • Instruktioner fortsatte från föregående rad.
  • Kod i skiftlägesinstruktioner startar på raden efter ärendeinstruktionen och är indraget.

Följande saker är inte indragna:

  • Innehållet i namnområden.
  • Ärendeetiketter
  • Åtkomstkontrollsspecificerare.

Funktionsdeklarationer med långa parameterlistor kan delas upp över flera rader. Parameterdeklarationen på de delade raderna ska vara indraget till funktionsdeklarationens inledande parentes. Anrop till funktioner med långa parameterlistor kan delas upp över flera rader. De delade raderna bör dras in i den inledande parentesen för den associerade funktionssatsen.

Kod skrivs med allman- eller BSD Unix-klammerparenteser. Det här formatet placerar klammerparentesen som är associerad med en kontrollsats på nästa rad, indragen på samma nivå som kontrollsatsen. Instruktioner inom klammerparenteserna är indragna till nästa nivå. Vi rekommenderar att du aldrig utelämnar klammerparenteser, även för små block.

Blanksteg finns på följande platser:

  • Runt alla binära operatorer, inklusive tilldelningar
  • Mellan ett nyckelord och parenteser
  • Mellan en identifierare eller ett nyckelord och en klammerparentes
  • Efter kommatecken och semikolon som inte avslutar en linje

Blanksteg saknas på följande platser:

  • Före semikolon och kommatecken
  • På den inre sidan av parenteser
  • Mellan ett funktionsnamn och dess argumentlista
  • Mellan unary operatörer och deras operander
  • I en tom argumentlista
  • Mellan en etikett och ett kolon
  • Runt omfångsoperatorn ::

Medlemsinitieringslistor och basklasslistor som innehåller mer än en klass bör skrivas på en separat rad. Detta gör det mycket enkelt att upptäcka fel.

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

} } }

Namngivningskonventioner

  • Klass- och namnområdesnamn använder UpperCamelCase aka PascalCase.
  • Namn som ofta stavas i versaler (SQL, CNTK, ...) kan stanna i alla versaler.
  • Globala och offentliga statiska funktioner, stackvariabler och klassmedlemmar (klassvariabler) använder lowerCamelCase.
  • Klassmedlemsfunktioner (metoder) använder UpperCamelCase.
  • Makron och konstanter använder UPPER_SNAKE_CASE.
  • Mallparametrar som är typer använder UpperCamelCase.
  • Typprefix, ungersk notation osv. tillåts inte. Använd meningsfulla suffix om du behöver tvetydigt, t.ex. floatMatrix och normalizedDoubleMatrix.

Namnprefix

  • m_ för medlemsvariabler
  • s_ för statiska variabler i alla sammanhang
  • g_ för globala variabler, som bör undvikas i första hand (så mycket som möjligt)

Variabelnamn bör vara substantiv. Funktionsnamn bör vara verb, med undantag för getters, som kan vara substantiv. Till exempel skulle en klassegenskap med namnet position ha setter SetPosition() och getter Position().

Filnamnskonventioner

C++-filer ska ha .cpp-tillägget, medan huvudfiler ska ha .h-tillägget. Blanksteg och understreck tillåts inte. Det rekommenderas inte att använda tal i filnamn.

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

Preprocessor

Villkorsstyrd kompilering med hjälp av preprocessorn rekommenderas inte eftersom det leder till kodrot. Använd den bara när det är oundvikligt, till exempel när ett valfritt beroende används. Ett specialfall är att använda villkorsstyrd kompilering för att exkludera en hel fil baserat på plattformen, vilket är tillåtet.

I stället för villkorsstyrd kompilerad, plattformsspecifik kod bör du sträva efter att skriva portabel kod som fungerar på samma sätt oavsett plattform. Att använda Boost-biblioteken kan vara till stor hjälp i det här avseendet. Om du måste använda olika kod beroende på plattformen kan du försöka kapsla in den i hjälpfunktioner, så att mängden kod som skiljer sig åt mellan plattformar hålls till ett minimum.