Float on the flow

とあるエンジニアのブログ。「ゆったり・しっかり」がモットー。

TDD勉強会第2回終了時点のソースコード(Java版)

12章以降、id:kabakiyoさんはC#でコーディングされていたのですが、自分はそれを見つつ
教科書通りにJavaでコーディングしていました。

というわけで、Javaのコードを公開しておきます。
 ⇒17章終了時で、最終的に以下のようなコードになりました。 
 (自分の環境でGreenになったコード)

 ⇒感想等はこちら http://d.hatena.ne.jp/shozzy/20090627/1246110366



MoneyTest.java

import junit.framework.TestCase;

public class MoneyTest extends TestCase{
	
	public void testMultiplication(){
		Money five = Money.dollar(5);
		assertEquals(Money.dollar(10), five.times(2));
		assertEquals(Money.dollar(15), five.times(3));
	}

	public void testEquality(){
		assertTrue(Money.dollar(5).equals(Money.dollar(5)));
		assertFalse(Money.dollar(5).equals(Money.dollar(6)));
		assertFalse(Money.franc(5).equals(Money.dollar(5)));
	}

	public void testCurrency(){
		assertEquals("USD", Money.dollar(1).currency());
		assertEquals("CHF", Money.franc(1).currency());
	}
	
	public void testSimpleAddition(){
		Money five = Money.dollar(5);
		Expression sum = five.plus(five);
		Bank bank = new Bank();
		Money reduced = bank.reduce(sum, "USD");
		assertEquals(Money.dollar(10), reduced);
	}
	
	public void testPlusReturnsSum(){
		Money five = Money.dollar(5);
		Expression result = five.plus(five);
		Sum sum = (Sum) result;
		assertEquals(five, sum.augend);
		assertEquals(five, sum.addend);
	}
	
	public void testReduceSum(){
		Expression sum = new Sum(Money.dollar(3), Money.dollar(4));
		Bank bank = new Bank();
		Money result = bank.reduce(sum, "USD");
		assertEquals(Money.dollar(7), result);
	}
	
	public void testReduceMoney(){
		Bank bank = new Bank();
		Money result = bank.reduce(Money.dollar(1), "USD");
		assertEquals(Money.dollar(1), result);
	}
	
	public void testReduceMoneyDifferentCurrency(){
		Bank bank = new Bank();
		bank.addRate("CHF", "USD", 2);
		Money result = bank.reduce(Money.franc(2), "USD");
		assertEquals(Money.dollar(1), result);
	}

	
	public void testIdentityRate(){
		assertEquals(1, new Bank().rate("USD", "USD"));
	}
	
	public void testMixedAddition(){
		Expression fiveBucks = Money.dollar(5);
		Expression tenFrancs = Money.franc(10);
		Bank bank = new Bank();
		bank.addRate("CHF", "USD", 2);
		Money result = bank.reduce(fiveBucks.plus(tenFrancs), "USD");
		assertEquals(Money.dollar(10), result);
	}
	
	public void testSumPlusMoney(){
		Expression fiveBucks = Money.dollar(5);
		Expression tenFrancs = Money.franc(10);
		Bank bank = new Bank();
		bank.addRate("CHF", "USD", 2);
		Expression sum = new Sum(fiveBucks, tenFrancs).plus(fiveBucks);
		Money result = bank.reduce(sum, "USD");
		assertEquals(Money.dollar(15), result);
	}

	public void testSumTimes(){
		Expression fiveBucks = Money.dollar(5);
		Expression tenFrancs = Money.franc(10);
		Bank bank = new Bank();
		bank.addRate("CHF", "USD", 2);
		Expression sum = new Sum(fiveBucks, tenFrancs).times(2);
		Money result = bank.reduce(sum, "USD");
		assertEquals(Money.dollar(20), result);
	}

	/*
	//最後に削除されてる
	public void testPlusSameCurrencyReturnsMoney(){
		Expression sum = Money.dollar(1).plus(Money.dollar(1));
		assertTrue(sum instanceof Money);
	}
	*/
}

Money.java

public class Money implements Expression{
	protected int amount;
	protected String currency;
	
	Money(int amount, String currency){
		this.amount = amount;
		this.currency = currency;
	}
	
	public boolean equals(Object object){
		Money money = (Money) object;
		return amount == money.amount
			&& currency().equals(money.currency());
	}
	
	static Money dollar(int amount){
		return new Money(amount, "USD");
	}
	
	static Money franc(int amount) {
		return new Money(amount, "CHF");
	}

	public Expression times(int multiplier){
		return new Money(amount * multiplier, currency);
	}
	
	String currency(){
		return currency;
	}
	
	public String toString(){
		return amount + " " + currency;
	}

	public Expression plus(Expression addend) {
		// TODO Auto-generated method stub
		return new Sum(this, addend);
	}
	
	public Money reduce(Bank bank, String to){
		int rate = bank.rate(currency, to);
		return new Money(amount / rate, to);
	}
}

Expression.java

interface Expression {
	Money reduce(Bank bank, String to);

	Expression plus(Expression addend);

	Expression times(int multiplier);
}

Bank.java

import java.util.*;
class Bank {

	public Money reduce(Expression source, String to) {
		// TODO Auto-generated method stub
		return source.reduce(this, to);
	}

	public void addRate(String from, String to, int rate) {
		// TODO Auto-generated method stub
		rates.put(new Pair(from, to), new Integer(rate));
	}
	
	int rate(String from, String to){
		if(from.equals(to)) return 1;
		Integer rate = (Integer) rates.get(new Pair(from, to));
		return rate.intValue();
	}
	
	private Hashtable rates = new Hashtable();
}

Sum.java

public class Sum implements Expression{
	Expression augend;
	Expression addend;

	Sum(Expression augend, Expression addend) {
		// TODO Auto-generated constructor stub
		this.augend = augend;
		this.addend = addend;
	}

	public Money reduce(Bank bank, String to) {
		// TODO Auto-generated method stub
		int amount = augend.reduce(bank, to).amount + addend.reduce(bank, to).amount;
		return new Money(amount, to);
	}

	public Expression plus(Expression addend) {
		// TODO Auto-generated method stub
		return new Sum(this, addend);
	}

	public Expression times(int multiplier) {
		// TODO Auto-generated method stub
		return new Sum(augend.times(multiplier), addend.times(multiplier));
	}
}

Pair.java

public class Pair {

	private String from;
	private String to;
	
	Pair(String from, String to){
		this.from = from;
		this.to = to;
	}
	
	public boolean equals(Object object){
		Pair pair = (Pair) object;
		return from.equals(pair.from) && to.equals(pair.to);
	}
	
	public int hashCode(){
		return 0;
	}
}