CodeGym/Java Blog/Acak/Bagaimana refactoring bekerja di Jawa
John Squirrels
Level 41
San Francisco

Bagaimana refactoring bekerja di Jawa

Dipublikasikan di grup Acak
anggota
Saat Anda mempelajari cara memprogram, Anda menghabiskan banyak waktu untuk menulis kode. Sebagian besar pengembang pemula percaya bahwa inilah yang akan mereka lakukan di masa depan. Ini sebagian benar, tetapi pekerjaan seorang programmer juga mencakup pemeliharaan dan pemfaktoran ulang kode. Hari ini kita akan berbicara tentang refactoring. Cara kerja refactoring di Java - 1

Memfaktorkan ulang pada CodeGym

Refactoring dibahas dua kali dalam kursus CodeGym: Tugas besar memberikan kesempatan untuk berkenalan dengan refactoring nyata melalui latihan, dan pelajaran tentang refactoring di IDEA membantu Anda menyelami alat otomatis yang akan membuat hidup Anda jauh lebih mudah.

Apa itu refactoring?

Itu mengubah struktur kode tanpa mengubah fungsinya. Sebagai contoh, misalkan kita memiliki metode yang membandingkan 2 angka dan mengembalikan benar jika yang pertama lebih besar dan sebaliknya salah :
public boolean max(int a, int b) {
    if(a > b) {
        return true;
    } else if (a == b) {
        return false;
    } else {
        return false;
    }
}
Ini adalah kode yang agak berat. Bahkan pemula jarang menulis sesuatu seperti ini, tetapi ada peluang. Mengapa menggunakan if-elseblok jika Anda dapat menulis metode 6 baris dengan lebih ringkas?
public boolean max(int a, int b) {
     return a > b;
}
Sekarang kami memiliki metode sederhana dan elegan yang melakukan operasi yang sama seperti contoh di atas. Beginilah cara kerja refactoring: Anda mengubah struktur kode tanpa memengaruhi esensinya. Ada banyak metode dan teknik refactoring yang akan kita lihat lebih dekat.

Mengapa Anda perlu melakukan refactoring?

Ada beberapa alasan. Misalnya, untuk mencapai kesederhanaan dan singkatnya kode. Pendukung teori ini percaya bahwa kode harus seringkas mungkin, bahkan jika diperlukan beberapa lusin baris komentar untuk memahaminya. Pengembang lain yakin bahwa kode harus difaktorkan ulang agar dapat dimengerti dengan jumlah komentar minimum. Setiap tim mengadopsi posisinya sendiri, tetapi ingat bahwa refactoring tidak berarti pengurangan . Tujuan utamanya adalah untuk memperbaiki struktur kode. Beberapa tugas dapat dimasukkan dalam tujuan keseluruhan ini:
  1. Refactoring meningkatkan pemahaman kode yang ditulis oleh pengembang lain.
  2. Ini membantu menemukan dan memperbaiki bug.
  3. Itu dapat mempercepat kecepatan pengembangan perangkat lunak.
  4. Secara keseluruhan, ini meningkatkan desain perangkat lunak.
Jika refactoring tidak dilakukan untuk waktu yang lama, pengembangan dapat mengalami kesulitan, termasuk penghentian pekerjaan sepenuhnya.

"Bau kode"

Ketika kode membutuhkan refactoring, dikatakan memiliki "bau". Tentu saja, tidak secara harfiah, tetapi kode seperti itu benar-benar tidak terlihat menarik. Di bawah ini kita akan mengeksplorasi teknik refactoring dasar untuk tahap awal.

Kelas dan metode yang terlalu besar

Kelas dan metode bisa rumit, tidak mungkin untuk dikerjakan secara efektif justru karena ukurannya yang besar.

Kelas besar

Kelas seperti itu memiliki banyak sekali baris kode dan banyak metode berbeda. Biasanya lebih mudah bagi pengembang untuk menambahkan fitur ke kelas yang sudah ada daripada membuat yang baru, itulah sebabnya kelas tumbuh. Biasanya, terlalu banyak fungsi yang dijejalkan ke dalam kelas seperti itu. Dalam hal ini, ada baiknya memindahkan sebagian fungsionalitas ke kelas terpisah. Kami akan membicarakan hal ini lebih detail di bagian teknik refactoring.

Metode panjang

"Bau" ini muncul ketika pengembang menambahkan fungsionalitas baru ke suatu metode: "Mengapa saya harus memasukkan pemeriksaan parameter ke dalam metode terpisah jika saya dapat menulis kode di sini?", "Mengapa saya memerlukan metode pencarian terpisah untuk menemukan yang maksimal elemen dalam array? Mari kita simpan di sini. Kode akan lebih jelas dengan cara ini", dan kesalahpahaman lainnya.

Ada dua aturan untuk memfaktorkan ulang metode yang panjang:

  1. Jika Anda ingin menambahkan komentar saat menulis metode, Anda harus meletakkan fungsionalitas tersebut dalam metode terpisah.
  2. Jika suatu metode membutuhkan lebih dari 10-15 baris kode, Anda harus mengidentifikasi tugas dan subtugas yang dijalankannya dan mencoba menempatkan subtugas ke dalam metode terpisah.

Ada beberapa cara untuk menghilangkan metode panjang:

  • Pindahkan sebagian fungsionalitas metode ke dalam metode terpisah
  • Jika variabel lokal mencegah Anda memindahkan sebagian fungsionalitas, Anda dapat memindahkan seluruh objek ke metode lain.

Menggunakan banyak tipe data primitif

Masalah ini biasanya terjadi ketika jumlah bidang di kelas bertambah dari waktu ke waktu. Misalnya, jika Anda menyimpan semuanya (mata uang, tanggal, nomor telepon, dll.) dalam tipe primitif atau konstanta, bukan objek kecil. Dalam hal ini, praktik yang baik adalah memindahkan pengelompokan bidang secara logis ke dalam kelas terpisah (kelas ekstrak). Anda juga dapat menambahkan metode ke kelas untuk memproses data.

Terlalu banyak parameter

Ini adalah kesalahan yang cukup umum, terutama jika dikombinasikan dengan metode yang panjang. Biasanya, ini terjadi jika sebuah metode memiliki terlalu banyak fungsionalitas, atau jika sebuah metode mengimplementasikan beberapa algoritma. Daftar parameter yang panjang sangat sulit untuk dipahami, dan menggunakan metode dengan daftar seperti itu tidak nyaman. Akibatnya, lebih baik melewatkan seluruh objek. Jika objek tidak memiliki cukup data, Anda harus menggunakan objek yang lebih umum atau membagi fungsionalitas metode sehingga setiap metode memproses data yang terkait secara logis.

Grup data

Grup data yang terkait secara logis sering muncul dalam kode. Misalnya, parameter koneksi basis data (URL, nama pengguna, kata sandi, nama skema, dll.). Jika tidak ada satu bidang pun yang dapat dihapus dari daftar bidang, maka bidang ini harus dipindahkan ke kelas terpisah (kelas ekstrak).

Solusi yang melanggar prinsip OOP

"Bau" ini terjadi saat pengembang melanggar desain OOP yang tepat. Ini terjadi ketika dia tidak sepenuhnya memahami kemampuan OOP dan gagal menggunakannya secara penuh atau benar.

Gagal menggunakan warisan

Jika subclass hanya menggunakan subset kecil dari fungsi kelas induk, maka itu berbau hirarki yang salah. Ketika ini terjadi, biasanya metode yang berlebihan tidak diganti atau mereka membuang pengecualian. Satu kelas mewarisi yang lain menyiratkan bahwa kelas anak menggunakan hampir semua fungsionalitas kelas induk. Contoh hierarki yang benar: Bagaimana refactoring bekerja di Java - 2Contoh hierarki yang salah: Cara kerja refactoring di Java - 3

Beralih pernyataan

Apa yang salah dengan sebuah switchpernyataan? Itu buruk ketika menjadi sangat kompleks. Masalah terkait adalah sejumlah besar ifpernyataan bersarang.

Kelas alternatif dengan antarmuka yang berbeda

Beberapa kelas melakukan hal yang sama, tetapi metode mereka memiliki nama yang berbeda.

Bidang sementara

Jika sebuah kelas memiliki bidang sementara yang hanya diperlukan objek sesekali ketika nilainya ditetapkan, dan itu kosong atau, amit-amit, nulldi sisa waktu, maka kodenya berbau. Ini adalah keputusan desain yang dipertanyakan.

Bau yang membuat modifikasi sulit

Bau ini lebih serius. Bau lain terutama mempersulit untuk memahami kode, tetapi ini mencegah Anda untuk memodifikasinya. Saat Anda mencoba memperkenalkan fitur baru apa pun, setengah dari pengembang berhenti, dan setengah lagi menjadi gila.

Hirarki warisan paralel

Masalah ini memanifestasikan dirinya ketika subclassing kelas mengharuskan Anda untuk membuat subclass lain untuk kelas yang berbeda.

Dependensi yang terdistribusi secara seragam

Setiap modifikasi mengharuskan Anda untuk mencari semua kegunaan (ketergantungan) kelas dan membuat banyak perubahan kecil. Satu perubahan — edit di banyak kelas.

Pohon modifikasi yang rumit

Bau ini kebalikan dari yang sebelumnya: perubahan memengaruhi sejumlah besar metode dalam satu kelas. Sebagai aturan, kode semacam itu memiliki ketergantungan yang mengalir: mengubah satu metode mengharuskan Anda untuk memperbaiki sesuatu di metode lain, lalu di metode ketiga, dan seterusnya. Satu kelas — banyak perubahan.

"Bau sampah"

Kategori bau yang agak tidak menyenangkan yang menyebabkan sakit kepala. Tidak berguna, tidak perlu, kode lama. Untungnya, IDE dan linter modern telah belajar untuk memperingatkan bau tersebut.

Sejumlah besar komentar dalam suatu metode

Suatu metode memiliki banyak komentar penjelasan di hampir setiap baris. Hal ini biasanya disebabkan oleh algoritme yang rumit, jadi lebih baik membagi kode menjadi beberapa metode yang lebih kecil dan memberinya nama penjelas.

Kode duplikat

Kelas atau metode yang berbeda menggunakan blok kode yang sama.

Kelas malas

Kelas mengambil fungsi yang sangat sedikit, meskipun direncanakan untuk menjadi besar.

Kode yang tidak digunakan

Kelas, metode, atau variabel tidak digunakan dalam kode dan merupakan bobot mati.

Konektivitas yang berlebihan

Kategori bau ini dicirikan oleh banyaknya hubungan yang tidak dapat dibenarkan dalam kode.

Metode eksternal

Metode menggunakan data dari objek lain jauh lebih sering daripada datanya sendiri.

Keintiman yang tidak pantas

Kelas bergantung pada detail implementasi kelas lain.

Panggilan kelas panjang

Satu kelas memanggil yang lain, yang meminta data dari yang ketiga, yang mendapatkan data dari yang keempat, dan seterusnya. Rantai panggilan yang begitu panjang berarti ketergantungan yang tinggi pada struktur kelas saat ini.

Kelas pemberi tugas

Kelas diperlukan hanya untuk mengirim tugas ke kelas lain. Mungkin itu harus dihapus?

Teknik pemfaktoran ulang

Di bawah ini kita akan membahas teknik refactoring dasar yang dapat membantu menghilangkan bau kode yang dijelaskan.

Ekstrak kelas

Kelas melakukan terlalu banyak fungsi. Beberapa dari mereka harus dipindahkan ke kelas lain. Misalnya, kita memiliki Humankelas yang juga menyimpan alamat rumah dan memiliki metode yang mengembalikan alamat lengkap:
class Human {
    private String name;
    private String age;
    private String country;
    private String city;
    private String street;
    private String house;
    private String quarter;

    public String getFullAddress() {
        StringBuilder result = new StringBuilder();
        return result
                        .append(country)
                        .append(", ")
                        .append(city)
                        .append(", ")
                        .append(street)
                        .append(", ")
                        .append(house)
                        .append(" ")
                        .append(quarter).toString();
    }
 }
Merupakan praktik yang baik untuk menempatkan informasi alamat dan metode terkait (perilaku pemrosesan data) ke dalam kelas terpisah:
class Human {
   private String name;
   private String age;
   private Address address;

   private String getFullAddress() {
       return address.getFullAddress();
   }
}
class Address {
   private String country;
   private String city;
   private String street;
   private String house;
   private String quarter;

   public String getFullAddress() {
       StringBuilder result = new StringBuilder();
       return result
                       .append(country)
                       .append(", ")
                       .append(city)
                       .append(", ")
                       .append(street)
                       .append(", ")
                       .append(house)
                       .append(" ")
                       .append(quarter).toString();
   }
}

Ekstrak metode

Jika suatu metode memiliki beberapa fungsionalitas yang dapat diisolasi, Anda harus menempatkannya dalam metode terpisah. Misalnya, metode yang menghitung akar persamaan kuadrat:
public void calcQuadraticEq(double a, double b, double c) {
    double D = b * b - 4 * a * c;
    if (D > 0) {
        double x1, x2;
        x1 = (-b - Math.sqrt(D)) / (2 * a);
        x2 = (-b + Math.sqrt(D)) / (2 * a);
        System.out.println("x1 = " + x1 + ", x2 = " + x2);
    }
    else if (D == 0) {
        double x;
        x = -b / (2 * a);
        System.out.println("x = " + x);
    }
    else {
        System.out.println("Equation has no roots");
    }
}
Kami menghitung masing-masing dari tiga opsi yang memungkinkan dalam metode terpisah:
public void calcQuadraticEq(double a, double b, double c) {
    double D = b * b - 4 * a * c;
    if (D > 0) {
        dGreaterThanZero(a, b, D);
    }
    else if (D == 0) {
        dEqualsZero(a, b);
    }
    else {
        dLessThanZero();
    }
}

public void dGreaterThanZero(double a, double b, double D) {
    double x1, x2;
    x1 = (-b - Math.sqrt(D)) / (2 * a);
    x2 = (-b + Math.sqrt(D)) / (2 * a);
    System.out.println("x1 = " + x1 + ", x2 = " + x2);
}

public void dEqualsZero(double a, double b) {
    double x;
    x = -b / (2 * a);
    System.out.println("x = " + x);
}

public void dLessThanZero() {
    System.out.println("Equation has no roots");
}
Setiap kode metode menjadi jauh lebih pendek dan lebih mudah dipahami.

Melewati seluruh objek

Saat metode dipanggil dengan parameter, terkadang Anda mungkin melihat kode seperti ini:
public void employeeMethod(Employee employee) {
    // Some actions
    double yearlySalary = employee.getYearlySalary();
    double awards = employee.getAwards();
    double monthlySalary = getMonthlySalary(yearlySalary, awards);
    // Continue processing
}

public double getMonthlySalary(double yearlySalary, double awards) {
     return (yearlySalary + awards)/12;
}
Itu employeeMethodmemiliki 2 baris penuh yang dikhususkan untuk menerima nilai dan menyimpannya dalam variabel primitif. Terkadang konstruksi seperti itu bisa memakan waktu hingga 10 baris. Jauh lebih mudah untuk meneruskan objek itu sendiri dan menggunakannya untuk mengekstrak data yang diperlukan:
public void employeeMethod(Employee employee) {
    // Some actions
    double monthlySalary = getMonthlySalary(employee);
    // Continue processing
}

public double getMonthlySalary(Employee employee) {
    return (employee.getYearlySalary() + employee.getAwards())/12;
}

Sederhana, singkat, dan padat.

Mengelompokkan bidang secara logis dan memindahkannya menjadi terpisah classDespitefakta bahwa contoh di atas sangat sederhana, dan ketika Anda melihatnya, banyak dari Anda mungkin bertanya, "Siapa yang melakukan ini?", banyak pengembang membuat kesalahan struktural seperti itu karena kecerobohan, keengganan untuk memperbaiki kode, atau hanya sikap "itu cukup baik".

Mengapa refactoring efektif

Sebagai hasil dari pemfaktoran ulang yang baik, sebuah program memiliki kode yang mudah dibaca, prospek untuk mengubah logikanya tidak menakutkan, dan memperkenalkan fitur baru tidak menjadi neraka analisis kode, melainkan pengalaman yang menyenangkan selama beberapa hari. . Anda tidak boleh melakukan refactor jika akan lebih mudah untuk menulis program dari awal. Misalnya, tim Anda memperkirakan bahwa tenaga kerja yang diperlukan untuk memahami, menganalisis, dan memfaktorkan ulang kode akan lebih besar daripada mengimplementasikan fungsionalitas yang sama dari awal. Atau jika kode yang akan di-refactor memiliki banyak masalah yang sulit untuk di-debug. Mengetahui cara memperbaiki struktur kode sangat penting dalam pekerjaan seorang programmer. Dan belajar memprogram di Java paling baik dilakukan di CodeGym, kursus online yang menekankan praktik. 1200+ tugas dengan verifikasi instan, sekitar 20 proyek mini, tugas permainan — semua ini akan membantu Anda merasa percaya diri dalam pengkodean. Waktu terbaik untuk memulai adalah sekarang :)

Sumber daya untuk membenamkan diri Anda lebih jauh dalam pemfaktoran ulang

Buku paling terkenal tentang refactoring adalah "Refactoring. Improving the Design of Existing Code" oleh Martin Fowler. Ada juga publikasi menarik tentang refactoring, berdasarkan buku sebelumnya: "Refactoring Using Patterns" oleh Joshua Kerievsky. Berbicara tentang pola... Saat melakukan refactoring, selalu sangat berguna untuk mengetahui pola desain dasar. Buku-buku bagus ini akan membantu dalam hal ini: Berbicara tentang pola... Saat melakukan pemfaktoran ulang, selalu sangat berguna untuk mengetahui pola desain dasar. Buku-buku bagus ini akan membantu dalam hal ini:
  1. "Pola Desain" oleh Eric Freeman, Elizabeth Robson, Kathy Sierra, dan Bert Bates, dari seri Head First
  2. "Seni Kode yang Dapat Dibaca" oleh Dustin Boswell dan Trevor Foucher
  3. "Code Complete" oleh Steve McConnell, yang menetapkan prinsip untuk kode yang indah dan elegan.
Komentar
  • Populer
  • Baru
  • Lama
Anda harus login untuk memberikan komentar
Halaman ini belum memiliki komentar