Bagian 14. Konversi Sungguhan

$5 + Rp 10=Rp 9.010 jika $1=Rp 9000

Rp 10 + Rp 10=Rp 20

Di bagian 12 kita telah membuat test untuk penjumlahan. Sayangnya, agar test green kita menempuh jalur implementasi bohongan. Kemudian di bagian 13 kita memperbaiki implementasi bohongan tadi dengan implementasi sungguhan. Namun, sampai bagian ini kita baru berhasil menjumlahkan dua uang dengan matauang yang sama. Nah dibaigian 14 ini kita akan mencoba membuat implementasi agar dua uang dengan matauang berbeda bisa kita jumlahkan.

Pertama kita harus membuat test penjumlahan dua uang dengan matauang berbeda,

[Test] 
public void HasilTukarMoneyBedaCurrency(){ 
	Bank bank=new Bank(); 
	bank.AddRate("Rp","US",9000); 
	Money hasilTukar=bank.Tukar(Money.Rp(9000),"US"); 
	Assert.AreEqual(Money.US(1),hasilTukar); 
}

Idenya adalah bank tahu nilai tukar (rate). Jadi ketika saya ingin menukar uang 9000 rupiah ke Dollar, maka saya harus pergi ke Bank dan mendapatkan kembalian dalam bentuk dollar. Berapa nilai rupiah terhadap dollar disebut nilai tukar atau rate. Dalam test ini kita memberi nilai tukar Rp terhadap dollar: 9000:1, yang berarti 9000 rupiah sama dengan 1 dollar. Perbandingan ini kemudian saya test, apakah benar 9000 rupiah sama dengan 1 dollar.

Method AddRate tidak ditemukan oleh kompiler, karena memang belum kita berikan. Agar bisa dikompilasi kita berikan saja implementasi kosong.

public class Bank{ 
	...
	public void AddRate(string from, string to,int rate){ 
		 
	} 
}

Setelah berhasil dikompilasi, test kemudian kita jalankan, hasilnya seperti yang kita harapkan:RED. Pesan kesalahan yang muncul adalah “diharapkan 1US tapi yang muncul 9000 Rp”. Untuk membuat test ini menjadi green, kita harus melakukan langkah:”make it right”.

Implementasi stub yang paling mudah agar test ini berubah menjadi green adalah dengan mengkonversi langsung pada saat method Tukar() di class Money dipanggil,

public  class Money:IEkspression{ 
	...
	public Money Tukar(string ke){ 
		int rate=(this.Currency.Equals("Rp") && ke.Equals("US"))?9000:1; 
		return new Money(this.m_amount/rate,ke); 
	} 
}

Langkah selanjutnya setelah test menjadi green adalah menghapus duplikasi. Kita menemukan duplikasi data di sini, didalam test dan didalam Money yaitu nilai rate yang 9000:1. Trus apa yang mesti kita lakukan? Pertama kita harus buat sedemikian hingga bank adalah satu-satunya object yang tahu berapa nilai tukar. Maka, jika kita ingin konversi tetap dilakukan di dalam class Money, bank harus kita kirim ke class Money sebagai parameter.

public class Bank{ 
	public Money Tukar(IEkspression ekspresi, string tukarKe){ 
		return ekspresi.Tukar(this,tukarKe); 
	} 
	...
}

Sehingga interface dari IEkspression harus kita ubah menjadi,

public interface IEkspression{ 
	Money Tukar(Bank bank,string ke); 
}

Bank kita passing sebagai parameter. Karena IEkspression berubah maka class-class yang mengimplementasikan juga harus kita ubah,

public class Sum:IEkspression{ 
	...
	public Money Tukar(Bank bank,string ke){ 
		int amount=this.Tertambah.Amount+this.Penambah.Amount; 
		return new Money(amount,ke); 
	} 
}

dan class Money,

public  class Money:IEkspression{ 
	... 
	public Money Tukar(Bank bank,string ke){ 
		int rate=(this.Currency.Equals("Rp") && ke.Equals("US"))?9000:1; 
		return new Money(this.m_amount/rate,ke); 
	} 
}

Test tetap green. Nah sekarang kita mencoba untuk menghilangkan duplikasi rate. Pertama, kita pindahkan konversi currency ke bank dengan memperkenalkan method baru GetRate(), kemudian kita panggil di Money.

public class Bank{ 
	...
	public int GetRate(string from, string to){ 
		return (from.Equals("Rp") && to.Equals("US"))?9000:1; 
	} 
}

dan kita panggil di method Money,

public  class Money:IEkspression{ 
	...
	public Money Tukar(Bank bank,string ke){ 
		int rate=bank.GetRate(this.m_currency,ke); 
		return new Money(this.m_amount/rate,ke); 
	} 
}

Bank memiliki daftar nilai tukar. Daftar ini kita akan letakkan dalam sebuah hashtable untuk menghindari duplikasi. Hashtable memerlukan key. Nah, key bisa kita buat dari gabungan antara dua currency. Tentu saja key harus value object. Untuk itu kita harus membuat test yang menguji apakah key1=key1.

[Test] 
public void Key1EqualsKey1(){ 
	RateKey key1=new RateKey("Rp","US"); 
	RateKey key2=new RateKey("Rp","US"); 
	Assert.AreEqual(key1,key2); 
}

Test ini hasilnya Red, seperti yang kita harapkan. Key1 tidak sama dengan Key2. Agar test ini pass/green, kita harus mengoverride equality.

public class RateKey{ 
	private string m_fromKey; 
	private string m_toKey; 
	public RateKey(string fromKey, string toKey){ 
		this.m_fromKey=fromKey; 
		this.m_toKey=toKey; 
	} 
	public override bool Equals(object obj){ 
		if(!(obj is RateKey)) return false; 
		RateKey key=(RateKey)obj; 
		return this.m_fromKey.Equals(key.m_fromKey) && this.m_toKey.Equals(key.m_toKey); 
	} 
	public override int GetHashCode(){ 
		return this.m_fromKey.GetHashCode()+this.m_toKey.GetHashCode(); 
	}
}

Ada dua method yang harus kita override, Equals() dan GetHashCode(). Dalam method Equals() kita harus periksa terlebih dahulu apakah objectnya sama atau tidak, jika tidak maka kita return false. Setelah itu baru kita bandingkan apakah kedua currency sama atau tidak. Sementara itu untuk GetHasCode cukup kita jumlahkan saja nilai hashcode masing-masing currency.

Dengan implementasi ini, kembali test kita menjadi green. Sekarang kita akan melakukan test terhadap method GetRate() dari bank,

[Test] 
public void BankGetRate(){ 
	Bank bank=new Bank(); 
	bank.AddRate("Rp","US",9000); 
	Assert.AreEqual(9000,bank.GetRate("Rp","US")); 
}

Ternyata test ini green. Kita bisa melakukan triangulation untuk membuktikan kebenarannya, tetapi setelah saya cek ke dalam class Bank, saya menemukan duplikasi data. Jadi lebih baik kita mencoba untuk menghapus duplikasi ini.
Method GetRate() dalam class Bank sebaiknya kita buat melakukan look-up ke dalam hashtable.

public class Bank{ 
	...
	public int GetRate(string from, string to){ 
		RateKey key=new RateKey(from,to); 
		return getRate(key); 
	} 
}

Jadi pertama-tama kita buat key kemudian dengan key itu kita look-up kedalam tabel,

public class Bank{ 
	...
	private int getRate(RateKey key){ 
		return 1; 
	} 
}

Disini saya sengaja mereturn 1, agar test kita menjadi red. Implementasi termudah agar test menjadi green adalah dengan implementasi bohongan yaitu dengan mereturn 9000. Karena saya merasa yakin bisa menyelesaikan ini dengan cepat, maka saya akan menempuh jalur implementasi sungguhan. Saya akan buat tabelnya yaitu hashtable, kemudian method AddRate saya perbaiki.

Pertama saya definisikan table sebagai Idictionary,

public class Bank{ 
	private IDictionary m_rateTable=new Hashtable(); 
	...
}

kemudian method AddRate saya ubah menjadi

public class Bank{ 
	..
	public void AddRate(string from, string to,int rate){ 
		this.m_rateTable.Add(new RateKey(from,to),rate); 
	} 
	...
}

kemudian saya definiksan method untuk mengambilnya dari tabel,

public class Bank{ 
	...
	private int getRate(RateKey key){ 
		return (int)this.m_rateTable[key]; 
	} 
}

Test yang saya maksudkan pass, tetapi satu test HasilTukarDariMoney red. Apa yang terjadi, kita harus menfix-kan segera. Test yang break ini melakukan konversi 1 rupiah ke 1 rupiah. Pesan yang muncul adalah “Object reference not set”. Pesan ini menandakan rate yang tidak ditemukan. Kita harus membuat sesuatu yang lebih cerdas disini. Rp:Rp haruslah tetap 1:1, ini berlaku untuk semua mata uang yang sama.

Agar test ini berubah menjadi green, kita akan uji jika matauang sama kita kembalikan nilai 1,

public class Bank{ 
	...
	public int GetRate(string from, string to){ 
		if(from.Equals(to)) return 1; 
		RateKey key=new RateKey(from,to); 
		return getRate(key); 
	} 
}

Test all green.

Iklan

There are no comments on this post.

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: