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

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

На заре программйроеаиия про Удобочитаемый код писать ничуть не дольше, чем запутан-

грамма считалась частной соб- "ьш - по крайней мере в далекой перспективе. В работо-

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

ни6 чужой программы без спроса стью прочесть то, что написали, и уже одного этого доста-

было не меньшей наглостью, чем точно для работы над понятностью кода. Однако код чита-

чтеиие любовного письма. По г лх г лх

сути этим и Шилась програм Р обзоров. И при исправлении ошибок. И при

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

граммиста компьютеру, полным другой пытается использовать фрагмент вашего кода в по-

йнтимных деталей, известных хожей программе,

только партнерам, Программы

заполнялись кличками домаш- Работу над читабельностью кода не следует считать необя-

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

столь популярными у влюблен- ства во время написания за счет удобства во время чтения

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

awt/a ц U s»««,.an,u, л написать хороший код, чем раз за разом читать плохой,

больше никого во Вселенной, f t-

Всем остальным людям такие «Что, если я просто пишу код для себя? Почему я должен

программы непонятны. делать его удобочитаемым?» Потому что через неделю-две

ШШп Ытотт вы будете работать над другой программой и подумаете: «Эй!

{ЫШ&\ МвгсоПу) я уже написал этот класс на прошлой неделе. Я просто возьму мой старый протестированный отлаженный код и сэкономлю время». Если код неудобочитаем, желаю удачи - она вам пригодится.

Оправдывать написание нечитаемого кода тем, что над проектом работаете только вы, опасно. Помните, как ваша мать говорила: «Что, если твое лицо застынет в этом выражении?», а отец - «Ты играешь так, как тренируешься». Привычки влияют на всю вашу работу, и вы не можете изменить их, просто захотев этого, поэтому убедитесь, что используемые вами подходы, став привычками, вас устроят. Профессиональные программисты пишут удобочитаемый код, и точка.

Поймите также, что утверждение, согласно которому код может принадлежать одному программисту, спорно. В связи с этим Дуглас Комер провел полезное различие между личными и общими программами (Comer, 1981): «личные программы» используются только программистом. Никто другой их не использует. Никто другой их не изменяет. Никто даже не знает об их существовании. Такие программы обычно тривиальны и крайне редки. А вот «общие программы» используются или изменяются не только автором, но и кем-то еще.

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

Даже если вы думаете, что код будете читать только вы, в реальном мире высока вероятность того, что его придется изменять кому-то другому Одно из исследований показало, что среднюю программу сопровождали 10 поколений программистов, пока она не была переписана (Thomas, 1984). Програм-



мисты, отвечающие за сопровождение, тратят от 50 до 60% времени, пытаясь понять код, и они по достоинству оценят ваши усилия, потраченные на его документирование (Parikh and Zvegintzov, 1983).

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

Если вы считаете, что какой-то код не нужно делать удобочитаемым, потому что никто другой никогда не будет иметь с ним дело, проверьте, не путаете ли вы причину и следствие.

34.4. Программируйте с использованием языка, а не на языке

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

Разумно ли создавать метод-член класса, не согласующийся с абстракцией класса, только потому, что он удобнее метода, обеспечивающего более высокую согласованность? Код должен как можно надежнее защищать абстракцию, формируемую интерфейсом класса. Не нужно использовать глобальные данные или операторы goto только потому, что их поддерживает язык. Вы можете отказаться от опасных возможностей и применять вместо них соглашения программирования, компенсирующие слабости языка. Выбирать самые очевидные пути - значит программировать на языке, а не с использованием языка; в программировании этот выбор эквивалентен вопросу: «Если Фредди спрыгнет с моста, прыгнете ли вы за ним?» Подумайте о своих целях и решите, как лучше всего достичь их, программируя с использованием языка.

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

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



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

34.5. Концентрируйте внимание с помощью соглашений

Перехретиш! $еыдх9 О попеа- Набор соглашений - один из интеллектуальных инструмен-нош соглашений в контексте управления сложностью. В предыдущих главах мы го-

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

«Цели хорошего форматировав Многие аспекты программирования в чем-то произвольны.

НИИ» раздела 31.1 Какой длины отступ делать перед циклом? Как форматиро-

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

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

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

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



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