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

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

Рефакторинг реализации классов

Замена объектов-значений на объекты-ссылки Если вы создаете и поддерживаете много копий крупных или сложных объектов, измените подход так, чтобы существовал только один оригинал объекта (объект-значение), а в остальном коде использовались ссылки на этот объект (объекты-ссылки).

Замена объектов-ссылок на объекты-значения Если вам приходится прилагать усилия для обработки ссылок на небольшие или простые объекты, сделайте все объекты-ссылки объектами-значениями.

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

Изменение положения методов-членов или данных-членов в иерархии наследования Подумайте о внесении в иерархию наследования нескольких общих изменений. Следующие изменения обычно выполняются для устранения повторений кода в производных классах:

перемещение метода в суперкласс;

перемещение поля в суперкласс;

перемещение тела конструктора в суперкласс.

Другие изменения обычно вносятся с целью поддержки специализации в производных классах:

перемещение метода в производные классы;

перемещение поля в производные классы;

перемещение тела конструктора в производные классы.

Перемещение специализированного кода в подкласс Если какой-то код класса используется только в подмножестве его экземпляров, переместите этот специализированный код в отдельный подкласс.

Объединение похожего кода и его перемещение в суперкласс Если несколько подклассов включают похожий код, объедините этот код и переместите его в суперкласс.

Рефакторинг интерфейсов классов

Перемещение метода в другой класс Создайте в целевом классе новый метод и переместите тело метода из исходного класса в целевой класс. После этого вы можете вызывать новый метод из старого.

Разделение одного класса на несколько Если класс имеет более одной области ответственности, разбейте его на несколько классов, имеющих ясно определенные области ответственности.

Удаление класса Если класс почти ничего не делает, переместите его код в другие, более связные классы и удалите его.

Сокрытие делегата Иногда Класс А вызывает и Класс В, и Класс С, тогда как на самом деле А должен вызывать только В, а В - С. Спросите себя, какова пра-



вильная абстракция взаимодействия Класса А с Классом В. Если за вызов С должен отвечать В, внесите нужные изменения.

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

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

Замена делегирования на наследование Если класс предоставляет доступ ко всем открытым методам класса-делегата (класса-члена), выполните наследование от класса-делегата, а не просто используйте его.

Создание внешнего метода Если в класс нужно включить дополнительный метод, но изменять класс нельзя, вы можете создать нужный метод в клиентском классе.

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

Инкапсуляция открытой переменной-члена Если данные-члены открыты, сделайте их закрытыми и реализуйте доступ к ним при помощи методов.

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

Сокрытие методов, которые не следует вызывать извне класса Если без метода интерфейс класса будет более согласованным, скройте метод.

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

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

Рефакторинг на уровне системы

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



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

Изменение однонаправленной связи между классами на двунаправленную

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

Изменение двунаправленной связи между классами на однонаправленную

Если два класса известны друг другу, но на самом деле только один класс должен знать о другом, измените характер связи между классами.

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

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

Контрольный список: виды рефакторинга

http: cc2e.com/2450 .

Рефакторинг на уровне данных

□ Замена магического числа на именованную константу.

□ Присвоение переменной более ясного или информативного имени.

□ Встраивание выражения в код.

□ Замена выражения на вызов метода.

□ Введение промежуточной переменной.

□ Преобразование многоцелевой переменной в несколько одноцелевых переменных.

□ Использование локальной переменной вместо параметра.

□ Преобразование элементарного типа данных в класс.

□ Преобразование набора кодов в класс или перечисление.

□ Преобразование набора кодов в класс, имеющий производные классы.

□ Преобразование массива в класс.

□ Инкапсуляция набора.

□ Замена традиционной записи на класс данных.

Рефакторинг на уровне отдельных операторов

□ Декомпозиция логического выражения.

□ Вынесение сложного логического выражения в грамотно названную булеву функцию.

□ Консолидация фрагментов, повторяющихся в разных частях условного оператора.

□ Использование оператора break I return вместо управляющей переменной цикла.

□ Возврат из метода сразу после получения ответа вместо установки возвращаемого значения внутри вложенных операторов if-then-else.

□ Замена условных операторов (особенно многочисленных блоков case) на вызов полиморфного метода.

□ Создание и использование «пустых» объектов вместо проверки того, равно ли значение 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.0069