JavaRush /Java Blog /Random-ID /Aturan penulisan kode: mulai dari membuat sistem hingga b...

Aturan penulisan kode: mulai dari membuat sistem hingga bekerja dengan objek

Dipublikasikan di grup Random-ID
Selamat siang semuanya: hari ini saya ingin berbicara dengan Anda tentang menulis kode dengan benar. Ketika saya pertama kali memulai pemrograman, tidak tertulis dengan jelas di mana pun Anda dapat menulis seperti ini, dan jika Anda menulis seperti ini, saya akan menemukan Anda dan…. Akibatnya, banyak pertanyaan muncul di kepala saya: bagaimana cara menulis yang benar, prinsip apa yang harus diikuti di bagian program ini atau itu, dll. Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 1Ya, tidak semua orang ingin langsung mendalami buku seperti Clean Code, karena banyak yang tertulis di dalamnya, tapi pada awalnya hanya sedikit yang jelas. Dan pada saat Anda selesai membaca, Anda dapat menghilangkan semua keinginan untuk membuat kode. Jadi berdasarkan penjelasan di atas, hari ini saya ingin memberi Anda panduan kecil (serangkaian rekomendasi kecil) untuk menulis kode tingkat tinggi. Pada artikel ini kita akan membahas aturan dan konsep dasar yang berhubungan dengan pembuatan sistem dan bekerja dengan antarmuka, kelas, dan objek. Membaca materi ini tidak akan menyita banyak waktu Anda dan semoga tidak membuat Anda bosan. Saya akan membahas dari atas ke bawah, yaitu dari struktur umum aplikasi ke detail yang lebih spesifik. Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 2

Sistem

Karakteristik umum yang diinginkan dari sistem adalah:
  • kompleksitas minimal - proyek yang terlalu rumit harus dihindari. Yang utama adalah kesederhanaan dan kejelasan (terbaik = sederhana);
  • kemudahan pemeliharaan - saat membuat aplikasi, Anda harus ingat bahwa aplikasi tersebut perlu didukung (walaupun itu bukan Anda), sehingga kodenya harus jelas dan jelas;
  • kopling lemah adalah jumlah minimum koneksi antara berbagai bagian program (penggunaan prinsip OOP secara maksimal);
  • dapat digunakan kembali - merancang sistem dengan kemampuan untuk menggunakan kembali fragmennya dalam aplikasi lain;
  • portabilitas - sistem harus mudah beradaptasi dengan lingkungan lain;
  • gaya tunggal - merancang sistem dengan gaya yang sama dalam fragmennya yang berbeda;
  • ekstensibilitas (skalabilitas) - meningkatkan sistem tanpa mengganggu struktur dasarnya (jika Anda menambah atau mengubah sebuah fragmen, ini tidak akan mempengaruhi sisanya).
Hampir tidak mungkin membangun aplikasi yang tidak memerlukan modifikasi, tanpa menambahkan fungsionalitas. Kami perlu terus memperkenalkan elemen-elemen baru agar gagasan kami dapat mengikuti perkembangan zaman. Dan di sinilah skalabilitas berperan . Skalabilitas pada dasarnya adalah perluasan aplikasi, penambahan fungsionalitas baru, bekerja dengan lebih banyak sumber daya (atau, dengan kata lain, dengan lebih banyak beban). Artinya, kita harus mematuhi beberapa aturan, seperti mengurangi kopling sistem dengan meningkatkan modularitas, sehingga lebih mudah untuk menambahkan logika baru.

Tahapan desain sistem

  1. Sistem perangkat lunak - merancang aplikasi dalam bentuk umum.
  2. Pemisahan menjadi subsistem/paket - mendefinisikan bagian-bagian yang dapat dipisahkan secara logis dan menentukan aturan interaksi di antara mereka.
  3. Membagi subsistem ke dalam kelas - membagi bagian sistem ke dalam kelas dan antarmuka tertentu, serta menentukan interaksi di antara mereka.
  4. Membagi kelas menjadi beberapa metode adalah definisi lengkap tentang metode yang diperlukan untuk suatu kelas, berdasarkan tugas kelas tersebut. Desain metode - definisi rinci tentang fungsionalitas masing-masing metode.
Biasanya, pengembang biasa bertanggung jawab atas desain, dan arsitek aplikasi bertanggung jawab atas hal-hal yang dijelaskan di atas.

Prinsip dan konsep utama desain sistem

Idiom inisialisasi malas Sebuah aplikasi tidak menghabiskan waktu membuat objek sampai digunakan, yang mempercepat proses inisialisasi dan mengurangi beban pengumpul sampah. Namun Anda tidak boleh melangkah terlalu jauh, karena hal ini dapat menyebabkan pelanggaran modularitas. Mungkin ada baiknya memindahkan semua langkah desain ke bagian tertentu, misalnya, utama, atau ke kelas yang berfungsi seperti pabrik . Salah satu aspek kode yang baik adalah tidak adanya kode boilerplate yang sering diulang. Biasanya, kode tersebut ditempatkan di kelas terpisah sehingga dapat dipanggil pada waktu yang tepat. AOP Secara terpisah, saya ingin menyebutkan pemrograman berorientasi aspek . Ini adalah pemrograman dengan memperkenalkan logika end-to-end, yaitu kode berulang dimasukkan ke dalam kelas - aspek, dan dipanggil ketika kondisi tertentu tercapai. Misalnya ketika mengakses suatu metode dengan nama tertentu atau mengakses variabel dengan tipe tertentu. Terkadang aspeknya bisa membingungkan, karena tidak jelas dari mana kode tersebut dipanggil, namun demikian, ini adalah fungsi yang sangat berguna. Khususnya, saat melakukan caching atau logging: kami menambahkan fungsi ini tanpa menambahkan logika tambahan ke kelas reguler. Anda dapat membaca lebih lanjut tentang OAP di sini . 4 Aturan Mendesain Arsitektur Sederhana Menurut Kent Beck
  1. Ekspresif - kebutuhan akan tujuan kelas yang diungkapkan dengan jelas, dicapai melalui penamaan yang benar, ukuran kecil dan kepatuhan pada prinsip tanggung jawab tunggal (kita akan melihatnya lebih detail di bawah).
  2. Minimal kelas dan metode - dalam keinginan Anda untuk membagi kelas menjadi sekecil dan searah mungkin, Anda bisa melangkah terlalu jauh (antipattern - shotgunning). Prinsip ini mengharuskan sistem tetap kompak dan tidak berlebihan, menciptakan kelas untuk setiap bersin.
  3. Kurangnya duplikasi - kode tambahan yang membingungkan merupakan tanda desain sistem yang buruk dan dipindahkan ke tempat terpisah.
  4. Eksekusi semua pengujian - sistem yang telah lulus semua pengujian dikendalikan, karena perubahan apa pun dapat menyebabkan kegagalan pengujian, yang dapat menunjukkan kepada kita bahwa perubahan dalam logika internal metode juga menyebabkan perubahan dalam perilaku yang diharapkan. .
SOLID Saat merancang suatu sistem, ada baiknya mempertimbangkan prinsip SOLID yang terkenal: S - tanggung jawab tunggal - prinsip tanggung jawab tunggal; O - buka-tutup - prinsip keterbukaan/kedekatan; L - Substitusi Liskov - Prinsip substitusi Barbara Liskov; I - segregasi antarmuka - prinsip pemisahan antarmuka; D - inversi ketergantungan - prinsip inversi ketergantungan; Kami tidak akan membahas masing-masing prinsip secara spesifik (ini sedikit di luar cakupan artikel ini, namun Anda dapat mengetahui lebih lanjut di sini

Antarmuka

Mungkin salah satu tahapan terpenting dalam membuat kelas yang memadai adalah membuat antarmuka yang memadai yang akan mewakili abstraksi yang baik yang menyembunyikan detail implementasi kelas, dan pada saat yang sama akan mewakili sekelompok metode yang jelas konsisten satu sama lain. . Mari kita lihat lebih dekat salah satu prinsip SOLID - segregasi antarmuka : klien (kelas) tidak boleh mengimplementasikan metode yang tidak perlu yang tidak akan mereka gunakan. Artinya, jika kita berbicara tentang membangun antarmuka dengan jumlah metode minimum yang ditujukan untuk melakukan satu-satunya tugas antarmuka ini (bagi saya, ini sangat mirip dengan tanggung jawab tunggal ), lebih baik membuat beberapa yang lebih kecil yang bukannya satu antarmuka yang membengkak. Untungnya, sebuah kelas dapat mengimplementasikan lebih dari satu antarmuka, seperti halnya dengan pewarisan. Anda juga perlu mengingat tentang penamaan antarmuka yang benar: nama tersebut harus mencerminkan tugasnya seakurat mungkin. Dan, tentu saja, semakin pendek, semakin sedikit kebingungan yang ditimbulkannya. Pada tingkat antarmuka biasanya komentar untuk dokumentasi ditulis , yang, pada gilirannya, membantu kami menjelaskan secara rinci apa yang harus dilakukan metode, argumen apa yang diperlukan, dan apa yang akan dikembalikan.

Kelas

Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 3Mari kita lihat organisasi internal kelas. Atau lebih tepatnya, beberapa pandangan dan aturan yang harus diikuti ketika membangun kelas. Biasanya, kelas harus dimulai dengan daftar variabel, disusun dalam urutan tertentu:
  1. konstanta statis publik;
  2. konstanta statis pribadi;
  3. variabel instan pribadi.
Berikutnya adalah berbagai konstruktor dalam urutan argumen yang lebih sedikit hingga lebih banyak. Diikuti oleh metode dari akses yang lebih terbuka hingga yang paling tertutup: sebagai aturan, metode pribadi yang menyembunyikan implementasi beberapa fungsi yang ingin kita batasi berada di bagian paling bawah.

Ukuran kelas

Sekarang saya ingin berbicara tentang ukuran kelas. Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 4Mari kita ingat salah satu prinsip SOLID - tanggung jawab tunggal . Tanggung jawab tunggal - prinsip tanggung jawab tunggal. Dinyatakan bahwa setiap objek hanya memiliki satu tujuan (tanggung jawab), dan logika semua metodenya ditujukan untuk memastikannya. Artinya, berdasarkan hal ini, kita harus menghindari kelas yang besar dan membengkak (yang pada dasarnya merupakan antipola - "objek ilahi"), dan jika kita memiliki banyak metode logika yang beragam dan heterogen di suatu kelas, kita perlu berpikir tentang memecahnya menjadi beberapa bagian logis (kelas). Hal ini, pada gilirannya, akan meningkatkan keterbacaan kode, karena kita tidak memerlukan banyak waktu untuk memahami tujuan suatu metode jika kita mengetahui perkiraan tujuan kelas tertentu. Anda juga perlu memperhatikan nama kelasnya : nama tersebut harus mencerminkan logika yang dikandungnya. Katakanlah, jika kita memiliki kelas yang namanya memiliki 20+ kata, kita perlu memikirkan tentang pemfaktoran ulang. Setiap kelas yang menghargai diri sendiri tidak boleh memiliki variabel internal sebanyak itu. Faktanya, setiap metode bekerja dengan salah satu atau beberapa metode, yang menyebabkan penggabungan yang lebih besar di dalam kelas (yang memang seharusnya terjadi, karena kelas harus menjadi satu kesatuan). Akibatnya, peningkatan koherensi suatu kelas menyebabkan penurunan kelas tersebut, dan, tentu saja, jumlah kelas kita bertambah. Bagi sebagian orang, hal ini menjengkelkan; mereka perlu lebih sering masuk kelas untuk melihat cara kerja tugas besar tertentu. Antara lain, setiap kelas adalah modul kecil yang minimal harus terhubung satu sama lain. Isolasi ini mengurangi jumlah perubahan yang perlu kita lakukan saat menambahkan logika tambahan ke kelas.

Objek

Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 5

Enkapsulasi

Di sini pertama-tama kita akan membicarakan salah satu prinsip OOP - enkapsulasi . Jadi, menyembunyikan implementasi tidak berarti membuat lapisan metode antar variabel (membatasi akses tanpa berpikir panjang melalui metode tunggal, pengambil dan penyetel, yang tidak baik, karena inti enkapsulasi hilang). Menyembunyikan akses ditujukan untuk membentuk abstraksi, yaitu kelas menyediakan metode konkrit umum yang digunakan untuk bekerja dengan data kami. Namun pengguna tidak perlu tahu persis bagaimana kami bekerja dengan data ini - data ini berfungsi, dan itu tidak masalah.

Hukum Demeter

Anda juga dapat mempertimbangkan Hukum Demeter: ini adalah seperangkat aturan kecil yang membantu mengelola kompleksitas di tingkat kelas dan metode. Jadi, mari kita asumsikan kita memiliki sebuah objek Cardan objek tersebut memiliki metode - move(Object arg1, Object arg2). Menurut Hukum Demeter, metode ini terbatas pada pemanggilan:
  • metode objek itu sendiri Car(dengan kata lain, ini);
  • metode objek yang dibuat di move;
  • metode meneruskan objek sebagai argumen - arg1, arg2;
  • metode objek internal Car(sama dengan ini).
Dengan kata lain, hukum Demeter seperti aturan anak-anak - Anda dapat berbicara dengan teman, tetapi tidak dengan orang asing .

Struktur data

Struktur data adalah kumpulan elemen terkait. Ketika mempertimbangkan suatu objek sebagai struktur data, itu adalah sekumpulan elemen data yang diproses oleh metode, yang keberadaannya tersirat secara implisit. Artinya, suatu objek yang tujuannya adalah untuk menyimpan dan mengoperasikan (memproses) data yang disimpan. Perbedaan utama dari objek biasa adalah bahwa objek adalah sekumpulan metode yang beroperasi pada elemen data yang keberadaannya tersirat. Apakah kamu mengerti? Dalam objek biasa, aspek utamanya adalah metode, dan variabel internal ditujukan untuk pengoperasian yang benar, tetapi dalam struktur data yang terjadi adalah sebaliknya: metode mendukung dan membantu bekerja dengan elemen tersimpan, yang merupakan elemen utama di sini. Salah satu jenis struktur data adalah Data Transfer Object (DTO) . Ini adalah kelas dengan variabel publik dan tidak ada metode (atau hanya metode baca/tulis) yang meneruskan data saat bekerja dengan database, bekerja dengan penguraian pesan dari soket, dll. Biasanya, data dalam objek tersebut tidak disimpan untuk waktu yang lama dan bersifat segera dikonversi menjadi entitas tempat aplikasi kita bekerja. Entitas, pada gilirannya, juga merupakan struktur data, namun tujuannya adalah untuk berpartisipasi dalam logika bisnis di berbagai tingkat aplikasi, sedangkan DTO adalah untuk mengangkut data ke/dari aplikasi. Contoh DTO:
@Setter
@Getter
@NoArgsConstructor
public class UserDto {
    private long id;
    private String firstName;
    private String lastName;
    private String email;
    private String password;
}
Semuanya tampak jelas, tapi di sini kita belajar tentang keberadaan hibrida. Hibrid adalah objek yang berisi metode untuk menangani logika penting dan menyimpan elemen internal serta metode akses (dapatkan/set) ke dalamnya. Objek seperti itu berantakan dan menyulitkan penambahan metode baru. Anda tidak boleh menggunakannya, karena tidak jelas tujuannya - menyimpan elemen atau menjalankan semacam logika. Anda dapat membaca tentang kemungkinan jenis objek di sini .

Prinsip membuat variabel

Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 6Mari kita pikirkan sedikit tentang variabel, atau lebih tepatnya, pikirkan tentang apa prinsip pembuatannya:
  1. Idealnya, Anda harus mendeklarasikan dan menginisialisasi variabel segera sebelum menggunakannya (daripada membuat dan melupakannya).
  2. Jika memungkinkan, deklarasikan variabel sebagai final untuk mencegah nilainya berubah setelah inisialisasi.
  3. Jangan lupakan variabel counter (biasanya kita menggunakannya dalam beberapa jenis loop for, yaitu kita tidak boleh lupa untuk meresetnya, jika tidak maka akan merusak seluruh logika kita).
  4. Anda harus mencoba menginisialisasi variabel di konstruktor.
  5. Jika ada pilihan antara menggunakan objek dengan atau tanpa referensi ( new SomeObject()), pilih tanpa ( ), karena objek ini, setelah digunakan, akan dihapus pada pengumpulan sampah berikutnya dan tidak akan menyia-nyiakan sumber daya.
  6. Buatlah masa pakai variabel sesingkat mungkin (jarak antara pembuatan variabel dan akses terakhir).
  7. Inisialisasi variabel yang digunakan dalam perulangan tepat sebelum perulangan, bukan di awal metode yang berisi perulangan.
  8. Selalu mulai dengan cakupan yang paling terbatas dan perluas hanya jika diperlukan (Anda harus mencoba membuat variabel selokal mungkin).
  9. Gunakan setiap variabel hanya untuk satu tujuan.
  10. Hindari variabel dengan makna tersembunyi (variabel terpecah di antara dua tugas, yang berarti jenisnya tidak cocok untuk menyelesaikan salah satunya).
Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 7

Metode

Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 8Mari kita langsung ke implementasi logika kita, yaitu metode.
  1. Aturan pertama adalah kekompakan. Idealnya, satu metode tidak boleh melebihi 20 baris, jadi jika, katakanlah, metode publik “membengkak” secara signifikan, Anda perlu mempertimbangkan untuk memindahkan logika terpisah ke metode privat.

  2. Aturan kedua adalah bahwa blok dalam perintah if, else, whiledan seterusnya tidak boleh bertumpuk tinggi: hal ini secara signifikan mengurangi keterbacaan kode. Idealnya, sarang tidak boleh lebih dari dua blok {}.

    Dianjurkan juga untuk membuat kode di blok ini kompak dan sederhana.

  3. Aturan ketiga adalah suatu metode harus melakukan hanya satu operasi. Artinya, jika suatu metode menjalankan logika yang kompleks dan bervariasi, kami membaginya menjadi submetode. Akibatnya, metode itu sendiri akan menjadi fasad, yang tujuannya adalah untuk memanggil semua operasi lain dalam urutan yang benar.

    Namun bagaimana jika operasinya tampak terlalu sederhana untuk membuat metode terpisah? Ya, terkadang hal ini tampak seperti menembakkan burung pipit dari meriam, namun metode kecil memberikan sejumlah manfaat:

    • membaca kode lebih mudah;
    • metode cenderung menjadi lebih kompleks seiring berjalannya pengembangan, dan jika metode awalnya sederhana, maka fungsionalitasnya akan menjadi sedikit lebih rumit;
    • menyembunyikan detail implementasi;
    • memfasilitasi penggunaan kembali kode;
    • keandalan kode yang lebih tinggi.
  4. Aturan ke bawah adalah bahwa kode harus dibaca dari atas ke bawah: semakin rendah, semakin besar kedalaman logikanya, dan sebaliknya, semakin tinggi, semakin abstrak metodenya. Misalnya, perintah saklar sangat tidak ringkas dan tidak diinginkan, namun jika Anda tidak dapat melakukannya tanpa menggunakan saklar, Anda harus mencoba memindahkannya serendah mungkin, ke metode tingkat terendah.

  5. Argumen metode - berapa banyak yang ideal? Idealnya, tidak ada sama sekali)) Tapi apakah itu benar-benar terjadi? Namun, Anda harus berusaha memilikinya sesedikit mungkin, karena semakin sedikit jumlahnya, semakin mudah menggunakan metode ini dan semakin mudah untuk mengujinya. Jika ragu, coba tebak semua skenario penggunaan metode dengan argumen masukan dalam jumlah besar.

  6. Secara terpisah, saya ingin menyoroti metode yang memiliki tanda boolean sebagai argumen masukan , karena ini secara alami menyiratkan bahwa metode ini mengimplementasikan lebih dari satu operasi (jika benar maka satu operasi, salah - operasi lainnya). Seperti yang saya tulis di atas, ini tidak baik dan sebaiknya dihindari sebisa mungkin.

  7. Jika suatu metode memiliki sejumlah besar argumen masuk (nilai ekstremnya adalah 7, tetapi Anda harus memikirkannya setelah 2-3), Anda perlu mengelompokkan beberapa argumen dalam objek terpisah.

  8. Jika ada beberapa metode serupa (kelebihan beban) , maka parameter serupa harus diteruskan dalam urutan yang sama: ini meningkatkan keterbacaan dan kegunaan.

  9. Saat Anda meneruskan parameter ke suatu metode, Anda harus yakin bahwa semuanya akan digunakan, jika tidak, argumennya untuk apa? Hentikan itu dari antarmuka dan selesai.

  10. try/catchSifatnya tidak terlihat bagus, jadi langkah yang baik adalah memindahkannya ke metode perantara yang terpisah (metode untuk menangani pengecualian):

    public void exceptionHandling(SomeObject obj) {
        try {
            someMethod(obj);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
Saya berbicara tentang pengulangan kode di atas, tetapi saya akan menambahkannya di sini: Jika kita memiliki beberapa metode dengan bagian kode yang berulang, kita perlu memindahkannya ke metode terpisah, yang akan meningkatkan kekompakan metode dan metode. kelas. Dan jangan lupa tentang nama yang benar. Saya akan memberi tahu Anda detail penamaan kelas, antarmuka, metode, dan variabel yang benar di bagian artikel selanjutnya. Dan hanya itu yang saya punya untuk hari ini. Aturan penulisan kode: dari membuat sistem hingga bekerja dengan objek - 9Aturan kode: kekuatan penamaan yang tepat, komentar baik dan buruk
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION