Studi Kasus: Ekspresi Penjumlahan (7)

Ekspresi Penjumlahan

5+2+4-3+10-2=?

Konversi string 1 ke object Satu.

Konversi string 2 ke object Dua.

Konversi string 3 ke object Tiga.

…dst sampai Sembilan.

Object puluhan

Value dalam komposisi puluhan

Object ratusan

Object penjumlahan

Eksepsi jika tidak ada ekspresi yang bersesuaian

Ekspresi penjumlahan adalah “+”. Ekspresi ini merupakan komposisi dua ekspresi, satu sebagai tambahan dan yang satu sebagai yang ditambah, yang bisa kita nyatakan sebagai:”x + y”.

Sebelum kita membuat konversi ekspresi penjumlahan, kita harus membuat komposisi penjumlahan. Komposisi ini saya sebut sebagai komposisi Plus.

Berikut ini adalah test untuk komposisi Plus,

[Test] 
public void KomposisiPlus() 
{ 
	IExpression puluhan=Number.CreateNewNumber("2"); 
	IExpression satuan=Number.CreateNewNumber("0"); 
	IExpression asal=new Puluhan(puluhan,satuan); 
	IExpression tambahan=Number.CreateNewNumber("0"); 
	IExpression plus=new Plus(asal, tambahan); 
	Assert.AreEqual("20 + 0",plus.Expression); 
	Assert.AreEqual(20,plus.Value); 
}

Komposisi ini terbuat dari 20 dan 0 yang masing-masing dinyatakan dengan komposisi Puluhan dan Number 0. Komposisi puluhan terbuat dari Numer 2 dan Number 0. Kesemuanya adalah ekspresi.

Agar test bisa berjalan kita harus membuat class Plus,

public class Plus:IExpression 
{ 
	private IExpression m_asal; 
	private IExpression m_tambahan; 
	public Plus(IExpression asal, IExpression tambahan) 
	{ 
		this.m_asal= asal; 
		this.m_tambahan = tambahan; 
	} 
	public string Expression { 
		get { 
			return ""; 
		} 
	} 
	public object Value { 
		get { 
			return 0; 
		} 
	} 
}

Konstruktor dari class Plus berparameter dua buah ekspresi number, yang satu sebagai nilai awal dan yang kedua sebagai nilai tambah. Test diatas masih memberi keluaran red. Namun demikian implementasi keduanya adalah sangat jelas. Untuk property Expression kita cukup menggabungkan ekspresi pembentuknya dan untuk Value kita juga cukup menjumlahkan kedua value dari ekspresi pembentuknya.

public class Plus:IExpression 
{ 
		
	public string Expression { 
		get { 
			return String.Format("{0} + {1}",this.m_asal.Expression,this.m_tambahan.Expression); 
		} 
	} 
	public object Value { 
		get { 
			return (int)this.m_asal.Value + (int)this.m_tambahan.Value; 
		} 
	} 
}

Implementasi sederhana yang cukup membuat test kita menjadi green.

Sekarang kita buat konversi ekspresi plus. Berikut ini adalah test konversi “1 + 1” ke object Plus.

[Test] 
public void Ekspresiplus(){ 
	string input="1 + 1"; 
	IExpressionConverter exConverter=new ExpressionConverter(); 
	IExpression ex=exConverter.Convert(input); 
	Assert.AreEqual("1 + 1",ex.Expression); 
	Assert.AreEqual(2,ex.Value); 
}

Jika test kita jalankan, kita akan menetapkan pesan bahwa ekspresi “1 + 1” tidak disupport. Jadi, apa yang akan kita lakukan? Tidak ada implementasi yang jelas yang langsung bisa kita implementasikan.

Saya punya usul. Ekspresi ini kita pecah-pecah menurut komponennya, ada 3 komponen. Ekspresi 1, komposisi Plus dan ekspresi 1. Ekspresi 1 + 1, kita masukkan dulu kedalam array, kemudian kita baca baris demi baris, jika ketemu 1 buat ekspresi 1 dan jika ketemu + buat ekspresi plus.

Kita berikan implementasi konstant dulu,

public IExpression Convert (string ekspresi) 
{ 
	if(ekspresi.Length==1) 
		return Number.CreateNewNumber(ekspresi); 
	else if (ekspresi.Length == 2) 
	{ 
		char[] exs=ekspresi.ToCharArray(); 
		IExpression puluhan=Number.CreateNewNumber(exs[0].ToString()); 
		IExpression satuan=Number.CreateNewNumber(exs[1].ToString()); 
		return new Puluhan(puluhan,satuan); 
	} 
	else if(ekspresi.Equals("1 + 1")) 
	    return Number.CreateNewNumber("1") ; 
	else 
		throw new ApplicationException(string.Format("Expression {0} not supported",ekspresi)); 
}

Perhatikan statement “else if(ekspresi.Equals(“1 + 1”)) ”, saya berikan implementasi konstan disini. Dan ini langsung menimbulkan duplikasi data, didalam test dan didalam program.

Agar test ini menjadi green, cara termudah adalah dengan memberikan impelemantasi Plus,

public IExpression Convert (string ekspresi) 
{ 
	if(ekspresi.Length==1) 
		return Number.CreateNewNumber(ekspresi); 
	else if (ekspresi.Length == 2) 
	{ 
		char[] exs=ekspresi.ToCharArray(); 
		IExpression puluhan=Number.CreateNewNumber(exs[0].ToString()); 
		IExpression satuan=Number.CreateNewNumber(exs[1].ToString()); 
		return new Puluhan(puluhan,satuan); 
	} 
	else if(ekspresi.Equals("1 + 1")) 
	    return new Plus(Number.CreateNewNumber("1"),Number.CreateNewNumber("1")); 
	else 
		throw new ApplicationException(string.Format("Expression {0} not supported",ekspresi)); 
}

Test kita sudah green. Langkah berikutnya kita harus bisa menghilangkan duplikasi. Kita pindahkan terlebih daulu new Plus() ke dalam method baru katakanlah method interpret.

	else if(ekspresi.Equals("1 + 1")) 
			    return interpret(ekspresi);

dan method interprete,

private IExpression interpret(string ekspresi) 
{ 
	return new Plus(Number.CreateNewNumber("1"),Number.CreateNewNumber("1")); 
}

kita tidak akan membatasi seberapa panjang ekspresi yang masuk, maka kita ubah jika panjang ekspresi lebih dari 2 eksekusi interpret,

public IExpression Convert (string ekspresi) 
{ 
	if(ekspresi.Length==1) 
		return Number.CreateNewNumber(ekspresi); 
	else if (ekspresi.Length == 2) 
	{ 
		char[] exs=ekspresi.ToCharArray(); 
		IExpression puluhan=Number.CreateNewNumber(exs[0].ToString()); 
		IExpression satuan=Number.CreateNewNumber(exs[1].ToString()); 
		return new Puluhan(puluhan,satuan); 
	} 
	else if(ekspresi.Length>2) 
	    return interpret(ekspresi); 
	else 
		throw new ApplicationException(string.Format("Expression {0} not supported",ekspresi)); 
}

Test tetap green.

Sekarang kita siap mengoprek interpret. Seperti ide kita semula, kita buat ekspresi masing-masing,

private IExpression interpret(string ekspresi) 
{ 
	IExpression exp1=getExp1(ekspresi); 
	IExpression exp2=getExp2(ekspresi); 
	return getOperator(ekspresi,exp1,exp2); 
}

Method getExp1 ditujukan untuk mengambil ekpresi pertama dari penjumlahan. Kemudian getExp2 ditujukan untuk menngambil ekspresi kedua penyusun penjumlahan. Sedangkan getOperator, diguanakan untuk mendapatkan operator apa, kebetulan saat ini penjumlahan.

Method getExp1,

private IExpression getExp1(string exs) 
{ 
	string[] splitedStr=exs.Split('+'); 
	string number= splitedStr[0].Trim(); 
	return Number.CreateNewNumber(number); 
}

Pertama-tama string ekspresi kita split berdasarkan karakter +, sementara kita abaikan kemungkinan operator lain. Hasil dari split ini adalah array string, str[0] =”1” dan str[2]=”1”. Dengan demikian ekspresi pertama adalah str[0]. Untuk menghilangkan white space kita panggil trim. Kemudian kita panggil Number.

Method getExp2,

private IExpression getExp2(string exs) 
{ 
	string[] splitedStr=exs.Split('+'); 
	string number= splitedStr[1].Trim(); 
	return Number.CreateNewNumber(number); 
}

Tidak berbeda dari getExp1, kecuali pada saat mengambil array. Disini kita ambil array yang ke dua. Ini kandidat untuk bisa kita satukan.

Dan getOperator,

private IExpression getOperator(string ekspresi,IExpression exp1, IExpression exp2) 
{ 
	string afterExp1=ekspresi.Substring(exp1.Expression.Length).Trim(); 
	string opr=afterExp1.Substring(0,1); 
	if(opr.Equals("+")){ 
		return new Plus(exp1,exp2); 
	}else 
		throw new ApplicationException(String.Format("Expression {0} not operator",opr)); 
}

Logikanya adalah kita ambil substring yang dimulai dari karakter setelah ekspresi pertama. Jadi untuk 1 + 1, substringnya adalah + 1. Setelah itu kita ambil karakter pertama dari substring. Kemudian kita uji karakter itu + atau bukan. Jika plus buat ekspresi plus, jika bukan keluarkan eksepsi.

Dengan cara ini test sudah green. Karena getExp1 dan getExp2 modelnya sama kita bisa satukan, yaitu dengan memanggil getExp. Sufix 1 dan 2 kita pertahankan. Penting sebagai tanda bahwa komposisi kita kesemuanya membutuhkan ekspresi 1 dan ekspresi 2.

private IExpression getExp(int oprNumber,string exs) 
{ 
	string[] splitedStr=exs.Split('+'); 
	if(splitedStr.Length <=oprNumber) 
		return Number.CreateNewNumber("0"); 
	string number= splitedStr&#91;oprNumber&#93;.Trim(); 
	return Number.CreateNewNumber(number); 
}
&#91;/sourcecode&#93;
	<p>Jika operator number yang kita inginkan ternyata lebih besar dari array yang ada kita return number '0'.</p>
	<p>Dan getExp1 dan getExp2 berubah menjadi,</p>

private IExpression getExp1(string exs) 
{ 
	return getExp(0,exs); 
} 
private IExpression getExp2(string exs) 
{ 
	return getExp(1,exs); 
}
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: