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

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

дующие за проверкой if-tben-else, ближе к месту самой проверки, чем в случае с вложенными if и совсем не использует блоки else.

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

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

Переписать с помощью try-finally Некоторые языки, включая Visual Basic и Java, предоставляют конструкцию try-finally, которая может быть использована для очистки ресурсов в случае ошибки.

Чтобы переписать пример, используя подход с try-finally, поместите код, который должен проверять возможные ошибки, в блок try, 2i код очистки - в блок finally. Блок try задает область обработки исключений, а finally выполняет любое освобождение ресурсов. Блок finally будет вызываться всегда независимо от того, будет ли сгенерировано исключение и будет ли это исключение перехвачено в методе PurgeFilesQ.

Код, избавившийся от goto с помощью try-finally (Visual Basic)

Этот метод стирает группу файлов. Исключения передаются вызывающей стороне. Sub PurgeFilesO

Dim filelndex As Integer

Dim fileToPurge As Data File

Dim fileList As File List

Dim numPilesToPurge As Integer

MakePurgeFileList( fileList, numPilesToPurge )

filelndex - 0

While ( filelndex < numPilesToPurge ) filelndex = filelndex + 1

FindFile( fileList( filelndex ), fileToPurge ) OpenFile( fileToPurge ) OverwriteFile( fileToPurge ) Erase( fileToPurge ) Wend Finally

DeletePurgeFileList( fileList, numPilesToPurge ) End Try End Sub

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



Преимущество подхода с применением try-finally в том, что он проще, чем с goto и не использует goto. Кроме того, он позволяет избежать глубоко вложенных структур if-tben-else.

Ограничением данного варианта с try-finally является то, что он должен быть последовательно реализован во всем коде. Если бы предыдущий пример был частью программы, использующей коды ошибок наряду с исключениями, то коду исключения пришлось бы устанавливать код ошибки для всех возможных ошибок, и это требование сделало бы фрагмент примерно таким же сложным, как и другие варианты.

Сравнение рассмотренных подходов

ftepKacTNin иытг Полный защиту каждой из четырех приведенных методик есть что спиш мшлйк, которые мож- сказать. Подход с goto позволяет избежать глубокой вложен-ио С1й«менйть ь аналогичных ности и ненужных проверок, но, увы, он содержит goto. Под-тхщщт, перечислен а подраз- ход с вложенными (позволяет обойтись без goto, но его глу-ть «Сводка методик ушнше- бокая вложенность преувеличивает картину логической слож-mlfr ности метода. Подход со статусной переменной избегает goto

и глубокой вложенности, но добавляет дополнительные проверки. И, наконец, подход с try-finally тоже позволяет избежать как goto, так и глубокой вложенности, но доступен не во всех языках.

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

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

Операторы goto и совместное использование кода в блоке else

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

Пример совместного использования кода в блоке else с помощью goto (С++)

if ( statusOk ) {

if ( dataAvailable ) { importantVariable = x; goto MID.LOOP;



else {

importantVariable = GetValueO;

MID LOOP:

Много кода.

Это хороший, логически извилистый пример: его практически невозможно читать в том виде, в каком он есть, и тяжело правильно переписать без goto. Если вам кажется, что вы легко преобразуете его в вариант без goto, попросите кого-нибудь проверить ваш код! Несколько экспертов-программистов переписали его некорректно.

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

Лучший способ переписать этот код - вынести участок Много кода в отдельный метод. После этого вы сможете вызывать его из тех мест, где раньше располагались goto и метка его перехода. Это позволит сохранить оригинальную структуру условного оператора. Вот как это выглядит:

Пример совместного использования кода в блоке else

с помощью вынесения общего кода в отдельный метод (С++)

if ( statusOk ) {

if ( dataAvailable ) { importantVariable = x; DoLotsOfCode( importantVariable );

else {

importantVariable = GetValueO; DoLotsOfCode( importantVariable );

В общем случае написание нового метода - лучший подход. Однако иногда выносить дублированный код в отдельный метод непрактично. В этом случае как обходной маневр можно предложить реструктурирование условных выражений так, чтобы оставить код в том же методе, а не выносить в отдельный:

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

if ( ( StatusOk && dataAvailable ) !statusOk ) { if ( StatusOk && dataAvailable ) { importantVariable = x;



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