683 MGraphics.ru - На примере денег - Равенство для всех
Уроки photoshopa


Экстремальное программирование - На примере денег

Равенство для всех

Условия перепечатки материалов

Рейтинг статьи: 0.000.000.000.000.00
Проголосовало 0 человек.
Оцените статью:

Если у меня есть целое число и я прибавляю к нему 1, то не предполагаю, что изме­нится исходное число, — в результате я ожидаю получить новое число. Объекты же обычно ведут себя другим образом. К примеру, если у меня есть контракт и я добавлю 1 к его сумме, то это будет означать, что сумма контракта должна изме­ниться (да, несомненно, это пример для обсуждения многих интересных законов бизнеса, которые мы здесь рассматривать не будем).

Мы можем использовать объекты в качестве значений, так же как используем наш объект Dollar. Соответствующий паттерн называется Value Object (объект-зна­чение). Одно из ограничений этого паттерна заключается в том, что значения ат­рибутов объекта устанавливаются в конструкторе и никогда в дальнейшем не из­меняются.

Значительное преимущество использования паттерна Value Object состоит в том, что не нужно беспокоиться о проблеме наложения имен (aliasing). Скажем, у меня есть чек и я устанавливаю его сумму — $5, а затем присваиваю эти же $5 сумме другого чека. Одна из самых неприятных проблем на моей памяти заклю­чалась в том, что изменение величины первого чека может приводить к непредна­меренному изменению величины второго. Это и есть проблема наложения имен (aliasing).

Когда вы используете Value Objects, не нужно беспокоиться о наложении имен (aliasing). Если у меня есть пять долларов ($5), то они всегда гарантированно бу­дут оставаться именно пятью долларами ($5). Если вдруг кому-то понадобится $7, тогда придется создавать новый объект.

$5+10 CHF=$10, если курс обмена 2:1

$5*2=$10

Сделать переменную amount закрытым членом класса

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

 

Одно из следствий использования Value Objects заключается в том, что все опе­рации должны возвращать результаты в виде новых объектов, о чем было рассказано в главе 2. Другое следствие заключается в том, что Value Objects должны реа-лизовывать equals(), операцию проверки равенства, потому что одни $5 ничем не отличаются от других.

$5+10 CHF=$10, если курс обмена 2:1

$5*2=$10

Сделать переменную "amount" закрытым членом

Побочные эффекты в клоссе Dollar?

Округление денежных величин?

equals()

hashCode()

 

Кроме того, если использовать Dollar в качестве ключа хэш-таблицы, то, реали-зовывая equalsO, придется реализовать и hashCode(). Добавим этот пункт в список задач и вернемся к нему, когда это будет необходимо.

Вы ведь не собираетесь немедленно приступить к реализации метода equals()? Отлично, я тоже об этом не думаю. Ударив себя линейкой по руке, я стал раз­мышлять над тем, как протестировать равенство. Для начала $5 должны быть равны $5:

public void testEqualityО {

assertTrue(new Dollar(5).equals(new Dollar(5))): } Полоска окрасилась красным. Для возврата значения true достаточно заглушки:

Dollar

public boolean equals(0bject object) {

return true: }

 

Конечно, мы с вами знаем, что true на самом деле это "5==5", что, в свою оче­редь, означает "amount==5", что соответствует "amount==dollar.amount". Но если бы я сразу проследил все эти шаги, я не смог бы продемонстрировать третью и наиболее консервативную методику реализации — триангуляцию (Triangulation).

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

По аналогии, когда мы выполняем триангуляцию, мы обобщаем код только в том случае, когда у нас два примера или больше. При этом мы ненадолго игнори­руем дублирование между тестом и самим кодом (приложения). Когда второй пример потребует более общего решения, тогда и только тогда мы выполним обобщение.

Итак, для триангуляции нам понадобится второй пример. Как насчет того, чтобы проверить $5 != $6?

public void testEquality(){

assertTrue(new Dollar(5).equals(new Dollar(5))):

assertFalse(new Dollar(5).equals(new Dollar (б))):

}

 

Теперь необходимо обобщить равенство (equality):

Dollar

public boolean equals(Object object) {

Dollar dollar=(Dollar) object;

return amount == dollar.amount: }

$5+10 CHF=$10, если курс обмена 2:1

$5*2=$10

Сделать переменную amount закрытым членом класса

Побочные эффекты в клоссс Dollar?

Округление денежных величин?

equals()

hashCode()

 

Мы могли бы использовать триангуляцию и для управления обобщением ме­тода times(). Если бы у нас были примеры $5*2 = $10 и $5 * 3 - $15, нам не уда­лось бы просто возвращать константу.

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

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

$5+10 CHF=$10, если курс обмена 2:1

$5*2=$10

Сделать переменную amount закрытым членом класса

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

hashCode()

Равенство значению null

Равенство объектов

Итак, сейчас операция «равенство» (equality) реализована полностью. Но как учесть сравнение со значением null и сравнение с другими объектами? Это часто используемые операции, пока они нам еще не нужны, поэтому мы просто доба­вим их в список задач.

Теперь, когда у нас есть операция равенства, можно напрямую сравнивать объекты Dollar. Это позволит нам сделать переменную amount закрытой, какой и должна быть хорошая экземплярная переменная. Резюмируя все вышесказан­ное, мы:

• поняли, что для использования паттерна проектирования Value Object необходимо реализовать операцию проверки равенства;

• создали тест для этой операции;

• реализовали ее простейшим способом;

• продолжили тестирование (вместо того, чтобы сразу приступить к рефак-торингу);

• выполнили, рефакторинг так, чтобы охватить оба теста сразу.

Разместил: MaxxWhite
Опубликовано: 27.05.2008
Статья "Экстремальное программирование - На примере денег - Равенство для всех" прочтена 5072 раза.





Последние новости