Refactor apa sih itu?

Jeffry Dane
temancatat
Published in
2 min readApr 17, 2018

Refactoring biasanya dimotivasi karena adanya implementasi kode yang bisa dibilang ‘bad code’. Kode yang seperti itu bisa dibilang karena implementasi yang sangat panjang, terdapat duplikat, sulit dibaca, tidak intuitif, dsb.

Refactoring akan mengubah kode sumber tersebut menjadi bentuk baru yang berperilaku sama seperti sebelumnya tetapi itu tidak lagi memiliki kendala-kendala tersebut. Untuk rutinitas yang panjang, satu atau beberapa subrutin yang lebih kecil dapat diekstrak, untuk rangkap ulangan, duplikasi dapat dihapus dan diganti dengan satu fungsi bersama, atau menggunakan fungsi / struktur lain.

Secara umum refactoring dalam TDD dilakukan setelah membuat unit test dan sudah [GREEN]. Hal ini dikarenakan kita akan mengubah implementasi yang sudah kita buat sebelumnya ke bentuk yang lebih baik, namun masih menghasilkan sesuatu yang sama pada awalnya, lulus unit test yang sama.

Pengalaman refactoring yang saya alami mungkin karena kurangnya pengalaman menggunakan berbagai fungsi dokumentasi Java. Disini saya membuat sebuah fungsi yang mengubah sebuah format Calendar ke bentuk yang lebih terbaca dan berbahasa Indonesia. Kira-kira berbentuk seperti ini unit test-nya

@Before
public void setup() {
calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2018);
calendar.set(Calendar.MONTH, Calendar.JANUARY);
calendar.set(Calendar.DAY_OF_MONTH, 30);
expectedDMYBahasa = "30 Januari 2018";
}
@Test
public void testFormatToDMY(){
assertTrue(DateUtil.formatToDMY(calendar.getTime()).equals(expectedDMYBahasa));
}

Dengan implementasi:

private static final String DMY_FORMAT = "dd MM yyyy";private static final String[] BULAN = {"Desember", "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"};public static String formatToDMY(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat(DMY_FORMAT, Locale.US);
return translateMonthToBahasa(sdf.format(date), 1);
}public static String translateMonthToBahasa(String date, int monthIndex) {
String[] parts = date.split(" ");
parts[monthIndex] = BULAN[Integer.parseInt(parts[monthIndex]) % 12];
return parts[0] + " " + parts[1] + " " + parts[2];
}

Terkesan memaksa apalagi dengan adanya method translateMonthToBahasa yang memiliki parameter monthIndex yang dipergunakan untuk mengetahui bagian mana yang merupakan Bulan. Hal ini dikarenakan “sdf.format(date)” mengembalikan sesuatu seperti “30 01 2018” (perhatikan DMY_FORMAT) dan saya ingin mengambil “01” untuk mengakses BULAN[1] yang merupakan “Januari” sehingga keluarannya menjadi “30 Januari 2018”

Singkat cerita setelah di code review dan diberikan masukan bahwa metode sebelumnya sangatlah tidak elegan, saya mulai mencoba cara lain untuk memperindah kode yang memang terkesan memaksa tersebut dan menghasilkan kode yang kira-kira seperti berikut ini:

private static final String DMY_FORMAT = "dd MMMM yyyy";private static final String[] BULAN = {"Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"};public static String formatToDMY(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat(DMY_FORMAT, Locale.US);
return sdf.format(date).replaceFirst("[^\\d ]+" , BULAN[date.getMonth()]);
}

Jadi di sini “sdf.format(date)” akan mengembalikan sesuatu seperti “30 January 2018” (perhatikan DMY_FORMAT), lalu dengan metode “.replaceFirst” saya cari String yang merupakan letter (Alpabhet saja) dan diganti dengan BULAN[date.getMonth()] dimana date.getMonth() mengembalikan 0 untuk January. Jadi disini “January” akan diganti dengan BULAN[0] yaitu “Januari” sehingga keluarannya menjadi “30 Januari 2018”

Dalam pergantian implementasi formatToDMY ini, unit test sebelumnya tidak perlu diganti karena tujuan awalnya hanya menganti alur prosesnya, tidak mengubah luaran yang dihasilkan.

--

--