JavaRush /Blog Java /Random-MS /Bagaimana pemfaktoran semula berfungsi di Jawa

Bagaimana pemfaktoran semula berfungsi di Jawa

Diterbitkan dalam kumpulan
Apabila belajar memprogram, banyak masa dihabiskan untuk menulis kod. Kebanyakan pembangun permulaan percaya bahawa ini adalah aktiviti masa depan mereka. Ini sebahagiannya benar, tetapi tugas pengaturcara juga termasuk mengekalkan dan memfaktorkan semula kod. Hari ini kita akan bercakap tentang pemfaktoran semula. Bagaimana pemfaktoran semula berfungsi dalam Java - 1

Pemfaktoran semula dalam kursus JavaRush

Kursus JavaRush merangkumi topik pemfaktoran semula dua kali: Terima kasih kepada tugas besar, terdapat peluang untuk membiasakan diri dengan pemfaktoran semula sebenar dalam amalan, dan syarahan tentang pemfaktoran semula dalam IDEA akan membantu anda memahami alatan automatik yang menjadikan kehidupan lebih mudah.

Apakah pemfaktoran semula?

Ini ialah perubahan dalam struktur kod tanpa mengubah fungsinya. Sebagai contoh, terdapat kaedah yang membandingkan 2 nombor dan mengembalikan benar jika yang pertama lebih besar, dan palsu sebaliknya:
public boolean max(int a, int b) {
    if(a > b) {
        return true;
    } else if(a == b) {
        return false;
    } else {
        return false;
    }
}
Hasilnya adalah kod yang sangat rumit. Walaupun pemula jarang menulis sesuatu seperti ini, tetapi terdapat risiko sedemikian. Nampaknya, mengapa terdapat blok di sini if-elsejika anda boleh menulis kaedah 6 baris lebih pendek:
public boolean max(int a, int b) {
     return a>b;
}
Sekarang kaedah ini kelihatan mudah dan elegan, walaupun ia melakukan perkara yang sama seperti contoh di atas. Beginilah cara pemfaktoran semula berfungsi: ia mengubah struktur kod tanpa menjejaskan intipatinya. Terdapat banyak kaedah dan teknik pemfaktoran semula, yang akan kami pertimbangkan dengan lebih terperinci.

Mengapa pemfaktoran semula diperlukan?

Terdapat beberapa sebab. Contohnya, mengejar kesederhanaan dan ketepatan kod. Penyokong teori ini percaya bahawa kod harus ringkas yang mungkin, walaupun ia memerlukan berpuluh-puluh baris ulasan untuk memahaminya. Pembangun lain percaya bahawa kod itu harus difaktorkan semula supaya ia boleh difahami dengan bilangan komen yang minimum. Setiap pasukan memilih kedudukannya sendiri, tetapi kita harus ingat bahawa pemfaktoran semula bukanlah pengurangan . Matlamat utamanya adalah untuk memperbaiki struktur kod. Beberapa objektif boleh dimasukkan dalam matlamat global ini:
  1. Pemfaktoran semula meningkatkan pemahaman kod yang ditulis oleh pembangun lain;
  2. Membantu mencari dan membetulkan ralat;
  3. Membolehkan anda meningkatkan kelajuan pembangunan perisian;
  4. Secara keseluruhannya menambah baik komposisi perisian.
Jika pemfaktoran semula tidak dijalankan untuk masa yang lama, kesukaran pembangunan mungkin timbul, sehingga pemberhentian sepenuhnya kerja.

“Kod berbau”

Apabila kod memerlukan pemfaktoran semula mereka mengatakan ia "berbau." Sudah tentu, tidak secara literal, tetapi kod sedemikian benar-benar tidak kelihatan sangat bagus. Di bawah ini kita akan mempertimbangkan teknik pemfaktoran semula utama untuk peringkat awal.

Elemen besar yang tidak perlu

Terdapat kelas yang rumit dan kaedah yang mustahil untuk digunakan dengan berkesan dengan tepat kerana saiznya yang besar.

Kelas besar

Kelas sedemikian mempunyai sejumlah besar baris kod dan banyak kaedah yang berbeza. Biasanya lebih mudah bagi pembangun untuk menambah ciri pada kelas sedia ada daripada mencipta yang baharu, itulah sebabnya ia berkembang. Sebagai peraturan, fungsi kelas ini terlebih beban. Dalam kes ini, mengasingkan sebahagian daripada fungsi ke dalam kelas yang berasingan membantu. Kami akan membincangkan perkara ini dengan lebih terperinci dalam bahagian teknik pemfaktoran semula.

Kaedah Besar

"Bau" ini berlaku apabila pembangun menambahkan fungsi baharu pada kaedah. "Mengapa saya perlu meletakkan semakan parameter dalam kaedah berasingan jika saya boleh menulisnya di sini?", "Mengapa perlu memisahkan kaedah untuk mencari elemen maksimum dalam tatasusunan, mari tinggalkan di sini. Dengan cara ini kod lebih jelas,” dan salah tanggapan lain. Terdapat dua peraturan untuk memfaktorkan semula kaedah yang besar:
  1. Jika, semasa menulis kaedah, anda ingin menambah ulasan pada kod, anda perlu mengasingkan fungsi ini kepada kaedah yang berasingan;
  2. Jika kaedah mengambil lebih daripada 10-15 baris kod, anda harus mengenal pasti tugasan dan subtugasan yang dilakukannya dan cuba mengasingkan subtugasan kepada kaedah yang berasingan.
Beberapa cara untuk menghapuskan kaedah besar:
  • Asingkan bahagian kefungsian kaedah kepada kaedah berasingan;
  • Jika pembolehubah tempatan tidak membenarkan anda mengekstrak sebahagian daripada fungsi, anda boleh menghantar keseluruhan objek kepada kaedah lain.

Menggunakan banyak jenis data primitif

Biasanya, masalah ini berlaku apabila bilangan medan untuk menyimpan data dalam kelas bertambah dari semasa ke semasa. Contohnya, jika anda menggunakan jenis primitif dan bukannya objek kecil untuk menyimpan data (mata wang, tarikh, nombor telefon, dll.) atau pemalar untuk mengekod sebarang maklumat. Amalan yang baik dalam kes ini ialah mengumpulkan medan secara logik dan meletakkannya dalam kelas berasingan (memilih kelas). Anda juga boleh memasukkan kaedah untuk memproses data ini dalam kelas.

Senarai panjang pilihan

Kesilapan yang agak biasa, terutamanya dalam kombinasi dengan kaedah yang besar. Ia biasanya berlaku jika kefungsian kaedah terlebih beban, atau kaedah menggabungkan beberapa algoritma. Senarai panjang parameter sangat sukar untuk difahami, dan kaedah sedemikian menyusahkan untuk digunakan. Oleh itu, adalah lebih baik untuk memindahkan keseluruhan objek. Jika objek tidak mempunyai data yang mencukupi, ia patut menggunakan objek yang lebih umum atau membahagikan fungsi kaedah supaya ia memproses data yang berkaitan secara logik.

Kumpulan data

Kumpulan data yang berkaitan secara logik sering muncul dalam kod. Contohnya, parameter sambungan ke pangkalan data (URL, nama pengguna, kata laluan, nama skema, dll.). Jika tiada satu medan pun boleh dialih keluar daripada senarai elemen, maka senarai itu ialah sekumpulan data yang mesti diletakkan dalam kelas berasingan (pemilihan kelas).

Penyelesaian yang merosakkan konsep OOP

Jenis "bau" ini berlaku apabila pembangun melanggar reka bentuk OOP. Ini berlaku jika dia tidak memahami sepenuhnya keupayaan paradigma ini, menggunakannya secara tidak lengkap atau tidak betul.

Penolakan harta pusaka

Jika subkelas menggunakan bahagian minimum fungsi kelas induk, ia berbau seperti hierarki yang salah. Biasanya, dalam kes ini, kaedah yang tidak perlu hanya tidak ditindih atau pengecualian dibuang. Jika kelas diwarisi daripada kelas lain, ini membayangkan penggunaan hampir lengkap fungsinya. Contoh hierarki yang betul: Bagaimana pemfaktoran semula berfungsi dalam Java - 2 Contoh hierarki yang salah: Bagaimana pemfaktoran semula berfungsi dalam Java - 3

penyataan suis

Apa yang boleh salah dengan pengendali switch? Ia buruk apabila reka bentuknya sangat kompleks. Ini juga termasuk banyak blok bersarang if.

Kelas alternatif dengan antara muka yang berbeza

Beberapa kelas pada asasnya melakukan perkara yang sama, tetapi kaedah mereka dinamakan secara berbeza.

Medan sementara

Jika kelas mengandungi medan sementara yang objek hanya perlukan sekali-sekala, apabila ia diisi dengan nilai, dan selebihnya ia kosong atau, Allah melarang, null, maka kod itu "berbau", dan reka bentuk sedemikian adalah meragukan keputusan.

Bau yang menyukarkan pengubahsuaian

"Bau" ini lebih serius. Selebihnya terutamanya menjejaskan pemahaman kod, manakala ini tidak memungkinkan untuk mengubah suainya. Apabila memperkenalkan sebarang ciri, separuh daripada pembangun akan berhenti, dan separuh akan menjadi gila.

Hierarki warisan selari

Apabila anda mencipta subkelas kelas, anda mesti mencipta subkelas lain kelas lain.

Pengagihan pergantungan seragam

Apabila melakukan sebarang pengubahsuaian, anda perlu mencari semua kebergantungan (kegunaan) kelas ini dan membuat banyak perubahan kecil. Satu perubahan - suntingan dalam banyak kelas.

Pokok pengubahsuaian kompleks

Bau ini adalah bertentangan dengan yang sebelumnya: perubahan mempengaruhi sejumlah besar kaedah kelas yang sama. Sebagai peraturan, kebergantungan dalam kod tersebut adalah melata: setelah menukar satu kaedah, anda perlu membetulkan sesuatu dalam yang lain, dan kemudian dalam yang ketiga, dan seterusnya. Satu kelas - banyak perubahan.

“Bau sampah”

Kategori bau yang agak tidak menyenangkan yang menyebabkan sakit kepala. Tidak berguna, tidak perlu, kod lama. Nasib baik, IDE dan linter moden telah belajar untuk memberi amaran tentang bau sedemikian.

Sebilangan besar komen dalam kaedah

Kaedah ini mempunyai banyak ulasan penjelasan pada hampir setiap baris. Ini biasanya dikaitkan dengan algoritma yang kompleks, jadi adalah lebih baik untuk membahagikan kod kepada beberapa kaedah yang lebih kecil dan memberi mereka nama yang bermakna.

Penduaan kod

Kelas atau kaedah yang berbeza menggunakan blok kod yang sama.

Kelas malas

Kelas menggunakan fungsi yang sangat sedikit, walaupun banyak yang telah dirancang.

Kod yang tidak digunakan

Kelas, kaedah atau pembolehubah tidak digunakan dalam kod dan "berat mati".

Gandingan yang berlebihan

Kategori bau ini dicirikan oleh sejumlah besar sambungan yang tidak perlu dalam kod.

Kaedah pihak ketiga

Kaedah menggunakan data objek lain lebih kerap daripada menggunakan datanya sendiri.

Keintiman yang tidak wajar

Kelas menggunakan medan perkhidmatan dan kaedah kelas lain.

Panggilan kelas panjang

Satu kelas memanggil yang lain, yang meminta data dari yang ketiga, dari yang keempat, dan seterusnya. Rangkaian panggilan yang begitu panjang bermakna tahap pergantungan yang tinggi pada struktur kelas semasa.

Penjual-tugas kelas

Kelas hanya diperlukan untuk menghantar tugasan ke kelas lain. Mungkin ia perlu dikeluarkan?

Teknik Pemfaktoran Semula

Di bawah ini kita akan bercakap tentang teknik pemfaktoran semula awal yang akan membantu menghilangkan bau kod yang diterangkan.

Pemilihan kelas

Kelas melaksanakan terlalu banyak fungsi; sesetengah daripadanya perlu dipindahkan ke kelas lain. Sebagai contoh, terdapat kelas Humanyang turut mengandungi alamat kediaman dan kaedah yang menyediakan alamat penuh:
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();
   }
}
Adalah idea yang baik untuk meletakkan maklumat dan kaedah alamat (tingkah laku pemprosesan data) dalam kelas yang berasingan:
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();
   }
}

Pemilihan kaedah

Jika mana-mana fungsi boleh dikumpulkan dalam kaedah, ia harus diletakkan dalam kaedah yang berasingan. Sebagai contoh, kaedah yang mengira punca-punca persamaan kuadratik:
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");
    }
}
Mari alihkan pengiraan ketiga-tiga pilihan yang mungkin ke dalam kaedah berasingan:
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");
}
Kod untuk setiap kaedah telah menjadi lebih pendek dan jelas.

Memindahkan keseluruhan objek

Apabila memanggil kaedah dengan parameter, anda kadangkala boleh melihat kod seperti ini:
public void employeeMethod(Employee employee) {
    // Некоторые действия
    double yearlySalary = employee.getYearlySalary();
    double awards = employee.getAwards();
    double monthlySalary = getMonthlySalary(yearlySalary, awards);
    // Продолжение обработки
}

public double getMonthlySalary(double yearlySalary, double awards) {
     return (yearlySalary + awards)/12;
}
Dalam kaedah itu, employeeMethodsebanyak 2 baris diperuntukkan untuk mendapatkan nilai dan menyimpannya dalam pembolehubah primitif. Kadangkala reka bentuk sedemikian mengambil masa sehingga 10 baris. Lebih mudah untuk menghantar objek itu sendiri kepada kaedah, dari mana anda boleh mengekstrak data yang diperlukan:
public void employeeMethod(Employee employee) {
    // Некоторые действия
    double monthlySalary = getMonthlySalary(employee);
    // Продолжение обработки
}

public double getMonthlySalary(Employee employee) {
    return (employee.getYearlySalary() + employee.getAwards())/12;
}
Ringkas, ringkas dan padat.

Pengumpulan medan logik dan meletakkannya dalam kelas yang berasingan

Walaupun contoh di atas adalah sangat mudah dan apabila melihatnya ramai yang mungkin bertanya soalan "Siapa sebenarnya yang melakukan ini?", ramai pembangun, disebabkan oleh ketidakpedulian, keengganan untuk memfaktorkan semula kod, atau hanya "Ia akan berjaya," membuat ralat struktur yang serupa.

Mengapa pemfaktoran semula berkesan

Hasil pemfaktoran semula yang baik adalah program yang kodnya mudah dibaca, pengubahsuaian pada logik program tidak menjadi ancaman, dan pengenalan ciri-ciri baru tidak berubah menjadi penghuraian kod neraka, tetapi aktiviti yang menyenangkan selama beberapa hari . Pemfaktoran semula tidak boleh digunakan jika lebih mudah untuk menulis semula atur cara dari awal. Sebagai contoh, pasukan menganggarkan kos buruh untuk menghurai, menganalisis dan memfaktorkan semula kod lebih tinggi daripada untuk melaksanakan fungsi yang sama dari awal. Atau kod yang perlu difaktorkan semula mempunyai banyak ralat yang sukar untuk dinyahpepijat. Mengetahui cara menambah baik struktur kod adalah wajib dalam kerja pengaturcara. Nah, adalah lebih baik untuk mempelajari pengaturcaraan Java di JavaRush - kursus dalam talian dengan penekanan pada latihan. 1200+ tugasan dengan pengesahan segera, kira-kira 20 projek mini, tugasan permainan - semua ini akan membantu anda berasa yakin dalam pengekodan. Masa terbaik untuk bermula ialah sekarang :) Как устроен рефакторинг в Java - 4

Sumber untuk menyelam lebih lanjut ke dalam pemfaktoran semula

Buku yang paling terkenal tentang pemfaktoran semula ialah “Pemfaktoran Semula. Memperbaik Reka Bentuk Kod Sedia Ada” oleh Martin Fowler. Terdapat juga penerbitan yang menarik mengenai pemfaktoran semula, yang ditulis berdasarkan buku sebelumnya - "Pemfaktoran Semula dengan Corak" oleh Joshua Kiriewski. Bercakap tentang templat. Apabila pemfaktoran semula, ia sentiasa sangat berguna untuk mengetahui corak reka bentuk aplikasi asas. Buku-buku hebat ini akan membantu dengan ini:
  1. "Corak Reka Bentuk" - oleh Eric Freeman, Elizabeth Freeman, Kathy Sierra, Bert Bates daripada siri Head First;
  2. "Kod Boleh Dibaca, atau Pengaturcaraan sebagai Seni" - Dustin Boswell, Trevor Faucher.
  3. "Kod Sempurna" oleh Steve McConnell, yang menggariskan prinsip kod yang cantik dan elegan.
Nah, beberapa artikel tentang pemfaktoran semula:
  1. Hell of a task: mari mulakan refactoring legacy code ;
  2. Pemfaktoran semula ;
  3. Pemfaktoran semula untuk semua orang .
    Komen
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION