Поделиться через


Рекомендации по кодированию

стиль программирования CNTK

На этой странице описаны соглашения, используемые в исходном коде CNTK. Соблюдайте эти соглашения при написании нового кода. Следите за здравым смыслом и разбивайте функции, превышающие разумное ограничение (несколько страниц экрана), используйте значимые имена, хорошо закомментируйте и сохраните комментарии и код в синхронизации и т. д.

Основы: отступы, интервалы и фигурные скобки

Код постоянно отступен с использованием четырех пробелов. Символы табуляции не допускаются нигде в коде. Единственными исключениями являются Makefiles, другая система сборки или файлы данных, в которых символы табуляции являются синтаксически обязательными.

Следующие блоки кода отступы:

  • Тела операторов управления: for, if, while, switch и т. д.
  • Свободные блоки операторов, т. е. открывающие и закрывающие фигурные скобки, которые не следуют ни одному оператору управления. Иногда они используются для ограничения времени существования объектов.
  • Тела классов и функций.
  • Заявления продолжались с предыдущей строки.
  • Код в случае, если операторы начинаются в строке после оператора case и отступ.

Следующие элементы не отступы:

  • Содержимое пространств имен.
  • Метки case
  • Описатели управления доступом.

Объявления функций с длинными списками параметров могут быть разделены на несколько строк. Объявление параметра в разделенных строках должно быть отступом до открывающей скобки объявления функции. Вызовы функций с длинными списками параметров могут быть разделены по нескольким строкам, разделенные линии должны быть отступами до открывающей скобки связанной инструкции функции.

Код написан с помощью фигурных скобок стиля Allman или BSD Unix. Этот стиль помещает фигурную скобку, связанную с оператором элемента управления, в следующей строке с отступом на тот же уровень, что и оператор элемента управления. Операторы в фигурных скобках имеют отступ на следующий уровень, рекомендуется никогда не опускать фигурные скобки, даже для небольших блоков.

Пробелы присутствуют в следующих местах:

  • Вокруг всех двоичных операторов, включая назначения
  • Между ключевым словом и скобками
  • Между идентификатором или ключевым словом и фигурной скобкой
  • После запятых и с запятой, которые не заканчиваются линией

Пробелы отсутствуют в следующих местах:

  • Перед точками с запятой и запятыми
  • На внутренней стороне круглых скобок
  • Между именем функции и его списком аргументов
  • Между унарными операторами и их операндами
  • Внутри пустого списка аргументов
  • Между меткой и двоеточием
  • Вокруг оператора области ::

Списки инициализаторов элементов и списки базовых классов, содержащие несколько классов, должны быть записаны в отдельной строке. Это упрощает поиск ошибок.

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

} } }

Соглашения об именовании.

  • Имена классов и пространств имен используют UpperCamelCase и PascalCase.
  • Имена, часто написанные во всех верхних регистрах (SQL, CNTK, ...) могут оставаться во всех верхних регистрах.
  • Глобальные и открытые статические функции, переменные стека и члены класса (переменные класса) используют lowerCamelCase.
  • Функции-члены класса (методы) используют UpperCamelCase.
  • Макросы и константы используют UPPER_SNAKE_CASE.
  • Параметры шаблона, которые являются типами, используют UpperCamelCase.
  • Префиксы типов, венгерская нотация и т. д. запрещены. Используйте значимые суффиксы, если требуется диамбигуат, например floatMatrix и normalizedDoubleMatrix.

Префиксы имен

  • m_ для переменных-членов
  • s_ для статических переменных в любом контексте
  • g_ для глобальных переменных, которые следует избегать в первую очередь (как можно больше)

Имена переменных должны быть существительными. Имена функций должны быть глаголами, за исключением методов получения, которые могут быть существительными. Например, свойство класса с именем position будет иметь метод задания SetPosition() и getter Position().

Соглашения об именах файлов

Файлы C++ должны иметь расширение CPP, а файлы заголовков должны иметь расширение H. Запрещено использовать пробелы и знаки подчеркивания. Использование чисел в именах файлов не рекомендуется.

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

Препроцессор

Условная компиляция с помощью препроцессора настоятельно не рекомендуется, так как она приводит к сгниту кода. Используйте его только в том случае, если он неизбежен, например, если используется необязательная зависимость. Особый случай — использование условной компиляции для исключения всего файла на основе платформы, которая разрешена.

При выборе условно скомпилированного кода для конкретной платформы следует стремиться написать переносимый код, который работает одинаково независимо от платформы. Использование библиотек Boost может помочь в этом отношении. Если необходимо использовать другой код в зависимости от платформы, попробуйте инкапсулировать его в вспомогательных функциях, чтобы объем кода, отличающийся между платформами, сохранялся до минимума.