Refactoring Overview Apakah Refactoring itu Katalog bad smells
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 (is. Special. Deal()) { total = price * 0. 95; send() } else { total = price * 0. 98; send() } if (is. Special. Deal()) { 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 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) 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 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) 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) 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: : set. Title (string title. Text, int title. X, int title. Y, Colour title. Colour){…} void Scene: : get. Title (string& title. Text, int& title. X, int& title. Y, Colour& title. Colour){…} – Pada contoh tersebut, sebuah kelas Title perlu dibuat 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 get. Speed () { switch (_type) { case EUROPEAN: return get. Base. Speed(); case AFRICAN: return get. Base. Speed() – get. Load. Factor() * _num. Coconuts; case NORWEGIAN_BLUE: return (_is. Nailed) ? 0 : get. Base. Speed(_voltage); } } 23
Bad smells Switch statements • – – Contoh dari kekurangpahaman atas polimorfisme dan enkapsulasi. Solusi: • Redesign sebuah method polymorfisme dari Python. Bird (Replace conditional with polymorphism, replace type code with subclasses) 24
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) 25
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) 26
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 27
Refactoring Pattern: Extract Method • Terdapat sebuah penggalan kode yang bisa dipisahkan, maka jadikan sebuah method dengan nama yang menggambarkan tujuan dari fragmen void print. Owing(double amount) { print. Banner() } //print details Console. Writeline(“name: ” + _name); Console. Writeline(“amount: ” + amount); void print. Owing(double amount) { print. Banner() print. Details(amount) } void print. Details(double amount) { Console. Writeline(“name: ” + _name); Console. Writeline(“amount: ” + amount); } 28
Refactoring Pattern: Parameterize Method Web. Service handle. Get(…) handle(service. Type, …) handle. Put(…) 29
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 base. Price = _quantity * _item. Price; if (base. Price > 1000) double base. Price = _quantity * _item. Price; { if (base. Price > 1000) return base. Price * 0. 95; { return base. Price * 0. 95; } } else { { return base. Price * 0. 98; } } 30
Refactoring Pattern: Replace Temp with Query (2) double base. Price = _quantity * _item. Price; if (base. Price > 1000) { return base. Price * 0. 95; } else { return base. Price * 0. 98; } if (base. Price() > 1000) { return base. Price() * 0. 95; } else { return base. Price() * 0. 98; } … double base. Price() { return _quantity * _item. Price; } 31
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 get. Speed() { switch (_type) { case EUROPEAN: return get. Base. Speed(); case AFRICAN: return get. Base. Speed() - get. Load. Factor() * _number. Of. Coconuts; case NORWEGIAN_BLUE: return (_is. Nailed) ? 0 : get. Base. Speed(_voltage); } } 32
Refactoring Pattern: Replace Conditional with Polymorphism (2) 33
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. 34
Refactoring Pattern: Form Template Method (2) 35
Refactoring Pattern: Rename Method • Nama dari method tidak menunjukkan maksud dan tujuan method tersebut • Ganti nama method • Contoh: – customer. getinvcdtlmt(); – Customer. get. Invoice. Credit. Limit(); 36
- Slides: 36