Refactoring Story — Extract Method

Andy Librian
Karena Kita Vidio
Published in
3 min readJul 26, 2018

Semakin panjang sebuah method, semakin sulit dipahami. Kode yang sulit dipahami adalah sumber masalah bagi sebuah tim software engineer.

Kode ditulis sekali, dibaca berulang kali

Seringkali kita harus menambahkan fitur baru di atas fitur yang sudah berjalan. Untuk melakukannya, mau tidak mau kita harus memahami cara kerja kode-kode yang berhubungan dengan fitur tersebut.

Jika kode yang akan kita ubah sulit untuk dipahami cara kerjanya, baik karena terlalu panjang, atau karena alur nya rumit, pasti kita akan kesulitan untuk melakukan perubahan tersebut.

Paman Bob pernah bilang, kode hanya ditulis sekali, tapi dibaca berulang kali. Jadi sudah semestinya saat kita menulis, kita mendesain supaya kode kita mudah dibaca.

“Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …[Therefore,] making it easy to read makes it easier to write.” — Robert C. Martin

Refactoring

Salah satu cara untuk memperbaiki kode adalah dengan melakukan refactoring, yaitu merapikan kode tanpa mengubah external-behavior-nya.

Tim Software Engineers di KMK menerapkan metodologi Extreme Programming, yaitu sebuah bentuk dari Agile process dan Refactoring termasuk salah satu prinsip yang dijalankan di Extreme Programming.

Contoh Kode

Di bawah ini ada contoh method yang panjang dengan alur yang rumit. Maksud dari method ini adalah untuk menandai sebuah Message (pada aplikasi chatting) sudah terbaca. Method ini akan coba kita refactor supaya lebih sederhana.

void ConversationManager::markMessageRead(
Message &message,
const bool sendReadReceipt = true
) {
// ... validasi, update database, dan sebagainya ...
if (!sendReadReceipt) {
return;
}
Conversation &conversation = message.getConversation(); // If this is not a group, use the old style read receipt.
if (!conversation.isGroup()) {
for (auto& message: readMessages) {
const participants = message.getParticipants();

// filter participants
// ... ~20 baris
auto readReceipt = ReadReceipt(message, participants);

// set read receipt properties
// ...
messenger.send(readReceipt, user, options); }
return;
} // send new style read receipt
for (auto& message: readMessages) {
const participants = message.getParticipants();

// filter participants
// ... ~20 baris
auto readReceipt2 = ReadReceipt2(message, participants); // set read receipt2 properties
// ...
messenger.send(readReceipt2, user, options); }}

Kode berikut ini,

    // If this is not a group, use the old style read receipt.  
if (!conversation.isGroup()) {
for (auto& message: readMessages) {
// ...
}
}

panjang dan susah diikuti, sampai butuh komentar untuk meringkasnya. Ini bisa kita extract menjadi method terpisah:

    if (!conversation.isGroup()) {
sendOldStyleReadReceipt(readMessages);
}

Lebih ringkas, lebih jelas. Bahkan kita tidak lagi butuh comment yang tadi karena nama method nya sudah mewakili.

Setelah dilakukan extract method, method yang panjang tadi sekarang jadi sederhana dan mudah diikuti alur nya.

void ConversationManager::markMessageRead(
Message &message,
const bool sendReadReceipt = true
) {
// ... validasi, update database, dan sebagainya ...
if (!sendReadReceipt) {
return;
}
Conversation &conversation = message.getConversation(); if (!conversation.isGroup()) {
sendOldStyleReadReceipt(readMessages);
} else {
sendNewReadReceipt(readMessages);
}
}

“When you feel the need to write a comment, first try to refactor the code so that any comment becomes superfluous.” — Martin Fowler.

Teknik refactoring yang kita bahas ini dinamakan Extract Method, yaitu memindah sebagian kode ke method baru. Banyak manfaat yang kita dapat dari extract method, antara lain:

  • Kode lebih mudah dibaca.
  • Duplikasi kode berkurang, karena method tersebut bisa digunakan lagi (reused) oleh baris kode yang lain.
  • Method yang sederhana lebih mudah untuk ditest.

Tapi ada yang perlu diperhatikan dalam melakukan extract method, di antaranya yaitu:

  • Nama method harus sesuai dengan apa yang dikerjakan method itu. Nama yang tidak sesuai dengan isinya justru akan membingungkan.

--

--