Веревка достаточной длины, чтобы выстрелить себе в ногу



Предыдущая | Следующая

Веревка достаточной длины, чтобы выстрелить себе в ногу
Правила программирования на С и С++
Ален И. Голуб
Посвящается Аманде
Анонс книги

Благодарности

Работа над этой книгой затянулась, и я весьма обязан трем редакторам издательства MCGraw-Hill, которые по очереди мирились с постоянными задержками с моей стороны: Нэйлу Ливайну, Дэну Гонно и Дженифер Холт-Диджованна. Я особенно признателен Бобу Дюшарму, который защитил меня от самого себя, сделав очень тщательный просмотр первоначального наброска. Его советы значительно улучшили книгу в ее нынешнем виде.

Введение
Глава 1. Процес проектирования
1. Сущность программирования: без сюрпризов, минимум сцепления и максимум согласованности
2. Подавляйте демонов сложности (Часть 1).
2.2. Решайте конкретную проблему, а не общий случай.
3. Интерфейс пользователя не должен быть похожим на компьютерную программу (принцип прозрачности).
4. Не путайте легкость в изучении с легкостью в использовании.
5. Производительность может измеряться числом нажатий клавиш.
6. Если вы не можете сказать это по-английски, то вы не сможете выполнить это на С/С++.
6.1. Начинайте с комментариев.
7. Читайте код.
7.1. В цехе современных программистов нет места примадоннам.
8. Разлагайте сложные проблемы на задачи меньшего размера.
9. Используйте весь язык.
9.1. Используйте для работы соответствующий инструмент.
10. Проблема должна быть хорошо продумана перед тем, как она сможет быть решена.
11. Компьютерное программирование является индустрией обслуживания.
13. Заказчик всегда прав.
14. Малое - это прекрасно. (Большое == медленное)

Глава 2. Общие проблемы разработки програм
15. Прежде всего, не навреди.
16. Редактируйте свою программу.
17. Программа должна быть переписана не менее двух раз.
18. Нельзя измерять свою производительность числом строк.
19. Вы не можете программировать в изоляции.
20. Пустые потери времени.
21. Пишите программу с учетом сопровождения - вы специалист по сопровождению.
21.1. Эффективность часто просто пугало.
Глава 3. Форматирование и документация
22. Программа без комментариев ничего не стоит.
23. Располагайте программу и документацию вместе.
24. Комментарии должны быть предложениями.
25. Пропустите свой исходный тест через систему проверки орфографии.
26. Комментарий не должен подтверждать очевидное.
27. Комментарий должен предоставлять только нужную для сопровождения информацию.
28. Комментарии должны быть в блоках.
29. Комментарии должны быть выровнены вертикально.
30. Используйте аккуратные столбцы везде, где можно.
31. Не располагайте комментариев между именем функции и открывающей скобкой.
32. Помечайте конец длинного составного оператора чем-нибудь, имеющим смысл.
33. Располагайте в строке только один оператор.
34. Указывайте имена аргументов в прототипах функций.
35. Используйте "предикатную" форму при разбиении длинных выражений.
36. Подпрограмма должна помещаться на экране.
37. Нужно обеспечивать возможность распечатки всего текста программы.
38. Используйте штриховую линию для зрительного разделения подпрограмм.
39. Пробел - один из наиболее эффективных комментариев.
40. Используйте отступы в четыре пробела.
41. Условные операторы выделяются абзацными отступами.
плять - до сюда переделывать все связанное с кодом
41.1. Комментарии должны иметь тот же отступ, что и окружающий текст программы.
42. Выравнивайте скобки вертикально по левой границе.
43. Используйте скобки, если в условном операторе имеется более, чем одна строка.
Глава 4. Имена и идентификаторы
44. Имена должны быть обычными словами английского языка, описывающими то, что делает функция, аргумент или переменная.
44.1. Не используйте в качестве имен тарабарщину.
45. Имена макросов должны записываться ЗАГЛАВНЫМИ_БУКВАМИ.
45.1. Не используйте заглавных букв для констант перечисления.
45.2. Не используйте заглавных букв в именах типов, созданных при помощи typedef.
46. Избегайте области имен стандарта ANSI C.
47. Избегайте области имен Microsoft.
48. Избегайте ненужных идентификаторов.
49. Именованные константы для булевых величин редко необходимы.
Глава 5. Правила обычного программирования
50. Не путайте привычность с читаемостью.
51. Функция должна делать только одно дело.
52. Иметь слишком много уровней абстракции или инкапсуляции так же плохо, как и слишком мало.
53. Функция должна вызываться более одного раза, но...
53.1. Код, используемый более одного раза, должен быть помещен в функцию.
54. Функция должна иметь лишь одну точку входа.
54.1. Всегда предусматривайте возврат значения из блока внешнего уровня.
55. Избегайте дублирования усилий.
56. Не портьте область глобальных имен.
56.1. Избегайте глобальных идентификаторов.
56.2. Никогда не требуйте инициализации глобальной переменной при вызове функции.
56.2.1. Делайте локальные переменные статическими в рекурсивных функциях, если их значения не участвуют в рекурсивном вызове.
56.3. Используйте счетчик экземпляров объектов вместо инициализирующих функций.
56.4. Если оператор if завершается оператором return, то не используйте else.
57. Помещайте более короткий блок условного оператора if/else первым.
58. Старайтесь сдвинуть ошибки с этапа выполнения на этап компиляции.
59. Применяйте указатели на функции С в качестве селекторов.
60. Избегайте циклов do/while.
60.1. Никогда не используйте do/while для бесконечного цикла.
61. В цикле со счетчиком его значение должно по возможности уменьшаться.
62. Не делайте одно и то же двумя способами одновременно.
63. Используйте оператор for, если имеются любые два из инициализурующего, условного или инкрементирующего выражений.
64. То, чего нет в условном выражении, не должно появляться и в других частях оператора for.
65. Допускайте, что ситуация может измениться в худшую сторону.
66. Компьютеры не знают математики.
66.1. Рассчитывайте на невозможное.
66.2. Всегда проверяйте код, вызывающий ошибку.
67. Избегайте явно временных переменных.
68. Не нужно магических чисел.
69. Не делайте предположений о размерах.
70. Опасайтесь приведения типов (спорные вопросы С).
71. Немедленно обрабатывайте особые случаи.
72. Не старайтесь порадовать lint.
72. Не старайтесь порадовать lint.
73. Помещайте код, динамически распределяющий и освобождающий память, в одном и том же месте.
74. Динамическая память - дорогое удовольствие.
75. Тестовые подпрограммы не должны быть интерактивными.
76. Сообщение об ошибке должно подсказывать пользователю, как ее исправить.
77. Не выводите сообщения об ошибке, если она исправима.
78. Не используйте системно-зависимых функций для сообщений об ошибках.
Глава 6. Препроцессор
79. Все из одного .h файла должно быть использовано в по меньшей мере двух .c файлах.
80. Используйте вложенные директивы #include.
81. Вы должны быть всегда способны заменить макрос функцией.
81.1. Операция ?: не то же самое, что и оператор if/else.
81.2. Помещайте тело макроса и его аргументы в круглые скобки.
82. enum и const лучше, чем макрос.
83. Аргумент параметризированного макроса не должен появляться в правой части более одного раза.
 83.1. Никогда не используйте макросы для символьных констант.
84. Если все альтернативы отпали, то используйте препроцессор.
Глава 7. Правила, относящиеся к языку С
85. Подавляйте демонов запутанности (Часть 2).
85.1. Устраняйте беспорядок.
85.2. Избегайте битовых масок; используйте битовые поля.
85.3. Не используйте флагов завершения.
85.4. Рассчитывайте, что ваш читатель знает С.
85.5. Не делайте вид, что С поддерживает булевый тип (#define TRUE).
86. Для битового поля размером 1 бит должен быть определен тип unsigned.
87. Указатели должны указывать на адрес, больший, чем базовый для массива.
88. Используйте указатели вместо индексов массива.
89. Избегайте goto, за исключением...
Глава 8. Правила программирования на С++
Глава 8.А(A). Вопросы проектирования и реализации
90. Не смешивайте объектно-ориентированное и "структурное" проектирование.
90.1. Если проект не ориетирован на объекты, то используйте С.
91. Рассчитывайте потратить больше времени на проектирование и меньше на разработку.
92. Библиотеки классов С++ обычно не могут быть использованы неискушенными пользователями.
93. Пользуйтесь контрольными таблицами.
94. Сообщения должны выражать возможности, а не запрашивать (предлагать ?) информацию.
95. Вам обычно не удастся переделать имеющуюся структурную программу в объектно-ориентированную.
96. Объект производного класса является объектом базового класса.
97. Наследование - это процесс добавления полей данных и методов-членов.
98. Сначала проектируйте объекты.
99. Затем проектируйте иерархию снизу вверх.
99.1. Базовые классы должны иметь более одного производного объекта.
100. Возможности, определенные в базовом классе, должны использоваться всеми производными классами.
101. С++ - это не Smalltalk: избегайте общего класса object.
102. Смешения не должны наследоваться от чего попало.
103. Смешения должны быть виртуальными базовыми классами.
104. Инициализируйте виртуальные базовые классы при помощи конструктора, используемого по умолчанию.
105. Наследование не подходит, если вы никогда не посылаете сообщения базового класса объекту производного класса.
106. Везде, где можно, предпочитайте включение наследованию.
107. Используйте закрытые базовые классы лишь когда вы должны обеспечить виртуальные замещения.
108. Проектируйте структуры данных в последнюю очередь.
109. Все данные в определении класса должны быть закрытыми.
110. Никогда не допускайте открытого доступа к закрытым данным.
110.1. Не пользуйтесь функциями типа get/set (чтения и присваивания значений).
111. Откажитесь от выражений языка С, когда программируете на С++.
112. Проектируйте с учетом наследования.
112.1. Функция-член должна обычно использовать закрытые поля данных класса.
113. Используйте константы.
114. Используйте структуры только тогда, когда все данные открытые и нет функций-членов.
115. Не размещайте тела функций в определениях классов.
116. Избегайте перегрузки функций и аргументов, используемых по умолчанию.
Глава 8.Б(B). Проблемы сцепления
117. Избегайте дружественных классов.
118. Наследование - это форма сцепления.
119. Не портьте область глобальных имен: проблемы С++.
Глава 8.В(C). Ссылки
120. Ссылочные аргументы всегда должны быть константами.
121. Никогда не используйте ссылки в качестве результатов, пользуйтесь указателями.
122. Не возвращайте ссылки (или указатели) на локальные переменные.
123. Не возвращайте ссылки на память, выделенную оператором new.
Глава 8.Г(D). Конструкторы, деструкторы и operator=( )
124. Операция operator=( ) должна возвращать ссылку на константу.
125. Присваивание самому себе должно работать.
126. Классы, имеющие члены-указатели, должны всегда определять конструктор копии и функцию operator=().
127. Если у вас есть доступ к объекту, то он должен быть инициализирован.
128. Используйте списки инициализации членов.
129. Исходите из того, что члены и базовые классы инициализируются в случайном порядке.
130. Конструкторы копий должны использовать списки инициализации членов.
131. Производные классы должны обычно определять конструктор копии и функцию operator=( ).
132. Конструкторы, не предназначенные для преобразования типов, должны иметь два или более аргумента.
133. Используйте счетчики экземпляров объектов для инициализации на уровне класса.
134. Избегайте инициализации в два приема.
135. Суперобложки на С++ для существующих интерфейсов редко хорошо работают.
Глава 8.Д(E). Виртуальные функции
136. Виртуальные функции - это те функции, которые вы не можете написать на уровне базового класса.
137. Виртуальная функция не является виртуальной, если вызывается из конструктора или деструктора.
138. Не вызывайте чисто виртуальные функции из конструкторов.
139. Деструкторы всегда должны быть виртуальными.
140. Функции базового класса, имеющие то же имя, что и функции производного класса, обычно должны быть виртуальными.
141. Не делайте функцию виртуальной, если вы не желаете, чтобы производный класс получил контроль над ней.
142. Защищенные функции обычно должны быть виртуальными.
143. Опасайтесь приведения типов (спорные вопросы С++).
144. Не вызывайте конструкторов из операции operator=( ).
Глава 8.Е(F). Перегрузка операций
145. Операция - это сокращение (без сюрпризов).
146. Используйте перегрузку операций только для определения операций, имеющих аналог в С (без сюрпризов).
147. Перегрузив одну операцию, вы должны перегрузить все сходные с ней операции.
148. Перегруженные операции должны работать точно так же, как они работают в С.
149. Перегруженной бинарной операции лучше всего быть встроенным (inline) псевдонимом операции приведения типа.
150. Не сходите с ума с операторами преобразования типов.
151. Если можно, то делайте все преобразования типов с конструкторами.
Глава 8.Ж(G). Управление памятью
152. Используйте new/delete вместо malloc()/free().
153. Вся память, выделенная в конструкторе, должна быть освобождена в деструкторе.
154. Локальные перегрузки операторов new и delete опасны.
Глава 8.З(H). Шаблоны
155. Используйте встроенные шаблоны функций вместо параметризированных макросов.
156. Всегда знайте размер шаблона после его расширения.
157. Шаблоны классов должны обычно определять производные классы.
158. Шаблоны не заменяют наследование; они его автоматизируют.
Глава 8.И(I). Исключения
159. Назначение исключений - не быть пойманными.
160. По возможности возбуждайте объекты типа error.
161. Возбуждение исключений из конструктора ненадежно.
Заключение
Об авторе