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

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сущвн№ «Правила Деметры* см. в книгах «Ивдгпа-tic Prograramer* {Hunt and Thomas, 2000), Applying UML and Patterns* (Larman, 2001) и «Rin-damenlals of Object-Oriented Design in UMl» (Page-Jones, 2000).

B, HO ему не следует вызывать методы объектов, возвращаемых Объектом В. В нашем случае это означает, что вызов account.ContactPersonQ приемлем, однако вызова accounl-ContactPersonQ DaytimeContactlnfoQ следовало бы избежать. Это упрощенное объяснение - подробнее см. в книгах, указанных в конце главы.

Вообще мингшизируйте сотрудничество класса с другими классами Старайтесь свести к минимуму все следующие показатели:

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

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

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

Конструкторы

Советы по использованию конструкторов почти не зависят от языка (по крайней мере это касается С++, Java и Visual Basic). С деструкторами связано больше различий - см. материалы, указанные в разделе «Дополнительные ресурсы».

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

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

Пример создания класса-одиночки с помощью закрытого конструктора (Java)

public class Maxld {

конструкторы и деструкторы

- Закрытый конструктор.

> private MaxIdO {

I тденш! Ана-

логичный код, налйсанный на С"*-*, Ш Ьы очень похож. Подробнее см. ращл 26 mm «Моге Effective С++»> (Meyers, 1998).

открытые методы

- Открытый метод, предоставляющий доступ к единственному экземпляру класса.

public static Maxld Getlnstance() { return m instance;

закрытые члены



- Единственный экземпляр класса.

private static final Maxld n instance = new MaxIdO;

Закрытый конструктор вызывается только при инициализации статического объекта mjnstance. Для обращения к классу-одиночке Maxld нужно просто вызвать метод Maxld. GetlnstanceQ.

Если сомневаетесь, выполняйте полное копирование, а не ограниченное

Одним из главных аспектов работы со сложными объектами является выбор типа их копирования: полного или ограниченного. Полная копия (deep сору) - это почленная копия данных-членов объекта; ограниченная копия (shallow сору) обычно просто указывает или ссылается на исходный объект, хотя конкретные значения «полного» и «ограниченного» копирования могут различаться.

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

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

Если вы находите, что вам все-таки нужно ограниченное копирование, прекрасное обсуждение этого подхода в контексте С++ см. в разделе 29 книги Скотта Мейерса «Моге Effective С++» (Meyers, 1996). В книге Мартина Фаулера «Refactoring» (Fowler, 1999) описываются специфические действия, нужные для преобразования ограниченных копий в полные и наоборот [Фаулер называет их объектами-ссылками (reference objects) и объектами-значениями (value objects)].

6.4. Разумные причины создания классов

Если вы верите всему, что читаете, у вас могло сложиться

Перехреетная ееылкд Причины

создания классов и методов ао впечатление, что единственная причина создания класса -многом перекрываются (см. моделирование объектов реального мира. На самом деле это раздел 7.1). весьма далеко от истины. Список разумных причин созда-

ния класса приведен ниже. Перекрееткая Сбьшка Об иден- Моделирование объектов реального мира Пусть моде-umml лирование объектов реального мира - не единственная

те объекты реального мира причина создания класса, но от этого она не становится раздела 5.3. менее хорошей! Создайте класс для каждого объекта реаль-



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

Моделирование абстрактных объектов Другой разумной причиной создания класса является моделирование абстрактного объекта - объекта, который не существует в реальном мире, но является абстракцией других конкретных объектов. Прекрасный пример - классический объект Shape (фигура). Объекты Circle (окружность) и Square (прямоугольник) существуют на самом деле, тогда как класс Shape - это абстракция конкретных фигур.

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

- одна из главных проблем объектно-ориентированного проектирования.

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

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

Сокрытие деталей реализации Еще одна прекрасная причина создания класса

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

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



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