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

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

описаны в подразделе «Скрывайте секреты (к вопросу о сокрытии информации)» раздела 5.3.

берехистнаябоылка О пробна- Сокрытие глобальных данных Используя глобальные мах, связанных с глобальными данные, вы можете скрыть детали их реализации за интер-даннымй, см. раздел 13Л фейсом класса. Обращение к глобальным данным через методы доступа имеет ряд преимуществ в сравнении с их непосредственным использованием. Вы можете менять структуру данных, не изменяя программу Вы можете следить за доступом к данным. Кроме того, использование методов доступа подталкивает к размышлениям о том, на самом ли деле данные глобальны; часто оказывается, что «глобальные данные» на самом деле являются просто данными какого-то объекта.

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

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

Использование одного класса для чтения и записи БД является формой централизованного управления. Если БД нужно будет преобразовать в однородный файл или данные «в памяти», изменения придется внести только в один класс.

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

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

В Лаборатории проектирования ПО NASA были изучены десять проек-Д тов, в которых энергично преследовалось повторное использование кода

(McGarry, Waligora, and McDermott, 1989). И при объектно-, и при функционально-ориентированном подходах разработчикам первоначально не удалось достичь этой цели, потому что в предьщущих проектах не была создана достаточная база кода. Впоследствии при работе над функциональными проектами около 35% кода удалось взять из предыдущих проектов. В проектах, основанных на объектно-ориентированном подходе, этот показатель составил 70%. Если благодаря заблаговременному планированию можно избежать написания 70% кода, грех этим не воспользоваться!



Заметьте, что ядро подхода NASA к созданию повторно ис- щвлшштт» О реали*

пользуемых классов не включает «проектирование для по- щ тнтштт aubmz

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

ное использование, определяют в NASA в конце проектов, см. подраадел «Программа со-

Все действия по упрощению повторного использования Держит код, который может

когда-нибудь понадобиться»

классов выполняются как специальный проект в конце ос- рздла 24 2

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

Планирование создания семейства программ Если вы ожидаете, что программу придется изменять, разумно изолировать области предполагаемых изменений в отдельных классах. После этого вы можете изменять классы, не влияя на остальную часть программы, или вообще заменить их на абсолютно новые классы. Размышление о том, как может выглядеть целое семейство программ, а не просто одна программа, - эффективный эвристический принцип предвосхищения целых категорий изменений (Parnas, 1976).

Как-то я руководил группой, работавшей над рядом программ, упрощавших заключение договоров страхования. Мы должны были адаптировать каждую программу к отдельным тарифам, формату отчетов конкретного клиента и т. д. Однако многие части программ были похожи: например, классы ввода данных о потенциальных заказчиках, классы, сохранявшие информацию в БД, классы просмотра тарифов и т. д. Мы организовали программу так, чтобы каждая «изменчивая» часть находилась в отдельном классе. Создание первоначальной программы заняло три месяца или около того, но зато когда к нам обращался новый клиент, мы просто переписывали несколько классов и включали их в остальной код. Несколько дней работы и - вуаля! - специализированное приложение!

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

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

Классы, которых следует избегать

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



Избегайте создания «божественных» классов Избегайте создания классов, которые все знают и все могут. Если класс извлекает и задает данные других классов с использованием методов Get() и Set() (т. е. вмешивается в их дела и указывает им, что делать), спросите себя, не следует ли его функциональность реализовать в тех классах, а не выделять в божественный класс (Riel, 1996).

№фехрешш1 ооыш Такой ьщ УР нерелевантные классы Если класс имеет класса о&»14ио называют сгрукгу- только данные, но не формы поведения, спросите себя, дей-рой. О структурах см. раздел 13,1. ствительно ли это класс. Возможно, этот класс следует разжаловать, сделав его данные-члены атрибутами одного или нескольких других классов.

Избегайте классов, имена которых напоминают глаголы Как правило, класс, имеющий только формы поведения, но не данные, на самом деле классом не является. Подумайте о превращении класса вроде DatabaseInitialization() или StringBuilderO в метод какого-нибудь другого класса.

Резюме причин создания класса

Вот список разумных причин создания класса:

моделирование объектов реального мира;

моделирование абстрактных объектов;

снижение сложности;

изоляция СЛОЖНОСТИ;

сокрытие деталей реализации;

ограничение влияния изменений;

сокрытие глобальных данных;

упрощение передачи параметров в методы;

создание центральных точек управления;

облегчение повторного использования кода;

планирование создания семейства программ;

упаковка родственных операцией;

выполнение специфического вида рефакторинга.

6.5. Аспекты, специфические для языков

Использование классов в разных языках программирования имеет интересные различия. Рассмотрим, например, переопределение метода-члена в производном классе при реализации полиморфизма. В Java все методы переопределяемы по умолчанию, а чтобы в производном классе метод нельзя было переопределить, его нужно объявить как final. В С++ методы по умолчанию непереопределяемы. Чтобы сделать метод переопределяемым, его нужно объявить в базовом классе как virtual. В Visual Basic переопределяемый метод должен быть объявлен в базовом классе как overridable, а в производном классе нужно использовать ключевое слово overrides.



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