You are on page 1of 13

Tugas Kelompok ke-2

Minggu ke-5 Sesi 7


Dari coding java untuk tes cetak report berikut:
a. Cari 4 tipe code smell and jelaskan!
b. Lakukan refactor untuk memperbaiki code smell tersebut!

1. import java.util.Random;
2. import java.util.Vector;
3.
4. public class MainSystem {
5.
6. public static void main(String[] args) {
7. String [] it = {"Sandal xl","Sandal l","Sandal v", "Shoes xl","Shoes l", "Shoes v"};
8. int [] pt = {100, 90, 80, 200, 190, 185};
9. int [] hp = {1200, 1150, 1100, 2500, 2300, 2200};
10. int [] m = {1, 1, 2, 3, 3, 4, 5};
11. Random r = new Random(232);
12. Report report = new Report();
13. Transaction t = new Transaction(1, 2016);
14.
15. for(int i=0; i<it.length; i++)
16. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
17. report.AddTransaction(t);
18. t = new Transaction(2, 2016);
19. for(int i=0; i<it.length; i++)
20. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
21. report.AddTransaction(t);
22. t = new Transaction(3, 2016);
23. for(int i=0; i<it.length; i++)
24. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
25. report.AddTransaction(t);
26. t = new Transaction(4, 2016);
27. for(int i=0; i<it.length; i++)
28. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
29. report.AddTransaction(t);
30. t = new Transaction(5, 2016);
31. for(int i=0; i<it.length; i++)
32. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
33. report.AddTransaction(t);
34. t = new Transaction(6, 2016);
35. for(int i=0; i<it.length; i++)
36. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
37. report.AddTransaction(t);
38. t = new Transaction(7, 2016);
39. for(int i=0; i<it.length; i++)
40. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
41. report.AddTransaction(t);
42. t = new Transaction(8, 2016);
43. for(int i=0; i<it.length; i++)
44. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
45. report.AddTransaction(t);
46. t = new Transaction(9, 2016);
47. for(int i=0; i<it.length; i++)
48. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
49. report.AddTransaction(t);
50. t = new Transaction(10, 2016);
51. for(int i=0; i<it.length; i++)
52. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
53. report.AddTransaction(t);
54. t = new Transaction(11, 2016);

COMP6284 – Code Reengineering


55. for(int i=0; i<it.length; i++)
56. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
57. report.AddTransaction(t);
58. t = new Transaction(12, 2016);
59. for(int i=0; i<it.length; i++)
60. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
61. report.AddTransaction(t);
62. t = new Transaction(1, 2017);
63. for(int i=0; i<it.length; i++)
64. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
65. report.AddTransaction(t);
66. t = new Transaction(2, 2017);
67. for(int i=0; i<it.length; i++)
68. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
69. report.AddTransaction(t);
70. t = new Transaction(3, 2017);
71. for(int i=0; i<it.length; i++)
72. t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
73. report.AddTransaction(t);
74.
75. report.printTransaction(1, 2016, 3, 2016);
76. report.printTransaction(3, 2016, 12, 2016);
77. report.printTransaction(5, 2016, 1, 2017);
78. }
79.
80. }
81.
82. class Item {
83. private String name;
84. private int price;
85. private int quantity;
86. private int highSeasonPrice;
87. private final int HIGH_SEASON_START = 5;
88. private final int HIGH_SEASON_END = 8;
89.
90. public Item(String name, int price, int highSeasonPrice, int quantity) {
91. this.name = name;
92. this.price = price;
93. this.highSeasonPrice = highSeasonPrice;
94. this.quantity = quantity;
95. }
96. public String getName() {
97. return name;
98. }
99.
100. public int getPrice(int currentMonth, int quantity) {
101. int price;
102. if(currentMonth >= HIGH_SEASON_START && currentMonth <= HIGH_SEASON_END)
103. price = highSeasonPrice * quantity;
104. else price = this.price * quantity;
105. return moreThanFiveThousand(price)?(price - 100): price;
106. }
107. public int getQuantity() {
108. return quantity;
109. }
110.
111. private boolean moreThanFiveThousand(int price) {
112. return price > 5000;
113. }
114. }
115.
116. class Transaction {
117. private Vector<Item> items = new Vector<>();
118. private int month;
119. private int year;

COMP6284 – Code Reengineering


120. public Transaction(int month, int year) {
121. this.month= month;
122. this.year = year;
123. }
124. public Vector<Item> getItems() {
125. return items;
126. }
127. public int getMonth() {
128. return month;
129. }
130. public int getYear() {
131. return year;
132. }
133. public void addItem(Item item) {
134. items.add(item);
135. }
136. public int getTotalPrice(){
137. int total = 0;
138. for(Item e:items) {
139. total += e.getPrice(this.month, e.getQuantity());
140. }
141. return total;
142. }
143. }
144.
145. class Month {
146. private String[] months =
{"January","February","March","April","May","June","July","August","September","October","November","December"};
147. protected int month;
148. public String getText() {
149. return months[month - 1];
150. }
151. }
152.
153. class Report extends Month {
154. private Vector<Transaction> transactions = new Vector<>();
155. public void AddTransaction(Transaction tran){
156. transactions.add(tran);
157. }
158.
159. public int getTotalFor(int monthStart, int yearStart, int monthEnd, int yearEnd){
160. int sum = 0;
161. for(Transaction t: transactions)
162. if( (yearStart*100+monthStart) <= (t.getYear()*100+t.getMonth()) &&
(t.getYear()*100+t.getMonth()) <= (yearEnd*100+monthEnd) )
163. sum += t.getTotalPrice();
164. return sum;
165. }
166.
167. public void printTransaction(int monthStart, int yearStart, int monthEnd, int yearEnd) {
168.
169.
170. System.out.println("=================================================");
171. month = monthStart;
172. System.out.print("Report from " + getText() + " " + yearStart + " to ");
173. month = monthEnd;
174. System.out.println(getText() + " " + yearEnd);
175. System.out.println("=================================================");
176. int total = 0;
177. for(int year=yearStart; year<=yearEnd; year++) {
178. int me = year < yearEnd ? 12 : monthEnd;
179. int ms = year == yearStart ? monthStart : 1;
180. for(int m=ms; m<=me; m++) {
181. month = m;

COMP6284 – Code Reengineering


182. System.out.format("Year %d Month %-10s : %,15d\n", year, getText(),
getTotalFor(m, year, m, year));
183. total += getTotalFor(m, year, m, year);
184. }
185. }
186. System.out.println("=================================================");
187. System.out.format("Total Transaction = %,15d\n", total);
188. System.out.println("=================================================");
189. }
190. }

COMP6284 – Code Reengineering


Jawab

1. tipe code smell yaitu,


a. The Bloater
The bloater menunjukan sesuatu yang berkembang terlalu besar sehingga tidak
dapat ditangani secara efisien. Sesuatu tersebut dapat berupa metode yang terlalu
panjang, kelas yang terlalu besar, daftar parameter yang terlalu banyak, penggunaan
data primitive yang berlebihan, ataupun penggunaan data clumps. Berikut adalah
jenis jenis code smell dari kelompok the Bloater :
 Long Method: Method yang isinya sangat banyak.
 Large Class: Class yang isinya sangat banyak.
 Primitive Obsession: Tidak membuat class tersendiri untuk tipe data yang
bisa dienkapsulasi ke dalam sebuah class. Misalnya menyimpan nilai uang
ke dalam BigDecimal, sehingga operasi konversi kurs mata uang harus
diletakkan di class lain. Akan lebih ideal bila terdapat class Uang sehingga
nilai ulang beserta operasi konversi kurs bisa diletakkan di class ini.
 Long Parameter List: Terdapat parameter dengan jumlah banyak.
 DataClump: Beberapa data yang berbeda tapi sering kali dipakai bersamaan,
misalnya variabel “mulai” dan variabel “selesai“.

b. The Object Orientation Abuser


Penentu umum dari “smell” pada Object Orientation Abuser adalah penerapan
konsep object oriented yang tidak diterapkan secara penuh. Seperti penggunaan
operator switch yang banyak dan kompleks ataupun penggunaan operator if yang
banyak dan berurut, yang seharusnya dapat digantikan dengan penerapan konsep
object oriented. Penggunaan field sementara juga dapat menjadi indikasi bahwa
field tersebut sebaiknya dideklarasikan dalam sebuah metode, bukan dalam ruang
lingkup kelas. Berikut adalah jenis-jenis code smell dari kelompok Object
Orientation Abuser :

COMP6284 – Code Reengineering


 witch Statements: Penggunaan switch dapat diganti dengan inheritance di
OOP.
 Temporary Field: Sebuah variabel yang memiliki scope lebih luas tetapi
hanya dipakai sementara oleh method, bukan untuk pertukaran data bagi
method lainnya.
 Refused Bequest: Class yang tidak ingin memakai methods dari superclass-
nya.
 Alternative Classes with Different Interfaces:: Dua buah class yang berbeda
memiliki isi yang sangat mirip tetapi mereka mengimplementasikan dua
interface yang berbeda.

c. The Change Preventer


Changer Preventer merupakan smell yang mencegah/mempersulit terjadinya
perubahan pada aplikasi atau untuk kebutuhan perubahan dimasa yang akan datang.
Pada suatu kondisi, sebuah perubahan membutuhkan modifikasi yang terlalu
banyak pada sebuah kelas.Sedangkan pada kondisi lain, sebuah perubahan kecil
mempengaruhi terlalu banyak kelas yang harus dimodifikasi. Kedua kondisi
tersebut menyebabkan kesulitan yang tinggi dalam melakuan perubahan sistem
yang dibutuhkan. Berikut adalah jenis-jenis code smell dari kelompok Change
Preventer :
 Divergent Change: Kebalikan dari Shotgun Surgery, dimana developer
sering mengubah class yang sama untuk beberapa hal yang berbeda.
 Parallel Inheritance Hierarchies: Setiap kali membuat subclass dari sebuah
class, wajib membuat subclass baru dari class lainnya. Misalnya, setiap kali
membuat subclass dari Model bernama MahasiswaModel, wajib harus
membuat subclass dari Presenter bernama MahasiswaPresenter.

d. The Dispensable
Hal umum yang ada pada semua dispensable smell adalah adanya sesuatu yang
tidak dibutuhkan dan seharusnya dapat dihapus dari source code. Berikut adalah
contoh code smell dari kelompok the Dispensable :

COMP6284 – Code Reengineering


 Lazy Class: Class yang tidak berguna atau tidak cukup bermanfaat.
 Data Class: Class yang hanya berisi atribut (data) dan tidak memiliki
method (operasi).
 Duplicate Code: Kode program yang terduplikasi.
 ead Code: Kode program yang tidak dipakai lagi.
 Speculative Generality: Kode program yang dibuat dengan memikirkan
perubahan di masa depan, tetapi bagian tersebut tidak terpakai sama sekali.

e. The Coupler
The coupler merupakan kondisi dimana terdapat pelanggaran terhadap prinsip
coupling. Coupling merupakan ukuran keterikatan sebuah module dengan module
lainnya. Prinsip coupling menekankan pada penerapan low coupling, sehingga
perubahan pada satu module tidak akan (atau sedikit) mempengaruhi module
lainnya. Salah satu kondisi pelanggaran prinsip coupling adalah dimana sebuah
metode mengakses data dari object lainnya lebih sering dibandingkan data dari
dalam kelas itu sendiri. Penggunaan middle man juga merupakan indikasi
pelanggaran dari prinsip low coupling. Berikut adalah jenis jenis code smell dari
kelompok the Coupler :
 Feature Envy: Sebuah method sangat bergantung pada data yang ada di class
lain, bukan di data milik class tempat method tersebut berada.
 Inappropriate Intimacy: Dua class yang terlalu berhubungan erat satu sama
lainnya.
 Message Chains: Untuk mendapat data, class A harus memanggil class B
yang kemudian memanggil class C lalu mengambil data dari class D;
padahal yang dibutuhkan hanya data dari class D.
 Middle Man: Sebuah class yang fungsinya terlalu sederhana dan tidak
memiliki kontribusi selain hanya mendelegasikan tugasnya ke class lain.

COMP6284 – Code Reengineering


2. Dari source code tersebut terdapat beberapa code smell, diantaranya yaitu code smell long
method, duplicate code, dead code, dan feature envy. Berikut hasil refactoring dari tim kami,

import java.util.Random;
import java.util.Vector;

public class MainSystem {

public static void main(String[] args) {


report();

private static Report report() {


String[] it = { "Sandal xl", "Sandal l", "Sandal v", "Shoes xl",
"Shoes l", "Shoes v" };
int[] pt = { 100, 90, 80, 200, 190, 185 };
int[] hp = { 1200, 1150, 1100, 2500, 2300, 2200 };
Random r = new Random(232);
Report report = new Report();
Transaction t = new Transaction(1, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(2, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(3, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(4, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(5, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(6, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(7, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}

COMP6284 – Code Reengineering


report.AddTransaction(t);
t = new Transaction(8, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(9, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(10, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(11, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(12, 2016);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(1, 2017);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(2, 2017);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
t = new Transaction(3, 2017);
for (int i = 0; i < it.length; i++) {
t.addItem(new Item(it[i], pt[i], hp[i], r.nextInt(500) + 1));
}
report.AddTransaction(t);
report.printTransaction(1, 2016, 3, 2016);
report.printTransaction(3, 2016, 12, 2016);
report.printTransaction(5, 2016, 1, 2017);
return report;
}

class Item {
private String name;
private int price;
private int quantity;
private int highSeasonPrice;
private final int HIGH_SEASON_START = 5;

COMP6284 – Code Reengineering


private final int HIGH_SEASON_END = 8;

public Item(String name, int price, int highSeasonPrice, int quantity) {


this.name = name;
this.price = price;
this.highSeasonPrice = highSeasonPrice;
this.quantity = quantity;
}
public String getName() {
return name;
}

public int getPrice(int currentMonth, int quantity) {


int price;
if(currentMonth >= HIGH_SEASON_START && currentMonth <=
HIGH_SEASON_END)
price = highSeasonPrice * quantity;
else price = this.price * quantity;
return moreThanFiveThousand(price)?(price - 100): price;
}
public int getQuantity() {
return quantity;
}

private boolean moreThanFiveThousand(int price) {


return price > 5000;
}
}

class Transaction {
private Vector<Item> items = new Vector<>();
private int month;
private int year;
public Transaction(int month, int year) {
this.month= month;
this.year = year;
}
public Vector<Item> getItems() {
return items;
}
public int getMonth() {
return month;
}
public int getYear() {
return year;
}
public void addItem(Item item) {
items.add(item);
}
public int getTotalPrice(){
int total = 0;
for(Item e:items) {
total += e.getPrice(this.month, e.getQuantity());
}
return total;

COMP6284 – Code Reengineering


}
}

class Month {
private String[] months =
{"January","February","March","April","May","June","July","August","Septembe
r","October","November","December"};
protected int month;
public String getText() {
return months[month - 1];
}
}

class Report extends Month {


private Vector<Transaction> transactions = new Vector<>();
public void AddTransaction(Transaction tran){
transactions.add(tran);
}

public int getTotalFor(int monthStart, int yearStart, int monthEnd, int


yearEnd){
int sum = 0;
for(Transaction t: transactions)
if( (yearStart*100+monthStart) <= (t.getYear()*100+t.getMonth())
&& (t.getYear()*100+t.getMonth()) <= (yearEnd*100+monthEnd) )
sum += t.getTotalPrice();
return sum;
}

public void printTransaction(int monthStart, int yearStart, int


monthEnd, int yearEnd) {

System.out.println("=================================================");
month = monthStart;
System.out.print("Report from " + getText() + " " + yearStart + " to
");
month = monthEnd;
System.out.println(getText() + " " + yearEnd);

System.out.println("=================================================");
int total = total(monthStart, yearStart, monthEnd, yearEnd);

System.out.println("=================================================");
System.out.format("Total Transaction = %,15d\n", total);

System.out.println("=================================================");
}

private int total(int monthStart, int yearStart, int monthEnd, int


yearEnd) {
int total = 0;
for (int year = yearStart; year <= yearEnd; year++) {
int me = year < yearEnd ? 12 : monthEnd;

COMP6284 – Code Reengineering


int ms = year == yearStart ? monthStart : 1;
for (int m = ms; m <= me; m++) {
month = m;
System.out.format("Year %d Month %-10s : %,15d\n", year,
getText(), getTotalFor(m, year, m, year));
total += getTotalFor(m, year, m, year);
}
}
return total;
}
}

COMP6284 – Code Reengineering


Sumber :

 https://thesolidsnake.wordpress.com/2013/05/03/belajar-mencium-bau-nya-kode-
program-code-smell/
 https://www.altexsoft.com/blog/engineering/code-refactoring-best-practices-
when-and-when-not-to-do-it/
 https://dzone.com/articles/smells-in-java-code-do-you-recognize-them
 https://dzone.com/articles/staring-into-my-java-crystal-ball-2020
 https://refactoring.guru/refactoring/smells
 Eclipse – workspace
 Intellij IDEA
 Lecture Note

COMP6284 – Code Reengineering

You might also like