16a-refaktoring

  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View 16a-refaktoring as PDF for free.

More details

  • Words: 2,285
  • Pages: 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()) { total = price * 0.95; send() } else { total = price * 0.98; send() }

if (isSpecialDeal()) { total = price * 0.95; } else { total = price * 0.98; } 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? –



Terlalu jauh dari maksud dan tujuan awal method? –



Pecah ke dalam beberapa method (Extract 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” •



Kohesi rendah •



Mereka membutuhkan detil-detil dari subpart yang ada di kelas-kelas lain secara acak 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 …” • •



Filosofi Extrem Programming: • •



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. “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 methodmethod 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) { printBanner() //print details Console.Writeline(“name: ” + _name); Console.Writeline(“amount: ” + amount); }

void printOwing(double amount) { printBanner() printDetails(amount) } void printDetails(double 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; { if (basePrice > 1000) return basePrice * 0.95; { 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) { return basePrice * 0.95; } else { return basePrice * 0.98; }

if (basePrice() > 1000) { return basePrice() * 0.95; } else { 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 mengoverride 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