16a-refaktoring

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

Upload: api-3806259

Post on 07-Jun-2015

204 views

Category:

Documents


12 download

TRANSCRIPT

Page 1: 16A-Refaktoring

Refactoring

Overview• Apakah Refactoring itu?

• Katalog “bad smells”

Page 2: 16A-Refaktoring

2

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

Page 3: 16A-Refaktoring

3

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

Page 4: 16A-Refaktoring

4

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.

Page 5: 16A-Refaktoring

5

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

Page 6: 16A-Refaktoring

6

Contoh sangat sederhana

This

if (isSpecialDeal()) {

total = price * 0.95;send()

} else {

total = price * 0.98;send()

}

becomes this

if (isSpecialDeal())

{

total = price * 0.95;

}

else

{

total = price * 0.98;

}

send();

Menggabungkan bagian-bagian yang sama Menggabungkan bagian-bagian yang sama pada penggunaan skema kondisional pada penggunaan skema kondisional

Page 7: 16A-Refaktoring

7

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.

Page 8: 16A-Refaktoring

8

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

Page 9: 16A-Refaktoring

9

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

Page 10: 16A-Refaktoring

10

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”

Page 11: 16A-Refaktoring

11

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 :

Page 12: 16A-Refaktoring

12

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)

Page 13: 16A-Refaktoring

13

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)

Page 14: 16A-Refaktoring

14

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.

Page 15: 16A-Refaktoring

15

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.

Page 16: 16A-Refaktoring

16

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.

Page 17: 16A-Refaktoring

17

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)

Page 18: 16A-Refaktoring

18

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)

Page 19: 16A-Refaktoring

19

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)

Page 20: 16A-Refaktoring

20

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

Page 21: 16A-Refaktoring

21

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

– 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)

void Scene::setTitle (string titleText, int titleX, int titleY, Colour titleColour){…}

void Scene::getTitle (string& titleText, int& titleX, int& titleY, Colour& titleColour){…}

Page 22: 16A-Refaktoring

22

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 konstraincontoh., 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)

Page 23: 16A-Refaktoring

23

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); }}

Page 24: 16A-Refaktoring

24

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)

Page 25: 16A-Refaktoring

25

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)

Page 26: 16A-Refaktoring

26

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)

Page 27: 16A-Refaktoring

27

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)

Page 28: 16A-Refaktoring

28

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)

Page 29: 16A-Refaktoring

29

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)

Page 30: 16A-Refaktoring

30

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)

Page 31: 16A-Refaktoring

31

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)

Page 32: 16A-Refaktoring

32

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

Page 33: 16A-Refaktoring

33

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()

//print details//print details Console.Writeline(“name: ” + Console.Writeline(“name: ” + _name);_name); Console.Writeline(“amount: ” + Console.Writeline(“amount: ” + amount);amount);}}

void printOwing(double amount) void printOwing(double amount) {{ printBanner()printBanner() printDetails(amount)printDetails(amount)}}

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

Page 34: 16A-Refaktoring

34

Refactoring Pattern: Parameterize Method

BEFORE

AFTER

WebService WebService

handleGet(…)

handlePut(…)

handle(serviceType,…)

Page 35: 16A-Refaktoring

35

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)

{

return basePrice * 0.95;

}

else

{

return basePrice * 0.98;

}

double basePrice = _quantity * _itemPrice;

if (basePrice > 1000)

{ return basePrice * 0.95;

}

else

{ return basePrice * 0.98;

}

Page 36: 16A-Refaktoring

36

Refactoring Pattern: Replace Temp with Query (2)

if (basePrice() > 1000)

{ return basePrice() * 0.95;

}

else

{ return basePrice() * 0.98;

}

double basePrice()

{ return _quantity * _itemPrice;

}

double basePrice = _quantity * _itemPrice;

if (basePrice > 1000)

{

return basePrice * 0.95;

}

else

{

return basePrice * 0.98;

}

Page 37: 16A-Refaktoring

37

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);

}}

Page 38: 16A-Refaktoring

38

Refactoring Pattern: Replace Conditional with Polymorphism (2)

Page 39: 16A-Refaktoring

39

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.

Page 40: 16A-Refaktoring

40

Refactoring Pattern: Form Template Method (2)

Page 41: 16A-Refaktoring

41

Refactoring Pattern: Rename Method

• Nama dari method tidak menunjukkan maksud dan tujuan method tersebut

• Ganti nama method

• Contoh:– customer.getinvcdtlmt();– Customer.getInvoiceCreditLimit();