You are on page 1of 41

Refactoring

Overview
• Apakah Refactoring itu?
• Katalog “bad smells”
Apakah Refactoring ?

• Refactoring adalah proses memperbaiki struktur


internal sebuah sistem perangkat lunak dengan
tetap mempertahankan fungsionalitas (external
behavior) dari sistem.
• Refactoring merupakan proses memperbaiki
desain setelah coding

2
Latar Belakang
• Dasar kemunculan refactoring: sangat sulit mendapatkan
sebuah rancangan yang benar pada iterasi pertama
pengembangan sistem, dan ketika ada perubahan pada
sistem maka desain juga perlu diubah– INCREMENTAL
DESIGN
– refactoring menyediakan teknik-teknik untuk mengembangkan
desain dalam bentuk tahap-tahap kecil pengembangan sistem

• Keuntungan
– Ukuran program bisa lebih kecil
– Struktur yang membingungkan ditransformasikan ke struktur yang
lebih sederhana yang lebih mudah dipelihara dan dimengerti

3
Tujuan Refactoring

• Tujuan dari refactoring adalah membuat program


perangkat lunak menjadi lebih mudah dimengerti
dan dimodifikasi
• Berbeda dengan optimisasi, walaupun juga hanya
mengubah struktur internal dengan fungsionalitas
tetap, optimisasi membuat program lebih susah
dimengerti tetapi lebih cepat.

4
Mengapa perlu Refactoring?

• Refactoring memperbaiki desain perangkat lunak


– Tanpa refactoring, rancangan bisa rusak ketika ada perubahan
terhadap sistem perangkat lunak
• Refactoring membuat perangkat lunak lebih mudah untuk
dimengerti
– Karena struktur diperbaiki, duplikasi kode bisa diperbaiki, dan
lain-lain
• Refactoring membantu menemukan bugs
– Refactoring meningkatkan pemahaman terhadap kode dan
pemahaman ini sangat membantu dalam menemukan dan
mengantisipasi bugs
• Refactoring membuat pemrograman (pada iterasi
berikutnya) menjadi lebih cepat
5
Contoh sangat sederhana

Menggabungkan bagian-bagian yang sama


pada penggunaan skema kondisional
This becomes this

if (isSpecialDeal()) if (isSpecialDeal())
{
{
total = price * 0.95;
send() total = price * 0.95;
} }
else else
{ {
total = price * 0.98;
total = price * 0.98;
send()
} }
send();
6
Prinsip Refactoring (1)
• Ada anggapan bahwa refactoring menghabiskan waktu
implementasi dan menyebabkan penyelesaian proyek
terlambat.
- karenanya Refactoring perlu sistematik, bertahap, dan aman
• Bagaimana membuat refactoring aman?
=> Pertama, gunakan “pola-pola” refactoring
- Fowler memberikan nama pada “pola-pola” refactoring
=> Kedua, lakukan test
- Setelah refactoring, test harus dilakukan. Jika test memberikan
hasil gagal maka berarti Refactoring telah merusak program dan
harus diperbaiki dulu sebelum ke tahap selanjutnya.

7
Prinsip Refactoring (2)

• Refactoring berbeda dengan penambahan fungsi,


keduanya tidak bisa dilakukan secara bersamaan
• Penambahan fungsi
– Fungsionalitas diimplementasikan pada sistem tanpa
pembersihan kode
• Refactoring
– Tidak ada fungsionalitas yang ditambahkan pada
sistem, tetapi kode dibersihkan, sehingga mudah
dimengerti dan dimodifikasi, dan kadang-kadang bisa
mereduksi ukuran program

8
Kapan perlu refactoring?

• The Rule of Three


– Terdapat bagian kode berulang 3 kali, refactoring
dilakukan terhadap bagian tersebut
• Refactoring ketika menambah fungsionalitas
– Refactoring sebelum menambah fungsi untuk
mempermudah penambahan fungsi tersebut
– Atau lakukan setelah fungsi ditambahkan
• Refactoring untuk memperbaiki bugs
• Refactoring jika perlu review progran

9
Masalah dengan Refactoring

• Basis data
– Aplikasi bisnis biasanya terhubung erat basis data
– Kode mudah untuk diubah basis data tidak
• Mengubah antarmuka
– Beberapa refactoring membutuhkan perubahan antarmuka. Akan
jadi masalah jika source code antarmuka tidak ada.
• Perubahan desain yang sulit untuk direfaktor
– Itulah kenapa extreme programming mengatakan bahwa software
engineer harus memiliki “keberanian”

10
Katalog Refactoring

• Katalog refactoring terdiri dari “Bad Smells”, yaitu struktur


program yang tidak bagus dan perlu diperbaiki, dan pola
refactoring yang dibutuhkan untuk menghilangkan bad smells
• Studi kasus :

11
Bad smells

• Duplikasi Kode
– Bad smell yang paling banyak muncul
– Apakah terdapat dua method yang sama pada sebuah kelas?
• Buat sebuah rutin tambahan berparameter
(Extract method)
– Kode yang sama pada kelas yang berelasi?
• Pindahkan bagian yang sama tersebut ke ancestor terdekat dan
parametrisasi
• Gunakan template method untuk mengakomodasi variasi pada
subtasks
(template method)

12
Bad smells

• Duplikasi Kode
– Kode yang sama pada kelas yang tidak berelasi?
• Haruskah mereka berelasi?
– Buat kelas induk abstrak (Extract class, Pull up method)
• Apakah kode sebaiknya dimiliki hanya oleh sebuah kelas?
– Buat kelas lainnya sebagai client (Extract method)
• Dapatkah bagian kode yang sama tadi dipisahkan ke dalam subpart
atau functor atau other function object?
– Pindahkan method ke subobject dari kedua kelas tersebut
– Strategi DP membolehkan pendefinisian methods-as-objects/ method
object untuk variasi polimorfisme
(Replace method with method object)

13
Bad smells

• Long method
– Seringkali menunjukkan:
• Method melakukan terlalu banyak hal
• Menunjukkan abstraksi dan pembatasan yang buruk
• Micromanagement anti-pattern
– Harus diidentifikasi dengan cermat tentang tugas-tugas utama dan
bagaimana mereka berinterelasi.
• Pecah ke dalam method yang lebih kecil dalam kelas yang sama dan
dengan visibility Private (Extract method)
• Delegasikan subtask ke beberapa subobjek (contoh: template method DP)
(Extract class/method, Replace data value with object)

– Heuristic Fowler:
• When you see a comment, make a method.

14
Bad smells

• Large class
– Terlalu banyak komponen
– Solusi:
1. Kelompokkan dan pisahkan masing-masing ke sebuah kelas
(Extract class, replace data value with object)
2. Delegasikan method ke kelas / subparts.
(Extract method)

– Contoh:
• Kelas-kelas library seringkali ‘gemuk’ (banyak method, banyak
parameter, banyak overloading)
– Tidak masalah jika tujuannya untuk fleksibilitas.

15
Bad smells

• Long parameter list


– Menyulitkan memahami method
– Ini merupakan gejala dari:
• Method melakukan terlalu banyak hal
• Terlalu jauh dari maksud dan tujuan awal method
• Banyak mengandung subpart yang berlainan

– Pada pemrograman terstruktur parameter digunakan sebagai


solusi atas penggunaan variabel global yang banyak.
• Pada OOP, objek sangat mungkin memiliki variabel-variabel yang
bersifat global terhadap method tetapi tetap tersembunyi dari
semua bagian program lainnya.
Jadi, tidak perlu menjadikan subpart (atribut) pada method dari objek
yang sama.

16
Bad smells

• Long parameter list


– Solusi:
• Method melakukan terlalu banyak hal?
– Pecah ke dalam beberapa method
(Extract method)
• Terlalu jauh dari maksud dan tujuan awal method?
– Lokalisasi parameter, jangan mudah untuk menempatkan parameter di
beberapa layer pemanggilan
(Buat whole object, gunakan objek parameter)
• Banyak mengandung subpart yang berlainan?
– Kelompokkan parameter ke dalam aggregate subpart
– Antarmuka method akan menjadi lebih mudah untuk dipahami
(Preserve whole object, introduce parameter object)

17
Bad smells

• Divergent change
– Terjadi ketika sebuah kelas sering mengalami perubahan dengan
beragam cara untuk berbagai alasan
– Kelas melakukan banyak hal dan berisi banyak subpart yang tidak
berelasi satu sama lain
– Semakin lama, beberapa kelas membentuk “God complex”
• Mereka membutuhkan detil-detil dari subpart yang ada di kelas-kelas lain
secara acak
– Kohesi rendah
• Di satu kelas terdapat elemen-elemen yang tidak berelasi
– Solusi:
• Pecah kelasmenyusun ulang kelas, mempertimbangkan kembali relasi dan
responsibiliti (Extract class)

18
Bad smells

• Shotgun surgery
– Kebalikan dari divergent change
• Setiap kali terjadi perubahan yang koheren, maka banyak kelas
yang berubah
• Kohesi rendah
• Elemen-elemen yang berelasi ada di kelas-kelas yang berbeda
– Solution:
• Tempatkan atribut dan method yang berelasi pada sebuah kelas,
bisa kelas baru atau yang sudah ada.
(Move method/field)

19
Bad smells

• Feature envy
– Sebuah method lebih cocok berada di kelas lain
Contoh: method A::m() sering memanggil method get/set dari kelas B
– Solusi:
• Pindahkan m() (atau bagian dari m()) ke kelas B
(Move method/field, extract method)
– Pengecualian:
• Visitor/iterator/strategy DP yang bertujuan menempatkan data
terpisah dari algoritma

20
Bad smells

• Data clumps
– Terjadi jika sekumpulan data selalu bersama-sama, sebagai parameter
atau diubah/diakses pada saat yang sama
– Seharusnya terdapat sebuah subobjek koheren yang perlu dibuat
void Scene::setTitle (string titleText,
int titleX, int titleY,
Colour titleColour){…}

void Scene::getTitle (string& titleText,


int& titleX, int& titleY,
Colour& titleColour){…}

– Pada contoh tersebut, sebuah kelas Title perlu dibuat


– Pemindahan data dapat menimbulkan feature envy
• Perancangan dilakukan secara iterasi sampai benar.
(Preserve whole object, extract class, introduce parameter object)
21
Bad smells

• Primitive obsession
– Semua atribut dari objek merupakan instans dari tipe primitif
(int, string, bool, double, dll.)
Contoh: dates, currency, SIN, tel.#, ISBN
– Seringkali objek-objek mempunyai konstrain
contoh., fixed number dari digit/karakter, nilai khusus
– Solusi:
• Buat beberapa “kelas kecil” yang dapat mendukung definisi
konstrain.
(Replace data value with object, extract class, introduce
parameter object)

22
Bad smells

• Switch statements
– Contoh penggunaan switch:

Double getSpeed () {
switch (_type) {
case EUROPEAN:
return getBaseSpeed();
case AFRICAN:
return getBaseSpeed() –
getLoadFactor() * _numCoconuts;
case NORWEGIAN_BLUE:
return (_isNailed) ? 0
: getBaseSpeed(_voltage);
}
}

23
Bad smells

• Switch statements
– Contoh dari kekurangpahaman atas polimorfisme dan
enkapsulasi.
– Solusi:
• Redesign sebuah method polymorfisme dari PythonBird
(Replace conditional with polymorphism, replace type code
with subclasses)

24
Bad smells

• Lazy class
– Kelas-kelas yang tidak banyak melakukan hal-hal yang berbeda
dengan kelas-kelas lainnya.
– Jika ada beberapa kelas turunan yang tidak menampilkan
perbedaan/variasi perilaku dari kelas induknya maka hilangkan
kelas tersebut dan buat parameterisasi pada method kelas induk.
– Seringkali lazy classes merupakan akibat dari rancangan yang
terlalu ambisius atau refactoring
(Collapse hierarchy, inline class)

25
Bad smells

• Speculative generality
– Adanya kelas-kelas yang tidak berguna sebagai akibat dari
prinsip “We might need this one day …”
• Tidak masalah, tetapi harus diperiksa ulang apakah kelas-kelas
tersebut memang diperlukan atau tidak?
• Adanya kelas-kelas yang tidak terpakai menambah kompleksitas
model dan sistem.
– Filosofi Extrem Programming:
• “Sesederhana mungkin tetapi tidak lebih sederhana”
• “Rule of three”.
– Harus diingat bahwa Refactoring adalah proses yang
berlangsung terus menerus.
• Jika benar-benar diperlukan, kelas bisa ditambahkan kembali
(Collapse hierarchy, inline class, remove parameter)
26
Bad smells

• Message chains
– Objek klien (A) meminta servis dari sebuah objek (B), B
meminta servis dari subobjek lain (C), C meminta servis dari
subobjek lainnya (D), …
• Multi-layer “drill down” dapat menghasilkan sub-sub-sub-objects
ke objek klien.
– Perlu berpikir ulang tentang abstraksi
• Mengapa ada message passing bersarang?
• Mengapa objek-objek subpart yang berguna bagi objek klien
“berjarak jauh” dari objek klien tersebut?
(Hide delegate)

27
Bad smells
• Inappropriate intimacy
– Sharing properti privat antar kelas. Hal ini membawa sistem kepada
coupling yang tinggi, struktur internal kelas dan teknik implementasi
menjadi terbuka. Akibatnya struktur menjadi rapuh dan sulit
berkembang.
– Solusi:
• Gunakan method get/set
• Pikir ulang dari abstraksi.
• Gabungkan kelas
(Move/extract method/field, change bidirectional association to
unidirectional, hide delegate)

• Middle man
– Objek-objek yang hanya mendelegasikan message dari objek klien ke
objek server
(Remove middle man, replace delegation with inheritance)

28
Bad smells

• Alternative classes with different interfaces


– Kelas-kelas/method-method mengimplementasikan abstraksi
yang sama/sejenis padahal mereka tidak berelasi
– Bukan merupakan overloading tetapi keteledoran perancangan.
– Solusi:
• Gabungkan kelas-kelas yang terlihat “dekat”.
– Definisikan antarmukanya
– Cari subpart-subpart yang sama dan hampir semuanya dihapus agar
tidak ada redundansi .
(Extract [super]class, move method/field, rename method)

29
Bad smells

• Data class
– Kelas hanya terdiri dari field-field data sederhana
dan method-method pengaksesan sederhana.
– Solusi:
• Perhatikan pola penggunaan ini oleh objek klien
• Abstraksikan cara-cara pengaksesan yang sama
terhadap komponen, ke dalam method-method dari
kelas data, dan pindahkan beberapa fungsionalitas ke
kelas data tersebut
(Extract/move method)

30
Bad smells

• Refused bequest
– Subkelas mewarisi semua method/variabel dari kelas parent tetapi
tidak menggunakan sebagian dari mereka.
• Gunakan delegasi
(Replace inheritance with delegation)

– Kelas parent punya fitur yang digunakan hanya oleh beberapa


kelas turunannya. :
• Membuat kelas-kelas intermediate pada hierarki. Pindahkan method-
method khusus ke level yang lebih bawah.
(Push down field/method)

31
Bad smells

• Comments
– Filosofi memandang penting penggunaan komentar, karena:
• Membuat method lebih mudah dipahami
– Pada Refactoring, Fowler mengklaim bahwa komentar
merupakan tanda-tanda ketidakjelasan, kerumitan, dan
ketidakpahaman.
• Daripada memelihara ketidakjelasan, lebih baik kode
direstrukturisasi
(Extract method/class, [many others applicable] …)
– Komen diperlukan untuk mendokumentasi alasan
contoh, menerangkan mengapa pendekatan ini yang dipilih bukan yang
lainnya

32
Refactoring Pattern: Extract Method

• Terdapat sebuah penggalan kode yang bisa dipisahkan,


maka jadikan sebuah method dengan nama yang
menggambarkan tujuan dari fragmen

void printOwing(double amount) void printOwing(double amount)


{ {
printBanner() printBanner()
printDetails(amount)
//print details }
Console.Writeline(“name: ” +
_name); void printDetails(double amount)
Console.Writeline(“amount: ” + {
amount); Console.Writeline(“name: ” + _name);
} Console.Writeline(“amount: ” + amount);
}

33
Refactoring Pattern: Parameterize Method

BEFORE AFTER

WebService WebService

handleGet(…) handle(serviceType,…)
handlePut(…)

34
Refactoring Pattern: Replace Temp with Query(1)

• Menggunakan variabel sementara untuk menyimpan hasil


dari suatu expresi
• Jadikan expresi tersebut sebuah method
• Ganti semua referens ke variabel sementara tersebut
dengan expresi, dan hilangkan variabel
double basePrice = _quantity * _itemPrice;
if (basePrice > 1000)
{ double basePrice = _quantity * _itemPrice;
return basePrice * 0.95; if (basePrice > 1000)
} { return basePrice * 0.95;
else }
{ else
return basePrice * 0.98; { return basePrice * 0.98;
} }
35
Refactoring Pattern: Replace Temp with Query (2)

double basePrice = _quantity * _itemPrice;


if (basePrice > 1000)
{ if (basePrice() > 1000)
return basePrice * 0.95;
{ return basePrice() * 0.95;
}
}
else
else
{
return basePrice * 0.98; { return basePrice() * 0.98;
} }

double basePrice()
{ return _quantity * _itemPrice;
}

36
Refactoring Pattern: Replace Conditional with Polymorphism (1)

• Terdapat kondisional untuk berdasarkan tipe dari objek


• Hilangkan kondisional dengan sebuah overriding method yang ada
pada sub kelas
• Buat abstrak untuk method asal

double getSpeed()
{ switch (_type)
{ case EUROPEAN: return getBaseSpeed();
case AFRICAN: return getBaseSpeed() - getLoadFactor() *
_numberOfCoconuts;
case NORWEGIAN_BLUE:
return (_isNailed) ? 0 : getBaseSpeed(_voltage);
}
}

37
Refactoring Pattern: Replace Conditional with Polymorphism (2)

38
Refactoring Pattern: Form Template Method

• Terdapat 2 method dengan tujuan yang sama pada


beberapa subclass yang berbeda tetapi ada perbedaan
pada bagian algoritma.

• Buat sebuah method yang sama dan tempatkan pada


superclass/parent sehingga method asal sama, dan
definisikan sebuah method pada subclass yang meng-
override method tersebut.

39
Refactoring Pattern: Form Template Method (2)

40
Refactoring Pattern: Rename Method

• Nama dari method tidak menunjukkan


maksud dan tujuan method tersebut
• Ganti nama method
• Contoh:
– customer.getinvcdtlmt();
– Customer.getInvoiceCreditLimit();

41

You might also like