Professional Documents
Culture Documents
Overview
• Apakah Refactoring itu?
• Katalog “bad smells”
Apakah Refactoring ?
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
4
Mengapa perlu Refactoring?
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)
8
Kapan perlu refactoring?
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
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
16
Bad smells
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){…}
• 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
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)
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
33
Refactoring Pattern: Parameterize Method
BEFORE AFTER
WebService WebService
handleGet(…) handle(serviceType,…)
handlePut(…)
34
Refactoring Pattern: Replace Temp with Query(1)
36
Refactoring Pattern: Replace Conditional with Polymorphism (1)
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
39
Refactoring Pattern: Form Template Method (2)
40
Refactoring Pattern: Rename Method
41