Правила программирования на Си и Си++
ВведениеПроцесс проектирования
Сущность программирования: без сюрпризов, минимум сцепления и максимум согласованности
Решайте конкретную проблему, а не общий случай
Интерфейс пользователя не должен быть похожим на компьютерную программу (принцип прозрачности)
Не путайте легкость в изучении с легкостью в использовании
Производительность может измеряться числом нажатий клавиш
Если вы не можете сказать это по-английски, то вы не сможете выполнить это и на Си/Си++
Начинайте с комментариев
Читайте код
В цехе современных программистов нет места примадоннам
Разбивайте сложные проблемы на задачи меньшего размера
Используйте для работы соответствующий инструмент
Проблема должна быть хорошо продумана перед тем, как она сможет быть решена
Компьютерное программирование является индустрией обслуживания
Заказчик всегда прав
Малое — это прекрасно (большое == медленное)
Общие проблемы разработки программ
Прежде всего, не навреди
Нельзя измерять свою производительность числом строк
Вы не можете программировать в изоляции
Пустые потери времени
Пишите программу с учетом сопровождения — вы специалист по сопровождению
.1. Эффективность — часто просто пугало
Форматирование и документация
Программа без комментариев ничего не стоит
Располагайте программу и документацию вместе
Комментарии должны быть предложениями
Пропустите свой исходный тест через систему проверки орфографии
Комментарий не должен подтверждать очевидное
Комментарий должен предоставлять только нужную для сопровождения информацию
Комментарии должны быть выровнены вертикально
Используйте аккуратные столбцы везде, где можно
Не располагайте комментариев между именем функции и открывающей скобкой
Помечайте конец длинного составного оператора чем-нибудь, имеющим смысл
Располагайте в строке только один оператор
Указывайте имена аргументов в прототипах функций
Используйте "предикатную" форму при разбиении длинных выражений
Подпрограмма должна помещаться на экране
Нужно обеспечивать возможность распечатки всего текста программы
Используйте штриховую линию для зрительного разделения подпрограмм
Пробел — один из наиболее эффективных комментариев
Используйте отступы в четыре пробела
Условные операторы выделяются абзацными отступами
.1. Комментарии должны иметь тот же отступ, что и окружающий текст программы
Выравнивайте скобки вертикально по левой границе
Используйте скобки, если в условном операторе имеется более, чем одна строка
Имена и идентификаторы
Имена должны быть обычными
.1. Не используйте в качестве имен тарабарщину
Имена макросов должны записываться ЗАГЛАВНЫМИ_БУКВАМИ
.1. Не используйте заглавных букв для констант перечисления
.2. Не используйте заглавных букв в именах типов, созданных при помощи typedef
Не пользуйтесь именами из стандарта ANSI Cи
Не пользуйтесь именами Microsoft
Избегайте ненужных идентификаторов
Именованные константы для булевых величин редко необходимы
Правила обычного программирования
Не путайте привычность с читаемостью
Функция должна делать только одно дело
Иметь слишком много уровней абстракции или инкапсуляции так же плохо, как и слишком мало
Функция должна вызываться более одного раза, но…
.1. Код, используемый более одного раза, должен быть помещен в функцию
Функция должна иметь лишь одну точку выхода
.1. Всегда предусматривайте возврат значения из блока внешнего уровня
Избегайте дублирования усилий
Не захламляйте область глобальных имен
.1. Избегайте глобальных идентификаторов
.2. Никогда не требуйте инициализации глобальной переменной при вызове функции
.2.1. Делайте локальные переменные
.3. Используйте счетчик экземпляров объектов вместо инициализирующих функций
.4. Если оператор if завершается оператором return, то не используйте else
Помещайте более короткий блок условного оператора if/else первым
Старайтесь сдвинуть ошибки с этапа выполнения на этап компиляции
Применяйте указатели на функции Си в качестве селекторов
Избегайте циклов do/while
.1. Никогда не используйте do/while для бесконечного цикла
В цикле со счетчиком его значение должно по возможности уменьшаться
Не делайте одно и то же двумя способами одновременно
Используйте оператор for
То, чего нет в условном выражении, не должно появляться и в других частях оператора for
Допускайте, что ситуация может измениться в худшую сторону
Компьютеры не знают математики
.1. Рассчитывайте на невозможное
.2. Всегда проверяйте коды возврата ошибки
Избегайте явно временных переменных
Не нужно магических чисел
Не делайте предположений о размерах
Опасайтесь приведения типов (спорные вопросы Си)
Немедленно обрабатывайте особые случаи
Не старайтесь порадовать lint
Помещайте код, динамически распределяющий и освобождающий память, в одном и том же месте
Динамическая память — дорогое удовольствие
Тестовые подпрограммы не должны быть интерактивными
Сообщение об ошибке должно подсказывать пользователю, как ее исправить
Не выводите сообщения об ошибке, если она исправима
Не используйте системно-зависимых функций для сообщений об ошибках
Препроцессор
Все из одного .h файла должно быть использовано в по меньшей мере двух .c файлах
Используйте вложенные директивы #include
Вы должны быть всегда способны заменить макрос функцией
.1. Операция ?: не то же самое, что и оператор if/else
.2. Помещайте тело макроса и его аргументы в круглые скобки
Enum и const лучше, чем макрос
Аргумент параметризированного макроса не должен появляться в правой части более одного раза
.1. Никогда не используйте макросы для символьных констант
Если все альтернативы отпали, то используйте препроцессор
Правила, относящиеся к языку Си
.1. Устраняйте беспорядок
.2. Избегайте битовых масок; используйте битовые поля
.3. Не используйте флагов завершения
.4. Рассчитывайте, что ваш читатель знает Си
.5. Не делайте вид, что Си поддерживает булевый тип (#define TRUE)
Для битового поля размером 1 бит должен быть определен тип unsigned
Указатели должны указывать на адрес, больший, чем базовый для массива
Используйте указатели вместо индексов массива
Избегайте goto, за исключением…
Правила программирования на Си++
.1. Если проект не ориетирован на объекты, то используйте Си
Рассчитывайте потратить больше времени на проектирование и меньше на разработку
Библиотеки классов Си++ обычно не могут быть использованы неискушенными пользователями
Пользуйтесь контрольными таблицами
Сообщения должны выражать возможности, а не запрашивать информацию
Вам обычно не удастся переделать имеющуюся структурную программу в объектно-ориентированную
Наследование — это процесс добавления полей данных и методов-членов
Сначала проектируйте объекты
Затем проектируйте иерархию снизу вверх
.1. Базовые классы должны иметь более одного производного объекта
Си++ — это не Smalltalk: избегайте общего класса object
Инициализируйте виртуальные базовые классы при помощи конструктора, используемого по умолчанию
Используйте закрытые базовые классы лишь когда вы должны обеспечить виртуальные замещения
Проектируйте структуры данных в последнюю очередь
Никогда не допускайте открытого доступа к закрытым данным
Правила программирования на Си и Си++
Не пользуйтесь функциями типа get/set (чтения и присваивания значений)Откажитесь от выражений языка Си, когда программируете на Си++
Проектируйте с учетом наследования
Функция-член должна обычно использовать закрытые поля данных класса
Используйте константы
Используйте структуры только тогда, когда все данные открытые и нет функций-членов
Не размещайте тела функций в определениях классов
Избегайте перегрузки функций и аргументов, используемых по умолчанию
Избегайте дружественных классов
Наследование — это форма сцепления
Не портьте область глобальных имен: проблемы Си++
Никогда не используйте ссылки в качестве результатов, пользуйтесь указателями
Не возвращайте ссылки (или указатели) на локальные переменные
Не возвращайте ссылки на память, выделенную оператором new
Присваивание самому себе должно работать
Классы, имеющие члены-указатели
Исходите из того, что члены и базовые классы инициализируются в случайном порядке
Конструкторы копий должны использовать списки инициализации членов
Производные классы должны обычно определять конструктор копии и функцию operator=( )
Конструкторы, не предназначенные
Используйте счетчики экземпляров объектов для инициализации на уровне класса
Суперобложки на Си++ для существующих интерфейсов редко хорошо работают
Виртуальные функции — это те функции, которые вы не можете написать на уровне базового класса
Виртуальная функция не является виртуальной, если вызывается из конструктора или деструктора
Не вызывайте чисто виртуальные функции из конструкторов
Деструкторы всегда должны быть виртуальными
Функции базового класса
Не делайте функцию виртуальной
Защищенные функции обычно должны быть виртуальными
Опасайтесь приведения типов (спорные вопросы Си++)
Не вызывайте конструкторов из операции operator=( )
Операция — это сокращение (без сюрпризов)
Используйте перегрузку операций
Перегрузив одну операцию, вы должны перегрузить все сходные с ней операции
Перегруженные операции должны работать точно так же, как они работают в Си
Перегруженной бинарной операции
Если можно, то делайте все преобразования типов с помощью конструкторов
Используйте new/delete вместо malloc()/free()
Вся память, выделенная в конструкторе, должна быть освобождена в деструкторе
Локальные перегрузки операторов new и delete опасны
Используйте встроенные шаблоны функций вместо параметризированных макросов
Всегда знайте размер шаблона после его расширения
Шаблоны не заменяют наследование; они его автоматизируют
Назначение исключений — не быть пойманными
По возможности возбуждайте объекты типа error
Возбуждение исключений из конструктора ненадежно