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

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

Метод не защищен от получения плохих данных. Если переменная cmtQtr равна О, ъыp2iЖ\m ytdRevenue * 40 / (double) cmtQtr вызывает ошибку деления на 0.

Метод использует несколько «магических» чисел: 100, 4.0, 12, 2 и 3 (о магических числах см. раздел 12.1).

Параметры screenX и screenY внутри метода не используются.

Параметр prevColor передается в метод неверно: он передается по ссылке (в-), но значение ему внутри метода не присваивается.

Метод принимает слишком много параметров. Как правило, чтобы параметры можно было охватить умом, их должно быть не более 7 - этот метод принимает 11. Параметры представлены таким неудобочитаемым образом, что большинство разработчиков даже не попытаются внимательно изучить их или хотя бы подсчитать.

Параметры метода плохо упорядочены и не документированы (об упорядочении параметров см. эту главу, о документировании - главу 32).

Если не считать сами компьютеры, методы - величайшее

изобретение в области компьютерных наук. Методы облег- http:/ycc2e.cofn/0799

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

вания деятелей таким кодом, что был приведен выше, - личайшего изобретения в обла-настоящее преступление. сти информатики. 06 эффек-

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

«Хорошо, - скажете вы. - Я уже знаю, что методы очень полезны и постоянно их использую. Чего ж вы от меня хотите?»

Я хочу, чтобы вы поняли, что есть много веских причин, а также правильных и неправильных способов создания методов. Будучи саудентом факультета информатики, я думал, что главная причина создания методов - предотврап1,ение дублирования кода. Во вводном учебнике, по которому я учился, полезность методов обосновывалась тем, что предотвращение дублирования кода делает программу более простой в разработке, отладке, документировании и сопровождении. Точка. Если не считать синтаксические детали использования параметров и локальных переменных, на этом обсуждение методов в той книге заканчивалось. Такое объяснение теории и практики использования методов нельзя считать ни удачным, ни полным. В следующих разделах я постараюсь это исправить.



7.1. Разумные причины создания методов

Ниже я привел список причин создания метода. Они несколько перекрываются и не исключают одна другую.

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

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

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

if ( node о NULL ) then

while ( node.next <> NULL ) do node = node.next leafName = node.name end while else

leafName = "" end if

вы можете иметь дело с чем-нибудь вроде:

leafName = GetLeafName( node )

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

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



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

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

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

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

Упрощение сложных булевых проверок Понимание сложных булевых проверок редко требуется для понимания пути выполнения программы. Поместив такую проверку в метод, вы сможете упростить код, потому что (1) детали проверки будут скрыты и (2) описательное имя метода позволит лучше охарактеризовать суть проверки.

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

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

Для уменьшения объема других методов? Нет. При на- fiepespecTHfl ссьша О сокры-личии стольких разумных причин создания методов эта не тии шформари ш. подраздея нужна. На самом деле для решения некоторых задач лучше «Скрывайте секрету (к вопро-использовать один крупный метод (об оптимальном размере сокрытии формации)» метода см. раздел 7.4). раздела 5.3.



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