Главная - Литература

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 [246] 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

Листинг 31-49. Пример избавления от непредсказуемого побочного эффекта (С++)

++п;

PrintMessage( п, п + 2 );

Если вы все еще не совсем уверены в том, что побочные эффекты надо выносить в отдельные строки, попробуйте понять, что делает функция, приводимая в листинге 31-50:

Листинг 31-50. Пример слишком большого количества операции в строке (С)

strcpy( char * t, char * s ) { while ( *++t = *++s )

Некоторые опытные программисты не видят сложности в этом примере, потому что эта функция им знакома. Они смотрят на нее и говорят: «Это функция strcpyQ-Однако в нашем случае это не совсем strcpyQ- Она содержит ошибку. Если вы сказали «Это strcpyO>, увидев данный код, вы узнали код, а не прочитали его. В такую же ситуацию вы попадаете при отладке программы: код, на который вы не обратили внимания, потому что «узнали», а не прочли его, может содержать ошибку, поиск которой займет гораздо больше времени, чем она этого заслуживает.

Фрагмент, показанный в листинге 31-51, функционально идентичен первому варианту и гораздо удобней для чтения:

Листинг 31-51. Пример читаемого количества операций в каждой строке (С)

strcpy( char * t, char * s ) { do { ++t; ++s;

*t = *s;

while ( *t != \0 );

В этом переформатированном коде ошибка очевидна. Конечно, и 5 инкрементируются до того, как *5 будет скопирована в 7. Первый символ пропускается.

Второй пример выглядит продуманней первого, хотя операции, выполняемые во втором примере, идентичны первому. Причина такого впечатления в том, что во втором варианте не скрывается сложность выполняемых действий.

т ех ттп сшлха О т производительности также не оправдывает размеще-«ТЕад нескольких операций на одной строке. Поскольку обе

функции StrcpyO логически эквивалентны, можно ожидать, что компилятор сгенерирует для них идентичный код. Однако при профилировании обеих функций выяснилось, что для копирования 5 ООО ООО строк первой функции понадобилось 4,81 секунды, а второй -4,35.

В нашем случае «умная» версия показала снижение скорости на 11%, что делает ее гораздо менее умной. Результаты могут изменяться от компилятора к компиля-



тору, но в целом они свидетельствуют о том, что пока вы не измерили прирост производительности, следует сначала стремиться к ясности и корректности, а уж затем - к производительности.

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

Размещение объявлений данных

Располагайте каждое объявление данных в отдельной „

Перекрестная сшдкф Q доку-

строке Как показали предыдущие примеры, каждому мешрованйи объявлений дШ1-объявлению данных надо выделять отдельную строку. Тог- нш см- подраздел «Комменти-да проще дописывать комментарии к каждому объявлению роеанйе объшений данных» - ведь каждое расположено в отдельной строке. Проще ис- PWne $2.5. Об использовании правлять объявления, поскольку все они изолированы друг А""* от друга. Проще находить конкретные переменные, так как

можно просканировать одну колонку, а не читать каждую строчку. Проще искать и исправлять синтаксические ошибки - строка, указанная компилятором, содержит только одно объявление.

А ну-ка, скажите быстренько: какой тип имеет переменная currentBottom в объявлении данных, приведенном в листинге 31-52?

Листинг 31-52. Пример скопления нескольких объявлений переменных в одной строке (С++)

int rowlndex, columnldx; Color previousColor, currentColor, nextColor; Point previousTop, previousBottom, currentTop, currentBottom, nextTop, nextBottom; Font previousTypeface, currentTypeface, nextTypeface; Color choices[ NUM COLORS ];

Это, конечно, крайний случай, однако он не так уж далек от гораздо более распространенного стиля, показанного в листинге 31-53:

Листинг 31-53. Пример скопления нескольких объявлений переменных в одной строке (С++)

int rowlndex, columnldx;

Color previousColor, currentColor, nextColor;

Point previousTop, previousBottom, currentTop, currentBottom, nextTop, nextBottom; Font previousTypeface, currentTypeface, nextTypeface; Color choices[ NUM COLORS ];

Это не такой уж и редкий стиль объявления переменных, а конкретную переменную все так же тяжело найти, поскольку все объявления свалены в кучу. Тип переменной тоже тяжело выяснить. А теперь скажите, какой тип имеет nextColor в листинге 31-54?



Листинг 31-54. Пример читаемого кода, достигнутого благодаря размещению только одной переменной в каждой строке (С++)

int rowlndex;

int columnldx;

Color previousColor;

Color currentColor;

Color nextColor;

Point previousTop;

Point previousBotton;

Point currentTop;

Point currentBottom;

Point nextTop;

Point nextBottom;

Font previousTypeface;

Font currentTypeface;

Font nextTypeface;

Color choices[ NUM COLORS ];

Вероятно, переменную nextColor было проще найти, чем nextTypeface в листинге 31-53. Такой стиль характеризуется наличием в каждой строке одного полного объявления, включающего тип переменной.

Надо признать, что такой стиль съедает больше экранного пространства - 20 строк, а не 3, как в первом примере, хотя те три строки и выглядели довольно безобразно. Я не могу процитировать ни одного исследования, показывающего, что этот стиль приводит к меньшему количеству ошибок или к лучшему пониманию программы. Однако если Салли попросит меня посмотреть ее код, а объявления данных будут выглядеть, как в первом примере, я отвечу: «Ни за что - это читать невозможно». Если они будут выглядеть, как во втором примере, я скажу: «Гм... Может, попозже». А если они будут выглядеть, как в третьем примере, я скажу: «Конечно, с удовольствием!»

О&ьяатйте переменные рядом с местом их первого использования Еще

более предпочтительный вариант, чем объявление всех переменных в одном большом блоке, - это стиль, при котором переменная объявляется рядом с местом ее первого использования. Это уменьшает срок службы и время жизни переменной и позволяет проще выполнить рефакторинг кода на меньшие методы (см. подраздел «Делайте время жизни переменных как можно короче» раздела 10.4).

Разумно упорядочивайте объявления В листинге 31-54 объявления сгруппированы по типам. Такая группировка обычно имеет смысл, поскольку переменные одинаковых типов часто используются в аналогичных операциях. В других случаях можно упорядочивать их по алфавиту в соответствии с именами переменных. Хотя у алфавитной сортировки много сторонников, мне кажется, затрачиваемых не нее усилий она не стоит. Если ваш список переменных настолько длинен, что ему помогает алфавитное упорядочиение, ваш метод, вероятно, слишком велик. Разбейте его на части, чтобы создать меньшие по размеру методы с небольшим количеством переменных.

В С++ при объявлении указателей располагайте звездочку рядом с именем переменной или объявляйте типы-указатели Очень часто приходится ви-



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 [246] 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294



0.002