Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Бек К. -> "Экстремальное программирование: разработка через тестирование " -> 60

Экстремальное программирование: разработка через тестирование - Бек К.

Бек К. Экстремальное программирование: разработка через тестирование — СПб.: Питер, 2003. — 224 c.
ISBN 5-8046-0051-6
Скачать (прямая ссылка): bek-k..pdf
Предыдущая << 1 .. 54 55 56 57 58 59 < 60 > 61 62 63 64 65 66 .. 81 >> Следующая


Представьте, что я — объект, и у меня есть прямоугольник (Rectangle). Я вычисляю некоторое значение, зависящее от этого прямоугольника, например его площадь. Чуть позже некто (например, другой объект) вежливо просит меня предоставить ему мой прямоугольник для выполнения некоторой операции. Чтобы не показаться невежливым, я предоставляю ему мой прямоугольник. А через пару мгновений, вы только посмотрите, прямоугольник был модифицирован у меня за спиной! Значение площади, которое я вычислил ранее, теперь не соответствует действительности и не существует способа известить меня об этом.

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

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

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

Я помню, как похожая ситуация возникла с целыми числами, когда я впервые изучал язык Smalltalk. Если я изменяю бит 2 на 1, почему все двойки не становятся шестерками?

а :- 2.

b := а.

а := a bitAt: 2 put: 1. а => 6 b => 2

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

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

Я предпочитаю использовать Value Object (Объект-значение) в ситуациях, когда операции, выполняемые над объектами, напоминают алгебру. Например, пересечение и объединение геометрических фигур, операции над значениями, с каждым из которых хранится единица измерения, а также операции символьной арифметики. Каждый раз, когда использование Value Object (Объект-значение) имеет хоть какой-то смысл, я пытаюсь его использовать, так как результирующий код проще' читать и отлаживать.

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

Null Object (Нуль-объект)

Каким образом реализовать специальные случаи использования объектов? Создать специальный объект, представляющий собой специальный случай. Специальный объект должен обладать точно таким же протоколом, что и обычный объект, но он должен вести себя специальным образом.
Предыдущая << 1 .. 54 55 56 57 58 59 < 60 > 61 62 63 64 65 66 .. 81 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100