Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 11 лет назад пользователемАльбина Топорова
1 eXtreme Programming XP Тема 3
2 XP Пусть есть некоторая информационная система для банков. В качестве основной валюты для расчетов используется доллар, для работы с которым был реализован класс Dollar. В условиях кризиса требовалось перевести систему на мультивалютные расчеты.
3 XP $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 public void testMultiplication() { Dollar five=new Dollar(5); five.times(2); assertEquals(10.,five.amount); } public class Dollar { double amount; Dollar (double amount) {} void times(int mult) {} }
4 XP При объявлении переменной amount: double amount=5*2; В методе times: void times(int mult){ amount=5*2;} Изменения должны быть и в конструкторе, и в методе times: Dollar (double amount){this.amount=amount;} void times(int mult) {amount*=mult;}
5 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин Тест, который не выполняется: public void testMultiplication() { Dollar five=new Dollar(5); five.times(2); assertEquals(10.,five.amount); five.times(3); assertEquals(15.,five.amount); } XP
6 Изменение метода times: Dollar times(int mult) { return new Dollar(amount*mult); } Изменение теста: public void testMultiplication() { Dollar five=new Dollar(5); Dollar product=five.times(2); assertEquals(10.,product.amount); product=five.times(3); assertEquals(15.,product.amount); } XP
7 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Тест на равенство: public void testEquality() { assertTrue(new Dollar(5).equals(new Dollar(5))); } Тест не работает – нужна заглушка метода equals. public boolean equals(Object obj){return true;} XP
8 Не работает другой тест: public void testEquality() { assertTrue(new Dollar(5).equals(new Dollar(5))); assertFalse(new Dollar(5).equals(new Dollar(6))); } Требуется изменить метод equals: public boolean equals(Object obj) { Dollar dollar=(Dollar)obj; return amount==dollar.amount; } XP
9 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов XP
10 Меняем тест – сравниваем на равенство объекты: public void testMultiplication() { Dollar five=new Dollar(5); assertEquals(new Dollar(10),five.times(2)); assertEquals(new Dollar(15),five.times(3)); } XP
11 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF XP
12 Добавляем новый класс Franc (код из класса Dollar); Пишем тест: public void testFrancMultiplication() { Franc five=new Franc(5); assertEquals(new Franc(10),five.times(2)); assertEquals(new Franc(15),five.times(3)); } XP
13 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF Дублирование Dollar/Franc Общие операции equals() Общие операции times() XP
14 Создадим класс Money, от которого наследуют Dollar и Franc Перенесем в него переменную amount. Для выполнения всех тестов требуется сделать ее protected. XP
15 Меняем в классе Dollar метод equals – перенос на тип данных Money public boolean equals(Object obj) { Money money=(Money)obj; return amount==money.amount; } Переносим метод в класс Money и удаляем из классов Dollar и Franc. Тест: public void testEquality() { assertTrue(new Dollar(5).equals(new Dollar(5))); assertFalse(new Dollar(5).equals(new Dollar(6))); assertTrue(new Franc(5).equals(new Franc(5))); assertFalse(new Franc(5).equals(new Franc(6))); } XP
16 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF Дублирование Dollar/Franc Общие операции equals() Общие операции times() Сравнение долларов и франков XP
17 Тест: public void testEquality() { assertTrue(new Dollar(5).equals(new Dollar(5))); assertFalse(new Dollar(5).equals(new Dollar(6))); assertTrue(new Franc(5).equals(new Franc(5))); assertFalse(new Franc(5).equals(new Franc(6))); assertFalse(new Franc(5).equals(new Dollar(5))); } Изменение метода: public boolean equals(Object obj) { Money money=(Money)obj; return amount==money.amount && getClass().equals(money.getClass()); } XP
18 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF Дублирование Dollar/Franc Общие операции equals() Общие операции times() Сравнение долларов и франков Валюта? XP
19 Методы times могут возвращать Money Money times(int mult) { return new Dollar(amount*mult); } В результате классы почти одинаковые -> хочется сделать только один класс XP
20 В класс Money добавим фабричный метод создания объекта Dollar: static Dollar dollar(double amount) {return new Dollar(amount);} Меняем принцип создания объекта в тесте: public void testMultiplication() { Money five=Money.dollar(5); assertEquals(Money.dollar(10),five.times(2)); assertEquals(Money.dollar(15),five.times(3)); } Осталась ошибка – метод times не определен в классе Money XP
21 Делаем класс Money абстрактным, добавляя в него абстрактный метод times. abstract class Money { protected double amount; … abstract Money times(int mult); } Меняем фабричный метод с точки зрения возвращаемого значения static Money dollar(double amount) {return new Dollar(amount); } XP
22 Делаем те же действия с классом Franc Меняем тесты public void testEquality() { assertTrue(Money.dollar(5).equals(Money.dollar(5))); assertFalse(Money.dollar(5).equals(Money.dollar(6))); assertTrue(Money.franc(5).equals(Money.franc(5))); assertFalse(Money.franc(5).equals(Money.franc(6))); assertFalse(Money.franc(5).equals(Money.dollar(5))); } XP
23 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF Дублирование Dollar/Franc Общие операции equals() Общие операции times() Сравнение долларов и франков Валюта? Нужен ли тест на умножения франков на число? XP
24 Добавляем метод для получения названия валюты в классы Dollar и Franc и абстрактный метод в класс Money: abstract String currency(); String currency(){ return "USD";} String currency(){ return "CHF";} Тест public void testCurrency() { assertEquals("USD",Money.dollar(1).currency()); assertEquals("CHF",Money.franc(1).currency()); } XP
25 Вводим символьную переменную для обозначения валюты в класс Money и переносим функцию currency полностью в класс Money abstract class Money { protected double amount; protected String currency; … String currency(){ return currency; } } Конструкторы должны инициализировать эту строку, например, Franc (double amount) { this.amount=amount; this.currency="CHF"; } XP
26 Конструкторы производных классов похожи -> можно инициализировать переменную currency внутри конструктора базового класса: public Money(double amount, String currency) { this.amount=amount; this.currency=currency; } Конструкторы производных классов выглядят, например, так: Franc (double amount) { super(amount,"CHF"); } Можно добавить второй параметр с обозначением валюты и передавать его конструктору базового класса XP
27 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF Дублирование Dollar/Franc Общие операции equals() Общие операции times() Сравнение долларов и франков Валюта? Нужен ли тест на умножения франков на число? XP
28 Функция times класса Dollar выглядит так: Money times(int mult) { return Money.dollar(amount*mult);} Вернемся к вызову конструктора: Money times(int mult) { return new Dollar(amount*mult,USD");} Строку с названием валюты можно получить из поля currency-> переносим в класс Money (класс перестает быть абстрактным) Money times(int mult){ return new Money(amount*mult,currency);} Тест не срабатывает – сравнение имен классов (один объект класса Dollar, другой – класса Money). XP переносим в класс Money (класс перестает быть абстрактным) Money times(int mult){ return new Money(amount*mult,currency);} Тест не срабатывает – сравнение имен классов (один объект класса Dollar, другой – класса Money). XP">
29 Вернемся к методам times внутри производных классов, например, в Dollar Money times(int mult) {return new Dollar(amount*mult,currency);} Тесты сработали. Добавляем тест для сравнения объектов, созданных с помощью Money и Dollar public void testDifferentClasses() { assertTrue(new Money(10,"CHF").equals(new Franc(10,"CHF"))); } Тест не сработал. XP
30 Меняем equals – сравнение названий валют, а не имен классов. public boolean equals(Object obj) { Money money=(Money)obj; return amount==money.amount && currency.equals(money.currency); } Тесты сработали. Снова отказываемся от методов times производных классов. Тесты сработали. XP
31 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF Дублирование Dollar/Franc Общие операции equals() Общие операции times() Сравнение долларов и франков Валюта? Нужен ли тест на умножения франков на число? XP
32 Производные классы имеют только конструкторы. Отказываемся от них. Методы-фабрики должны вызывать конструктор класса Money. static Money franc(double amount) { return new Money(amount,"CHF"); } Тест на равенство объектов разных классов и умножение франков можно удалить. XP
33 $5+10 CHF =$10, если курс обмена 2:1 $5*2=$10 amount-закрытая переменная Побочные эффекты в классе Dollar – изменение объекта Округление денежных величин equals() Равенство значению null Равенство объектов 5 CHF*2=10 CHF Дублирование Dollar/Franc Общие операции equals() Общие операции times() Сравнение долларов и франков Валюта? Нужен ли тест на умножения франков на число? $5+$5=$10 XP
34 Реализуем тест: public void testSimpleAddition() { Money sum=Money.dollar(5).plus(Money.dollar(5)); assertEquals(sum,Money.dollar(10)); } В класс Money добавляем функцию plus: Money plus(Money added) { return new Money(amount+added.amount,currency); } XP
35 Обменный курсы должен знать банк -> создаем класс Bank (в нем метод reduce для перевода денег в конкретную валюту). XP
36 Тест: public void testSimpleAddition() { Money five=Money.dollar(5); Money sum=five.plus(five); Bank bank=new Bank(); Money reduced=bank.reduce(sum, "USD"); assertEquals(sum,Money.dollar(10)); } В классе Bank должна быть заглушка: public class Bank { Money reduce(Money source, String to) {return Money.dollar(10); } } Метод plus возвращает Money. XP
37 Тесты: public void testReduceMoney() { Bank bank=new Bank(); bank.addRate("CHF","USD",2); Money result=bank.reduce(Money.franc(2), "USD"); assertEquals(Money.dollar(1),result); } public void testHashRates() { Bank bank=new Bank(); bank.addRate("CHF", "USD", 2); assertTrue(bank.rate("CHF", "USD")==2.); } XP
38 В классе Bank создаем хэш-таблицу: private class Pair { private String from; private String to; public Pair(String from, String to) { this.from=from; this.to=to; } public boolean equals(Object obj) { Pair p=(Pair)obj; return from.equals(p.from) && to.equals(p.to); } public int hashCode(){ return 0; } } private Hashtable rates=new Hashtable(); XP
39 void addRate(String from, String to, double rate) { rates.put(new Pair(from,to), new Double(rate)); } double rate(String from, String to) { Double rate=(Double)rates.get(new Pair(from,to)); return rate.doubleValue(); } XP
40 Делаем метод-заглушку класса Bank: Money reduce(Money source,String to) { double rate=1; if (source.currency.equals("CHF") && to.equals("USD")) rate=2.; if (source.currency.equals("USD") && to.equals("CHF")) rate=1./2; return new Money(source.amount/rate,to); } XP
41 Изменяем заглушку: Money reduce(Money source,String to) { double rate=1; Pair p=new Pair(source.currency,to); if (rates.containsKey(p)) rate=rate(source.currency,to); return new Money(source.amount/rate,to); } XP
42 Изменяем тест public void testReduceMoney() { Bank bank=new Bank(); bank.addRate("CHF","USD",2); Money result=bank.reduce(Money.franc(2), "USD"); assertEquals(Money.dollar(1),result); result=bank.reduce(Money.dollar(2), "USD"); assertEquals(result,Money.dollar(2)); result=bank.reduce(Money.dollar(2), "CHF"); assertEquals(result,Money.franc(4)); } Тест не работает, так как если курса нет, то в хэш-таблице ничего не будет найдено. XP
43 Добавлять надо два курса void addRate(String from, String to, double rate) { rates.put(new Pair(from,to), new Double(rate)); rates.put(new Pair(to,from), new Double(1/rate)); } XP
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.