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

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

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

Временная связность (temporal cohesion) наблюдается, когда операции объединяются в метод на том основании, что все они выполняются в один интервал времени. Типичные примеры - методы StartupQ (запуск программы) Сотр-leteNewEmployeeQ (прием нового сотрудника на работу) и ShutdownQ (завершение программы). Временную связность порой считают неприемлемой, поскольку иногда она связана с плохими методиками программирования, такими как включение слишком разнообразного кода в метод StartupQ.

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

Этот пример поднимает вопрос выбора имени, описывающего такой метод с адекватным уровнем абстракции. Вы могли бы назвать метод ReadConflgFileln-UScratcbFileEtcQ (прочитать конфигурационный файл, инициализировать вспомогательный файл и т. д.), но из этого следовало бы, что он имеет только случайную связность. Если же вы назовете метод StartupQ, будет очевидно, что он имеет одну цель и поэтому обладает функциональной связностью.

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

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

Для достижения лучшей связности поместите разные операции в отдельные методы. Сделайте так, чтобы вызывающий метод решал одну задачу, причем полностью: пусть он соответствует имени GetEmployeeQ (получить данные о со-



труднике), а не GetFirstPartOJEmployeeDataQ (получить первую часть данных о сотруднике). Вероятно, при этом придется изменить и методы, получающие остальные данные. Довольно часто достижение функциональной связности требует изменения двух или более первоначальных методов. Логическая связность (logical cohesion) имеет место, когда метод включает несколько операций, а выбор выполняемой операции осуществляется на основе передаваемого в метод управляющего флага. Этот вид связности называется логическим потому, что операции метода объединены только управляющей «логикой» метода: крупным оператором ifwRn рядом блоков case. Какой-нибудь другой по-настоящему «логической» связи между операциями нет. Поскольку определяющим атрибутом логической связности является отсутствие отношений между операциями, возможно, лучше было бы назвать ее «нелогичной связностью».

В качестве примера такого метода можно привести метод InputAllQ, принимающий в зависимости от полученного флага фамилии клиентов, данные карт учета времени сотрудников или инвентаризационные данные. Другие примеры - методы ComputeAllQ, EditAllO, PrintAllQ и SaveAllQ. Главная проблема с ними в том, что передавать флаг для управления работой метода нецелесообразно. Вместо метода, выполняющего одну из трех операций в зависимости от полученного флага, л)ше создать три метода, выполняющих по одной операции. Если операции используют некоторый одинаковый код или общие данные, код следует переместить в метод более низкого уровня, а методы упаковать в класс.

Однако логически связный метод вполне приемлем, если его Перекрестная ссылка Связность д состоит исключительно из ряда операторов г/или case такого метода может быть удовлетворительной, однако лрй вызовов других методов. Если единственная роль метода этом возникает один вопрос ~" координация выполнения команд и сам он не выполня-проектированйя более высоко- ет действий, это обычно удачное проектное решение. Такие го уровня: использовать ли one- методы еще называют «обработчиками событий». Обработ-раторы case вместо полиморф- хщи часто используются в интерактивных средах, таких как ного метода? См. также подраз- . , х>г • i A.f. г w.. ттт дел «Замена условных операто- РР Macintosh, Microsoft Windows и других средах с GUI.

ров (особенно многочисленных При случайной связности (coincidental cohesion) каких-блоков cm) на вызов лояшор- либо ясных отношений между выполняемыми в методе опе-фного метода» раздела 24.3. рациями нет. Этот вариант можно еще называть «отсутствием связности» или «хаотичной связностью». Низкокачественный метод С++, приведенный в начале этой главы, имеет случайную связность. Случайную связность трудно преобразовать в более приемлемый вид связности - как правило, методы со случайной связностью нужно проектировать и реализовать заново.

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



7.3. Удачные имена методов

Имя метода должно ясно описывать все, что он делает. Советы по выбору удачных имен методов приведены ниже. J!Jn, и Описывайте все, что метод выполняет Опишите в

имени метода все выходные данные и все побочные эффекты. Если метод вычисляет сумму показателей в отчете и открывает выходной файл, имя ComputeReport-TotalsQ не будет адекватным. ComputeReportTotalsAndOpenOutputFileO - имя адекватное, но слишком длинное и несуразное. Создавая методы с побочными эффектами, вы получите много длинных несуразных имен. Выход из этого положения - не использование менее описательных имен, а создание ясных методов без побочных эффектов.

Избегайте невыразительных и неоднозначных глаголов Некоторые глаголы могут описывать практически любое действие. Имена вроде HandleCalculationO, PerformServicesO, OutputUserQ, ProcessInputQ и DealWitbOutput() не говорят о работе методов почти ничего. В лучшем случае по этим именам можно догадаться, что методы имеют какое-то отношение к вычислениям, сервисам, пользователям, вводу и выводу соответственно. Исключением было бы использование глагола «handle» в специфическом техническом смысле обработки события.

Иногда единственным недостатком метода является невыразительность его имени; сам метод при этом может быть спроектирован очень хорошо. Если имя HandleOutputO заменить на FormatAndPrintOutputO, роль метода станет очевидной.

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

ШНе используйте для дифференциации имен методов исключительно номера Один разработчик написал весь свой код в форме единственного объемного метода. Затем он разбил код на фрагменты по 15 строк и создал методы Partl,Part2 и т. д. После этого он создал один высокоуровневый метод, вызывающий каждую часть кода. Подобный способ создания и именования методов глуп до невозможности (и столь же редок, надеюсь). И все же программисты иногда используют номера для дифференциации таких методов, как OutputUser, OutputUserl и OutputUser2. Номера в конце каждого из этих имен ничего не говорят о различиях представляемых методами абстракций, поэтому такие имена нельзя признать удачными.

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



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