Transcript Document

Лекции по курсу
«Метрология и качество программного
обеспечения»
Лекция 7. Стандарты и хорошие
практики кодирования на языках
высокого уровня
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Стандарты кодирования и их
назначение
Применение общих и корпоративных стандартов кодирования
позволяет:
1. Избегать характерных ошибок;
2. Улучшить читабельность программ;
3. Улучшить переносимость программ;
4. Упростить сопровождение программных продуктов.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Стандарты кодирования и их
назначение
Некоторые известные открытые стандарты кодирования на С/С++
1. ISO C Standard, WG14/N869. Committee Draft — January 18, 1999.
2. The C Programming Language, Second Edition, B.W. Kernighan and
D. M. Ritchie, Prentice Hall, 1988.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Все описанные ниже правила разделены на три категории:
1. Запреты – описывают положения, которые нельзя нарушать ни
при каких условиях;
2. Требования – описывают то, что должно соблюдаться всегда и в
любом проекте. При этом лидер проекта может принять
решение, что отдельные требования могут не соблюдаться.
3. Рекомендации – описывают то, что может существенно
облегчить жизнь разработчикам. Пренебрежение ими может
осложнить сопровождение программ и взаимодействие между
разработчиками.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Запрет:
Запрещается использовать макросы для переименования
операторов и ключевых слов С/С++.
Пример запрещённой конструкции:
#define closed protected
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
При программировании на С/С++ рекомендуется избегать
использования макросов для обозначения констант – лучше для
этой цели использовать типизированные константы (константные
переменные)
Например, вместо конструкции
#define my_const 0
лучше использовать
int my_const = 0;
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Для символов, которые участвуют в выражениях #ifdef, #ifndef
или #if defined не должно быть определено подставляемое
значение.
Пример неправильного использования:
#define DEBUG 0
#ifdef
DEBUG
#endif
Пример правильного использования:
#define
DEBUG
#ifdef
#endif
DEBUG
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Препроцессорные константы, используемые для разрешения или
запрета компиляции группы операторов, должны использоваться
в директивах условной компиляции, а не в операторах
управления последовательностью действий.
Пример неправильного использования:
#define
DEBUG 1
for (i = 0; (i < 5) && DEBUG; i++)
{
printf("i = %d\n", i);
}
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование (продолжение):
Пример правильного использования:
#define
DEBUG
#ifdef
DEBUG
for (i = 0; i < 5; i++)
{
printf("i = %d\n", i);
}
#endif
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Перечислимые типы данных (enum) должны использоваться
вместо препроцессорных констант там, где это возможно. Если
числовые значения констант важны, их следует указывать при
определении перечислимого типа.
Пример неправильного использования:
#define RED
1
#define GREEN
2
#define BLUE
3
int light = RED;
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование (продолжение):
Пример правильного использования:
enum Color
{
RED = 1,
GREEN = 2,
BLUE = 3
};
Color light = RED;
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Запрещается использовать в исходных текстах числовые
константы. Тем более запрещается использовать числовые
константы, если они должны встречаться в различных частях
программы.
Пример неправильного использования:
y = 3.14 * r * r;
for (i=0; i<10; i++)
{
…….
}
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование (продолжение):
Пример правильного использования:
int n = 10;
double Pi = 3.14;
y = Pi * r * r;
for (i=0; i<n; i++)
{
…….
}
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Необходимо инициализировать локальные переменные
перед их использованием. Инициализировать переменные
можно при их
объявлении.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Все глобальные переменные и константы должны быть
определены в одном месте. Если все же вам пришлось
использовать глобальные переменные или константы (чего
следует избегать), создайте два файла – globals.h и globals.cpp
(имена могут быть другими). В первом файле вы объявите все
глобальные переменные и константы (указав спецификатор
extern), во втором файле вы определите их начальные значения.
Вместе с тем, программа, в которой используется большое число
глобальных переменных или которая разрабатывается
несколькими разработчиками, может содержать их объявления в
разных файлах, распределив их по назначению.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Для обеспечения переносимости установку всех битов
переменной в 1 рекомендуется выполнять с использованием ~0.
Дело в том, что обычно установку всех битов в переменной
производят присваиванием значения 0xFF или 0xFFFF в
зависимости от размера переменной. Однако, некоторые типы
меняют размер при переходе к другой аппаратной платформе.
Например, тип int имеет размер 8, 16, 32 или 64 бита, в
зависимости от разрядности процессора. Оператор ~ (побитовое
«не») инвертирует все биты значения 0 и, таким образом,
устанавливает все биты в 1, независимо от размера переменной.
Присваивание переменной значения ~0 является наиболее
красивым и переносимым методом установки всех битов.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Рекомендуется давать файлам имена, сходные с именами
функций или классов C++, объявленных или определенных в
этих файлах. Например, класс CBasicClass может быть объявлен
и определен в файлах basic_class.h и basic_class.cpp.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Идентификаторы, определенные разработчиком, не должны
конфликтовать с системными идентификаторами.
Например, разработчик не должен определять функцию или
макрос с именем printf() в глобальном пространстве имен, даже
если системная библиотека с этой функцией не подключена.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Запрет:
Запрещается создавать глобальные идентификаторы, которые
начинаются с подчерка или содержат ‘__’ (два подчерка).
Эти идентификаторы зарезервированы стандартами C и C++ для
разработчиков компиляторов.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Разные идентификаторы должны отличаться более, чем только
размером (регистром) букв.
Другими словами, в пределах описания одного класса, одной
функции или метода все идентификаторы должны различаться
не только регистром букв, но и еще чем-либо. В различных
функциях и методах локальные переменные могут различаться
только регистром букв.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Все имена макросов должны быть в верхнем регистре.
Поскольку макросы отличаются от других элементов языка
способом обработки компилятором, удобно сделать их
выделяющимися на фоне программы. Смысл этого правила будет
потерян, если другие идентификаторы будут тоже в верхнем
регистре или имена макросов по внешнему виду не будут
отличаться от названий классов или переменных.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Рекомендуется использовать только маленькие буквы в именах
переменных, аргументов и членов-данных различных типов
данных.
Для того чтобы сложные имена не были слитными и не
выглядели неразборчивыми, можно использовать символ
«подчерк».
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Все константы перечислимых типов (enum) должны быть в
верхнем регистре.
Например:
enum Color
{
RED = 1,
GREEN = 2,
BLUE = 3
};
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Рекомендуется, чтобы все имена классов начинались с большой
буквы, все слова в имени класса были написаны слитно, и
каждое слово начиналось с большой буквы.
Например:
class CIntegerEdit;
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Для всех функций и методов должны быть указаны типы
возвращаемых значений. При программировании на C, функции,
возвращающие указатели, должны возвращать NULL в случае
сбоя.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Во всех функциях и методах рекомендуется делать не более
одного оператора return.
Подобный
подход
упрощает
отладку
программы
и
ее
сопровождение. В ряде случаев можно не использовать
множество точек возврата даже в случае большого числа
проверок, когда вложенные операторы ветвления ухудшают
читабельность программы. Вместо многочисленных возвратов
можно использовать переменную, хранящую статус ошибки.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
В объявлении функции или метода обязательно должны
присутствовать имена аргументов.
Хотя имена формальных параметров необязательны в объявлениях
функций и методов, они могут помочь при определении
назначения аргументов. Например, намного легче использовать
функцию, которая объявлена как
int DrawRect(int iLeft, int iTop, int iRight, int iBottom);
а не
int DrawRect(int, int, int, int);
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Оператор присваивания должен обрабатывать присваивание
самому себе.
Когда вы определяете некоторый оператор присваивания, не
забывайте, что пользователь может присвоить объект самому
себе, например:
х = х;
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Все объявления функций должны начинаться с первой позиции в
строке. Все макроопределения (#define) должны начинаться с
первой позиции в строке.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Рекомендуется все парные фигурные скобки расставлять одним
из двух указанных способов.
<<statement>>
- друг под другом
{
…
}
<<statement>> {
…
}
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
- с наложением
Правила и рекомендации по
кодированию на С/С++
Требование:
Объявления переменных должны начинаться с той же позиции в
строке, что и код в текущем блоке.
Пример:
int main(void)
{
int sample_size;
float result;
printf("Result %d is %f\n", sample_size, result);
…..
}
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Рекомендуется объявлять переменные некоторого типа и
указатели на объекты этого типа в разных строках.
Нерекомендуемый способ:
int i, j, *amount;
Рекомендуемый способ:
int i, j;
int *amount;
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Запрет:
Запрещается размещать более одного оператора или
выражения на одной строке.
Пример запрещённого использования:
x++; y = x + z;
if (x >= y) { z = 0;}
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Запрет:
При написании комментариев запрещается использовать какойлибо язык, отличный от английского.
Не все компьютеры, где будут просматривать ваши исходные
тексты, могут иметь установленную поддержку вашего любимого
языка.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Если "case" в операторе "switch" не заканчивается оператором
"break", то необходимо разместить соответствующий
комментарий, подчеркивающий, что это было сделано
умышленно.
Исключение может быть сделано только в том случае, когда между
двумя секциями "case" нет кода.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Требование:
Для исключения блоков кода из процесса компиляции нужно
использовать директивы условной компиляции или построчные
комментарии C++ (//), а не комментирование блока /* .. */.
Комментировать многострочные блоки кода опасно посредством /* ..
*/, так как в них могут оказаться такие же комментарии /* .. */, а
вложенные комментарии не поддерживаются языком. Для
временного удаления кода следует использовать директивы
условной компиляции или комментарии C++ (//), или
комментарии /* .. */ в построчном режиме.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Операторы ветвлений и циклов, тело которых содержит более 5
строк, рекомендуется помечать в конце комментарием,
следующим за закрывающей фигурной скобкой.
Пример:
while (count > 0)
{
…
…
} // END_OF while (count > 0)
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Запрет:
Запрещается проверять логические переменные и результаты
логических выражений на равенство с TRUE.
В C и C++ истинным считается любое ненулевое значение.
Следовательно, сравнивать нужно с нулем, а не с единицей.
Однако вместо нуля нужно брать значение FALSE.
Пример запрещённого использования
if (is_valid_freq(cur_freq) == TRUE);
Пример разрешённого использования
if (is_valid_freq(cur_freq) != FALSE);
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Не рекомендуется использовать оператор goto.
В очень немногих случаях оператор goto может использоваться для
выхода при обработке сложных ошибок.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
кодированию на С/С++
Рекомендация:
Рекомендуется при проверке условий ставить константу на
первое место.
Это может предотвратить ошибочное употребление оператора «=»
вместо «==»
Пример рекомендуемого использования
if (0 == j)
{
…
};
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
оформлению заголовков файлов и
функций
Заголовок функции должен содержать следующую информацию
1. Имя функции;
2. Краткое описание функции;
3. Список параметров с описанием;
4. Описание возвращаемого значения;
5. Условия, необходимые для корректного вызова;
6. Условия, необходимые для корректного завершения;
7. Прочие существенные замечания.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
оформлению заголовков файлов и
функций
Примерный перечень вопросов чек-листа для контроля корректности
оформления кода
1. Type definitions use typedef, not #define.
2. All lossy type conversions use explicit casts.
3. Explicit type conversions (casts) are not used (only for C++).
4. Named constants is used instead of hard coded (“magic”) values
and the names is defined to aid readability and make usage clear.
5. Variables is declared one per line, and each declaration includes
the type of the variable.
6. All variables initialize before they are used.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
оформлению заголовков файлов и
функций
Примерный перечень вопросов чек-листа для контроля корректности
оформления кода (продолжение)
7. Each local variable has a comment describing its usage and
purpose unless the name of the variable provides all the information.
8. A macro that produces executable code is written as a
parameterized macro, even if no parameters are needed.
9. Each reference to a parameter of a function-like macro is
surrounded by parentheses.
10. Inline functions are preferred to function-like macro (only for
C++).
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
оформлению заголовков файлов и
функций
Примерный перечень вопросов чек-листа для контроля корректности
оформления кода (продолжение)
11. The Revision History (version, data, trigger CR, author and
comments of changes) and copyright information is updated.
12. All comments are written in English.
13. The brace placement, indentation, spacing, naming convention
and line length satisfy the coding standard.
14. The ASCII TAB character is not used.
15. C++ style comment delimiters (“//”) is not used (only for C).
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
оформлению заголовков файлов и
функций
Примерный перечень вопросов чек-листа для контроля корректности
оформления кода (продолжение)
16. Each line of code contains no more than one statement.
17. A null statement as the body of a loop appears on a separate line
and includes a comment to make the intent clear.
18. If a case statement with code within a switch statement does not
contain a normal break, a comment is used to highlight this and to
indicate the intent of the code.
19. Array elements are accessed using normal array subscripting
(i.e., using brackets) rather than the dereference operator *.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
оформлению заголовков файлов и
функций
Примерный перечень вопросов чек-листа для контроля корректности
оформления кода (продолжение)
20. Memory pointers are explicit set in NULL after call free function.
21. If a class uses new and delete to do memory management, it
defines a copy constructor and assignment operator.
22. A class assignment operator takes care to check if its operand
refers to the ‘this’ object and handle the situation appropriately.
23. Member functions are not defined inside the class definition.
24. Pointers to objects of a derived class are not converted to
pointers to objects of a virtual base class.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС
Правила и рекомендации по
оформлению заголовков файлов и
функций
Примерный перечень вопросов чек-листа для контроля корректности
оформления кода (продолжение)
25. The malloc, realloc, or free functions are not used (Instead use
new and delete).
26. Empty brackets ("[ ]") are provided for delete when deallocating
arrays.
© В.М. Гриняк, доц. каф. ИСКТ ВГУЭС