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

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

Пример пересечения индексов (С++)

/ сначала используется здесь...

►for ( i = 0; i < numPayCodes; i++ ) { много кода

for ( j = 0; j < 12; j++ ) { много кода

- ...a теперь здесь

-> for ( i = 0; i < numDivisions; i++ ) {

sum = sum + transaction[ j ][ i ][ к ];

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

Ограничивайте видимость переменных-индексов цикла самим циклом Пересечение индексов цикла и другое применение индексов вне самих циклов - настолько важная проблема, что разработчики языка Ada решили сделать индексы цикла for недоступными вне цикла. Попытка использования переменной-индекса вне цикла for приводит к ошибке времени компиляции.

С++ и Java в какой-то мере реализуют ту же идею - они позволяют объявлять индексы цикла в нем самом, но не требуют этого. Выше, в примере раздела «Избегайте писать код, зависящий от последнего значения индекса цикла», переменная recordCount может быть объявлена внутри выражения /ог, что ограничит ее область видимости этим циклом:

Пример объявления переменной-индекса цикла внутри цикла for (С++)

for ( int recordCount = 0; recordCount < MAX RECORDS; recordCount++ ) { Циклический код, использующий recordCount.

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

Пример объявления переменных-индексов внутри циклов tor и их (возможно!) безопасное повторное использование (С++)

for ( int recordCount = 0; recqrdCount < MAX RECORDS; recordCount++ ) { Циклический код, использующий recordCount.



Промежуточный код.

for ( int recordCount = 0; recordCount < MAX RECORDS; recordCount++ ) {

Дополнительный циклический код, использующий другую переменную recordCount.

Такая методика полезна для документирования назначения переменной recordCount. Однако не полагайтесь на ваш компилятор в вопросе области видимости record-Count. В разделе 6.3-3.1 книги «The С++ Programming Language» (Stroustrup, 1997) говорится, что переменная recordCount должна иметь область видимости, ограниченную ее циклом. Но, проверив эту функциональность в трех разных компиляторах С++, я получил три разных результата:

первый компилятор сигнализировал о повторном объявлении переменной recordCount во втором цикле for и сгенерировал ошибку;

второй компилятор допустил объявление переменной recordCount во втором цикле /ог, но разрешил ее использование вне первого цикла /ог;

третий компилятор разрешил оба объявления переменных recordCount и не допустил использования ни одной из них за пределами циклов, где они объявлялись.

Как это часто бывает с наиболее эзотерическими свойствами языка, реализации компиляторов могут различаться.

Насколько длинным может быть цикл?

Длина цикла может измеряться в строках кода или глубине вложенности.

Делайте циклы достаточно короткими, чтобы их можно было увидеть сразу целиком Если вы обычно смотрите на циклы на вашем мониторе, а ваш монитор показывает 50 строк, то установите 50-строчное ограничение длины. Эксперты предложили ограничивать длину цикла одной страницей. Однако когда вы оцените преимущество создания простого кода, вы редко будете писать циклы длиннее 15 или 20 строк.

Ограничивайте вложенность тремя уровнями Иссл е- щщщ 06 даоще-дования показали, что способность программистов разоб- ний вложвнн<юти ш. раздел 19Л раться в цикле существенно снижается, если уровень вложенности превышает три уровня (Yourdon, 198ба). Если вам нужно большее число уровней, сделайте цикл короче (концептуально), вынеся его часть в отдельный метод или упростив управляющую структуру

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

Делайте длинные циклы особенно ясными Длина увеличивает сложность. Если вы пишете короткий цикл, вы можете использовать более рискованные управляющие структуры, такие как break и continue, множественные выходы, сложные условия завершения и т.д. Если вы пишете более длинный цикл и проявляете хоть какую-то заботу о читателях, вы предусмотрите в цикле только один выход и сделаете условие выхода исключительно понятным.



16.3. Простое создание цикла - изнутри наружу

Если у вас иногда возникают затруднения при кодировании сложного цикла (что бывает у большинства программистов), есть простой способ реализовать его с первого раза. Вот как это сделать. Начните с одного действия. Закодируйте его с помощью констант. Затем сделайте отступ, окружите его циклом и замените константы индексами цикла или вычисляемыми выражениями. Добавьте еще один цикл, если он нужен, и замените другие константы. Повторите процесс нужное число раз. После этого добавьте код инициализации. Так как вы начали с одного действия и двигались в сторону его обобщения, то можете рассматривать этот процесс как кодирование изнутри наружу

беикршнаи ссыпка Кодирд0а*> Допустим, вы разрабатываете программу для страховой «йв цйш иавутри «аружу похо- компании. Ставки для страхования жизни варьируются в же на ППП (см. главу 9). зависимости от возраста и пола страхователя. Ваша задача

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

Во-первых, в комментариях напишите шаги, которые должно выполнять тело цикла. Легче записать, что необходимо сделать, когда вы не думаете о деталях синтаксиса, индексах цикла, массива и т. п.

Шаг 1: Создание цикла изнутри наружу (псевдокод)

- Получить ставку из таблицы.

- Добавить ставку к общей сумме.

Во-вторых, замените комментарии в теле цикла на код, насколько это возможно без фактического написания всего цикла. В данном случае возьмите ставку для одного лица и добавьте ее к сумме. Используйте реальные данные, а не абстракции.

Шаг 2: Создание цикла изнутри наружу (псевдокод)

- table еще не использует индексов.

->rate = table[ ]

totalRate = totalRate + rate

Пример предполагает, что table - это массив, содержащий данные о ставках. Сначала вам не надо беспокоиться об индексах массива, rate - это переменная, в которой хранится ставка, выбранная из таблицы ставок. Соответственно totalRate

- переменная, содержащая сумму всех ставок.

Далее добавьте индексы к массиву table:

Шаг 3: Создание цикла изнутри наружу (псевдокод)

rate = table[ census.Age ][ census.Gender ] totalRate = totalRate + rate

Доступ к элементам массива осуществляется в зависимости от возраста и пола, поэтому censusAge и census.Gender служат для индексации массива. Пример пред-



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.0026