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

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

дательный эффект применения goto перевешивается недостатками дублированного кода.

Оператор goto может пригодиться в методе, который сна- дррцпш tfmm О щтт чала распределяет ресурсы, выполняет с ними какие-то one- операторов оШ » кода, «с-рации, а потом освобождает эти ресурсы. Используя goto, вы тшьзукщш рвнсурсы, см. ниже можете выполнять очистку в одном месте. Оператор goto тщраэуяви «06р«йк)тка ошибок « уменьшает вероятность того, что вы забудете освободить опфаторыдОбисшнениях ресурсы при обнаружении ошибки.

Порой goto позволяет создать более быстрый и короткий код. Вышеупомянутая статья Кнута 1974 года рассматривает несколько вариантов, в которых goto дает ощутимое преимущество.

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

Десятилетия исследований операторов goto не смогли про- шдешьствуют mm о

демонстрировать их вредоносность. В обзоре литературы щ намеренно хаотичная Б.А. Шейл (В.А. Shell) сделал вывод, что нереалистичные тес- управйЯ10щай С1дотда ухудша-товые условия, плохой анализ данных и неубедительные ре- ет проиеводитвяьность [fiporpatt-

зультаты не подкрепляют заявления Шнейдермана и др., что Ь жлершвшы т

ттшш прашческй ни-

число ошибок в коде пропорционально количеству goto какого доказатепьстаа полезно-

(1981). Шейл не зашел так далеко, чтобы утверждать, что ис- го эффекта какого-то конкрет-

пользование goto - хорошая идея, он лишь показал, что эк- ного способа стрстирошия

спериментальные данные против этих операторов неубеди- ррашющей логики, тельны. - й/вйя

И, наконец, операторы goto входят во множество современных языков, включая Visual Basic, С++ и Ada - наиболее тщательно продуманный язык программирования в истории. Ada создавался уже после того, как были приведены все аргументы с обеих сторон дискуссии по goto, и после всестороннего рассмотрения вопроса разработчики Ada решили включить в него goto.

Воображаемая дискуссия по поводу goto

Отличительная особенность большинства обсуждений goto - поверхностность. Спорщик, утверждающий, что «goto - это зло», приводит тривиальный фрагмент кода, содержащий операторы goto, 2i затем показывает, как легко его можно переписать без goto. Это доказывает главным образом то, что тривиальный код можно легко написать и без goto.

Спорщик, утверждающий: «Я не могу жить без goto», - обычно приводит случай, в котором исключение goto выливается в дополнительное сравнение или дублирование кода. Это доказывает в основном то, что есть случаи, в которых goto позволяет выполнить на одно сравнение меньше - незначительная выгода для современных компьютеров.



Большинство учебников также не помогает. Они приводят простой пример переписывания некоторого кода без goto, как будто это все объясняет. Вот обманчивый пример тривиального фрагмента кода из такого учебника:

Пример кода, который должен легко переписываться без goto (С++)

do {

GetData( inputPile, data ); if ( eof( inputPile ) ) { goto LOOP EXIT;

DoSomething( data ); } while ( data != -1 ); LOOP.EXIT:

Книга быстро заменяет этот фрагмент кодом без goto:

Пример предположительно эквивалентного кода, переписанного без goto (С++)

GetData( inputPile, data );

while ( ( !eof( inputPile ))&&(( data != -1 ) ) ) { DoSomething( data ); GetData( inputPile, data )

Этот так называемый «простой» пример содержит ошибку. В случае, когда переменная data равна -1, преобразованный код отслеживает -1 и выходит из цикла до выполнения DoSomethingQ. Исходный код выполняет DoSometbingO до того, как -/ обнаружена. Автор книги по программированию, пытаясь показать, как легко можно кодировать без goto, преобразовал собственный же пример некорректно. Но ему не стоит расстраиваться - другие книги содержат похожие ошибки. Даже профессионалы сталкиваются с трудностями при преобразовании кода, использующего goto.

Вот более точная реорганизация кода без goto:

Пример действительно эквивалентного кода, переписанного без goto (С++)

do {

GetData( inputPile, data ); if ( !eof( inputPile )) { DoSomething( data );

} while ( ( data != -1 ) && ( !ebf( inputPile ) ) );

Даже при правильном преобразовании кода этот пример все же искусственный, потому что он показывает тривиальный вариант использования goto. Это не тот случай, когда толковые программисты выбирают goto в качестве предпочтительной формы управления.

В наши дни уже тяжело добавить что-нибудь стоящее к теоретическим дебатам вокруг goto. Однако на что обычно не обращают внимания, так это на ситуации, в кото-



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

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

Обработка ошибок и операторы goto

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

Пример кода с goto, который обрабатывает ошибки и освобождает ресурсы (Visual Basic)

Этот метод стирает группу файлов.

Sub PurgeFiles( ByRef errorState As Error Cocle )

Dim filelndex As Integer

Dim fileToPurge As Data File

Dim fileList As File List

Dim numPilesToPurge As Integer

MakePurgeFileList( fileList, numPilesToPurge )

errorState = FileStatus Success filelndex = 0

While ( filelndex < numPilesToPurge ) filelndex = filelndex + 1

If Not ( PindPile( fileList( filelndex ), fileToPurge ) ) Then errorState = FileStatus FileFindError

- Здесь используется GoTo.

-> GoTo END PROC

End If

If Not OpenFile( fileToPurge ) Then errorState = FileStatus FileOpenError

- Здесь используется GoTo.

-> GoTo END PROC

End If

If Not OverwriteFile( fileToPurge ) Then

errorState = FileStatus FileOverwriteError



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