JavaRush /Java Blog /Random-ID /Rehat kopi #64. Cara menulis kode bersih. Mengapa Java le...

Rehat kopi #64. Cara menulis kode bersih. Mengapa Java lebih baik daripada C++ untuk sistem latensi rendah

Dipublikasikan di grup Random-ID

Cara menulis kode bersih

Sumber: Dev.to Menulis kode yang bersih seperti menulis puisi. Ini adalah puisi yang harus ringkas, dapat dimengerti, dan dapat diubah. Kode yang bersih menyiratkan organisasi yang terukur. Artinya melakukan perubahan tidak menimbulkan kekacauan. Kemampuan untuk menulis kode seperti itu adalah salah satu kualitas utama dari seorang pengembang berpengalaman. Setelah beberapa orang merekomendasikan saya untuk membaca buku Clean Code, akhirnya saya memberanikan diri untuk membacanya. Ternyata ini adalah salah satu buku yang sampulnya benar-benar sesuai dengan hype yang ada di sekitarnya. Rekomendasi dalam buku ini jelas, spesifik, praktis, bahkan disajikan dengan humor. Hari ini saya ingin berbagi dengan Anda kesimpulan utama dari buku ini.Rehat kopi #64.  Cara menulis kode bersih.  Mengapa Java lebih baik daripada C++ untuk sistem latensi rendah - 1

1. Kode tidak hanya harus berfungsi, tetapi juga dapat dibaca

Sebagian besar biaya perangkat lunak terkait dengan dukungan jangka panjang. Oleh karena itu, kode yang Anda tulis harus mengungkapkan maksud Anda dengan jelas. Hal ini harus dilakukan agar pengembang baru yang bergabung dengan tim dapat dengan mudah memahami apa yang sebenarnya terjadi dalam kode dan alasannya. Semakin mudah dimengerti kode yang penulis tulis, semakin sedikit waktu yang dibutuhkan pengembang lain untuk memahaminya. Hal ini mengurangi cacat dan biaya pemeliharaan. Bagaimana cara mencapainya? Penamaan yang baik + kelas dan fungsi dengan tanggung jawab tunggal + tes menulis.

2. Nanti berarti tidak pernah

Jujur saja: kita semua terkadang berjanji pada diri sendiri bahwa kita akan kembali lagi dan membersihkan kodenya nanti, tapi kita akhirnya melupakannya. Jangan tinggalkan potongan kode tidak berguna yang tidak diperlukan lagi. Mereka membingungkan pengembang lain dan tidak ada nilainya. Oleh karena itu, saat melakukan perubahan fungsionalitas, selalu hapus kode lama. Jika ada yang rusak di suatu tempat, pengujian akan tetap menunjukkannya. Bagaimana cara mencapainya? Menghapus kode bisa jadi menakutkan, terutama pada arsitektur besar. Jadi pengujian adalah kuncinya di sini. Mereka memungkinkan Anda menghapus kode dengan percaya diri.

3. Fitur harus kecil

Aturan pertama dalam penulisan fungsi adalah ukurannya harus kecil, maksimal sekitar 20 baris . Semakin kecil fungsinya dan semakin terfokus pada satu tugas, semakin mudah menemukan nama yang bagus untuk tugas tersebut. Sedangkan untuk argumen fungsi, bilangan idealnya adalah 0. Berikutnya adalah 1, 2, namun Anda sebaiknya mencoba untuk tidak memiliki lebih dari 3 argumen. Bagaimana cara mencapainya? Fungsi harus ditulis sesuai dengan prinsip tanggung jawab tunggal dan terbuka/tertutup.

4. Duplikasi kode itu buruk

Duplikasi adalah musuh dari sistem yang terorganisir dengan baik. Ini adalah kerja ekstra, risiko ekstra, dan kerumitan ekstra yang tidak perlu. Apa yang harus dilakukan tentang hal itu? Pastikan kode Anda ditulis sesuai dengan prinsip KERING, terisolasi dan modular.

5. Satu-satunya komentar yang bagus adalah komentar yang Anda temukan cara untuk tidak menulisnya.

“Tidak ada yang lebih berguna daripada memberikan komentar yang baik di tempat yang tepat. Namun komentar, bahkan dalam skenario terbaik sekalipun, adalah tindakan jahat yang perlu dilakukan.” Komentar dimaksudkan untuk mengimbangi ketidakmampuan kami mengungkapkan pemikiran kami dalam kode. Artinya, ini awalnya merupakan pengakuan kekalahan. Ya, kita harus menggunakannya karena kita tidak selalu bisa memperjelas niat kita dengan kode, tapi itu bukan alasan untuk merayakannya. Soalnya, komentar sering kali bohong. Tidak selalu dan tidak disengaja, tapi terlalu sering. Semakin lama komentar tersebut dan semakin jauh dari kode yang dijelaskan, semakin besar kemungkinan komentar tersebut salah. Alasannya sederhana: pemrogram tidak dapat mengelola kode dan semua komentar dengan baik. Oleh karena itu, sering kali komentar dipisahkan dari kode yang dirujuknya dan menjadi anotasi yatim piatu dengan presisi minimal. Apa yang harus dilakukan tentang hal itu? Metode penamaan deskriptif harus digunakan. Saat Anda membaca nama suatu variabel, Anda harus segera memahami apa itu. Pengujian juga diperlukan agar pengembang lain memahami fungsi mana yang paling penting.

6. Objek mengungkapkan perilaku, tapi bukan data.

Sebuah modul tidak boleh mengetahui tentang internal objek yang dimanipulasinya. Objek menyembunyikan datanya dan mengungkapkan operasinya. Ini berarti bahwa suatu objek tidak boleh mengekspos struktur internalnya melalui metode pengakses. Tidak semua orang perlu melihat Anda telanjang. Apa yang harus dilakukan tentang hal itu? Ruang lingkup variabel harus selokal mungkin agar tidak memaparkan lebih dari yang diperlukan.

7. Pengujian

Kode pengujian sama pentingnya dengan apa yang dimasukkan ke dalam produksi. Oleh karena itu, ia harus berubah dan tumbuh seiring berkembangnya proyek. Pengujian menjaga kode Anda tetap fleksibel, mudah dipelihara, dan dapat digunakan kembali. Tanpa mereka, perubahan apa pun dapat mengakibatkan bug. Pengujian memungkinkan Anda membersihkan kode tanpa takut ada yang rusak. Oleh karena itu, menjaga kemurnian pengujian sangatlah penting. Kebersihan tes memastikan keterbacaannya. Tes adalah kesempatan untuk menjelaskan kepada pengembang lain dalam bahasa sederhana maksud pembuat kode. Oleh karena itu, kami hanya menguji satu konsep di setiap fungsi pengujian. Hal ini membuat tes menjadi deskriptif, lebih mudah dibaca, dan jika gagal, lebih mudah untuk melacak alasannya. Bagaimana cara mencapainya? Seseorang harus mengikuti prinsip tes PERTAMA yang bersih . Tes harus:
  • Cepat. Tes harus berjalan cepat. Jika Anda harus menunggu terlalu lama untuk menjalankan pengujian, kecil kemungkinan Anda akan menjalankannya lebih sering.
  • Mandiri/terisolasi (Mandiri). Pengujian harus diisolasi dan independen satu sama lain.
  • Dapat diulang. Pengujian harus dapat diulangi di lingkungan apa pun—pengembangan, pementasan, dan produksi.
  • Memvalidasi Diri. Hasil pengujian harus berupa nilai Boolean. Tes harus lulus atau gagal.
  • Menyeluruh. Kita harus berusaha untuk mencakup semua kasus edge, semua masalah keamanan, setiap kasus penggunaan (use case) dan jalur bahagia (skenario yang paling menguntungkan untuk kode) dengan pengujian.

8. Menangani kesalahan dan pengecualian

Setiap pengecualian yang Anda berikan harus memberikan konteks yang cukup untuk menentukan sumber dan lokasi kesalahan. Biasanya Anda memiliki jejak tumpukan pengecualian apa pun, namun jejak tumpukan tidak akan memberi tahu Anda tujuan operasi yang gagal. Jika memungkinkan, hindari meneruskan null dalam kode Anda. Jika Anda tergoda untuk mengembalikan null dari suatu metode, pertimbangkan untuk memberikan pengecualian. Jadikan penanganan kesalahan sebagai tugas terpisah yang dapat dilihat secara independen dari logika utama. Bagaimana cara mencapainya? Buat pesan kesalahan yang informatif dan sampaikan pesan tersebut beserta pengecualian Anda. Tentukan operasi yang gagal dan jenis kesalahannya.

9. Kelas

Kelas harus kecil. Namun bukan baris kode yang perlu diperhitungkan, melainkan tanggung jawab. Nama kelas adalah kunci untuk menggambarkan tanggung jawab mereka. Sistem kita harus terdiri dari banyak kelas kecil, bukan beberapa kelas besar. Setiap kelas kecil tersebut harus merangkum satu tanggung jawab. Hanya boleh ada satu alasan spesifik untuk keberadaan setiap kelas, dan setiap kelas harus "bekerja sama" dengan beberapa kelas lain untuk mencapai perilaku sistem yang diinginkan. Jarang ada alasan bagus untuk membuat variabel publik. Melemahkan enkapsulasi selalu merupakan pilihan terakhir. Selain itu, variabel instan harus sedikit. Desain perangkat lunak yang baik memungkinkan perubahan dilakukan tanpa investasi besar atau pengerjaan ulang. Mempersempit rentang variabel membuat tugas ini lebih mudah. Bagaimana cara mencapainya? Pemisahan perhatian adalah salah satu teknik desain tertua dan terpenting. Kelas harus dibuka untuk perluasan, tetapi ditutup untuk modifikasi. Dalam sistem yang ideal, kami mengaktifkan fitur-fitur baru dengan memperluas sistem, bukan dengan membuat perubahan pada kode yang sudah ada.

10. Pemformatan

Setiap baris kosong merupakan isyarat visual untuk membantu mengidentifikasi bahwa konsep baru yang terpisah telah dimulai. Variabel lokal harus muncul di bagian atas fungsi. Variabel instan harus dideklarasikan di bagian atas kelas. Garis pendek lebih baik daripada garis panjang. Biasanya batasannya adalah 100-120 karakter, sebaiknya jangan diperpanjang. Bagaimana cara mencapainya? Sebagian besar parameter dapat diteruskan ke linter di CI atau editor teks Anda. Gunakan alat ini untuk membuat kode Anda sebersih mungkin.

Prinsip Pengembangan Program

Gunakan teknik berikut dan kode Anda akan selalu bersih: Memberi nama variabel. Memilih nama yang tepat (penamaan yang baik) sangat penting agar kode dapat dibaca dan dipelihara. “Anda harus memilih nama untuk suatu variabel dengan penuh tanggung jawab seperti yang Anda lakukan untuk anak sulung Anda.” Memilih nama yang baik seringkali menjadi tantangan bagi pengembang. Hal ini memerlukan keterampilan deskriptif yang baik dan latar belakang budaya yang sama. Kode bersih adalah kode yang dibaca dan diperbaiki oleh pengembang yang sama sekali berbeda. Nama variabel, fungsi atau kelas harus menjawab semua pertanyaan dasar: mengapa entitas ini ada, apa dan bagaimana penggunaannya. Jika sebuah nama memerlukan komentar, berarti nama tersebut tidak cukup mengungkapkan esensi dari apa yang digambarkannya. Nama yang lebih panjang lebih penting daripada nama yang lebih pendek, dan nama apa pun yang dapat dicari lebih baik daripada nama yang konstan. Nama satu huruf hanya dapat digunakan sebagai variabel lokal di dalam metode pendek: panjang nama harus sesuai dengan cakupannya. Nama metode harus berupa kata kerja atau frasa kata kerja; nama kelas tidak boleh berupa kata kerja. Ketergantungan harus diminimalkan. Lebih baik mengandalkan apa yang Anda kendalikan daripada apa yang tidak bisa Anda kendalikan. Kalau tidak, hal-hal ini akan mengendalikan Anda. Ketepatan. Setiap bagian kode harus berada di tempat yang diharapkan pembaca dapat menemukannya. Navigasi melalui basis kode harus intuitif, dan niat pengembang harus jelas. Pembersihan. Jangan tinggalkan kode yang tidak berguna di basis kode (lama dan tidak lagi digunakan atau dibuat "berjaga-jaga"). Kurangi duplikasi dan buat abstraksi sederhana sejak dini. Standardisasi. Saat menulis kode, Anda harus mengikuti gaya dan praktik yang ditetapkan untuk repositori. Disiplin diri. Seiring berkembangnya teknologi bekas dan munculnya teknologi baru, pengembang sering kali memiliki keinginan untuk mengubah dan meningkatkan sesuatu dalam kode yang sudah ada. Jangan menyerah pada hype terlalu cepat: pelajari tumpukan baru secara menyeluruh dan hanya untuk tujuan tertentu. Menjaga basis kode Anda tetap bersih lebih dari sekadar bersikap sopan kepada kolega Anda saat ini dan di masa depan. Hal ini penting untuk kelangsungan program dalam jangka panjang. Semakin bersih kode Anda, semakin senang pengembangnya, semakin baik produknya, dan semakin lama masa pakainya.

Mengapa Java lebih baik daripada C++ untuk sistem latensi rendah

Sumber: StackOverflow Sebagai pengembang, kita semua tahu bahwa ada dua cara untuk melakukan sesuatu: secara manual, perlahan dan mengganggu, atau otomatis, sulit dan cepat. Saya dapat menggunakan kecerdasan buatan untuk menulis artikel ini untuk saya. Ini dapat menghemat banyak waktu saya - AI dapat menghasilkan ribuan artikel per detik, tetapi editor saya mungkin tidak akan senang mengetahui bahwa dibutuhkan waktu dua tahun untuk menghasilkan artikel pertama. Rehat kopi #64.  Cara menulis kode bersih.  Mengapa Java lebih baik daripada C++ untuk sistem latensi rendah - 2Situasi serupa muncul ketika mengembangkan sistem perangkat lunak dengan latensi rendah. Kebijaksanaan konvensional adalah bahwa menggunakan apa pun selain C++ adalah hal yang gila karena segala sesuatu yang lain memiliki terlalu banyak latensi. Namun saya di sini untuk meyakinkan Anda tentang gagasan sebaliknya, kontra-intuitif, dan hampir sesat: dalam hal mencapai latensi rendah dalam sistem perangkat lunak, Java lebih baik. Pada artikel ini, saya ingin mengambil contoh spesifik perangkat lunak yang menghargai latensi rendah: sistem perdagangan. Namun, argumen yang disajikan di sini dapat diterapkan pada hampir semua keadaan yang memerlukan atau menginginkan latensi rendah. Hanya saja lebih mudah untuk berdiskusi terkait dengan bidang pengembangan yang saya alami. Faktanya adalah latensi sulit diukur. Semuanya tergantung pada apa yang Anda maksud dengan latensi rendah. Mari kita cari tahu sekarang.

Kebijaksanaan yang Diperoleh

Karena C++ lebih mirip dengan perangkat keras, sebagian besar pengembang akan memberi tahu Anda bahwa pengkodean dalam bahasa ini menawarkan keunggulan kecepatan. Dalam situasi latensi rendah, seperti perdagangan berkecepatan tinggi, di mana milidetik dapat membuat perbedaan antara perangkat lunak yang layak dan pemborosan ruang disk, C++ dianggap sebagai standar emas. Setidaknya begitulah dulu. Namun kenyataannya banyak bank dan broker besar kini menggunakan sistem yang ditulis dalam Java. Maksud saya ditulis secara asli di Java, bukan ditulis di Java dan kemudian diinterpretasikan dalam C++ untuk mengurangi latensi. Sistem ini menjadi standar bahkan untuk bank investasi tingkat 1, meskipun faktanya sistem ini (seharusnya) lebih lambat. Jadi apa yang terjadi? Ya, C++ mungkin memiliki "latensi rendah" saat mengeksekusi kode, namun jelas bukan latensi rendah saat menerapkan fitur baru atau bahkan menemukan pengembang yang dapat menulisnya.

Perbedaan (nyata) antara Java dan C++

Masalah waktu pengembangan hanyalah permulaan dalam perbedaan antara Java dan C++ dalam sistem dunia nyata. Untuk memahami nilai sebenarnya setiap bahasa dalam konteks ini, mari kita pelajari lebih dalam. Pertama, penting untuk mengingat alasan sebenarnya mengapa C++ lebih cepat daripada Java di sebagian besar situasi: pointer C++ adalah alamat variabel di memori. Artinya, perangkat lunak dapat mengakses variabel individual secara langsung dan tidak perlu menelusuri tabel komputasi intensif untuk mencarinya. Atau setidaknya dapat diatasi dengan menentukan lokasinya, karena dengan C++ Anda sering kali harus mengelola masa pakai dan kepemilikan objek secara eksplisit. Akibatnya, kecuali Anda benar-benar pandai menulis kode (keterampilan yang membutuhkan waktu puluhan tahun untuk dikuasai), C++ akan memerlukan waktu berjam-jam (atau berminggu-minggu) untuk proses debug. Dan seperti yang dikatakan oleh siapa pun yang pernah mencoba men-debug mesin Monte Carlo atau alat pengujian PDE, mencoba men-debug akses memori pada tingkat dasar bisa sangat memakan waktu. Hanya satu pointer yang salah dapat dengan mudah menjatuhkan seluruh sistem, jadi merilis versi baru yang ditulis dalam C++ bisa sangat menakutkan. Tentu saja bukan itu saja. Orang yang menyukai pemrograman dalam C++ akan menunjukkan bahwa pengumpul sampah Java mengalami lonjakan latensi non-linier. Hal ini terutama berlaku ketika bekerja dengan sistem lama, jadi mengirimkan pembaruan ke kode Java tanpa merusak sistem klien dapat membuatnya sangat lambat sehingga tidak dapat digunakan. Sebagai tanggapan, saya ingin menunjukkan bahwa banyak pekerjaan telah dilakukan selama dekade terakhir untuk mengurangi latensi yang diciptakan oleh Java GC. Pengganggu LMAX, misalnya, adalah platform perdagangan latensi rendah yang ditulis dalam Java, juga dibangun sebagai kerangka kerja yang memiliki “interaksi mekanis” dengan perangkat keras yang dijalankannya dan tidak memerlukan penguncian. Masalah dapat dikurangi lebih lanjut jika Anda membangun sistem yang menggunakan proses integrasi dan pengiriman berkelanjutan (CI/CD), karena CI/CD memungkinkan penerapan otomatis perubahan kode yang diuji. Hal ini karena CI/CD memberikan pendekatan berulang untuk mengurangi latensi pengumpulan sampah, di mana Java dapat secara bertahap meningkatkan dan beradaptasi dengan lingkungan perangkat keras tertentu tanpa proses intensif sumber daya dalam menyiapkan kode untuk spesifikasi perangkat keras yang berbeda sebelum mengirimkannya. Karena dukungan Java IDE jauh lebih luas daripada C++, sebagian besar kerangka kerja (Eclipse, IntelliJ IDEA) memungkinkan Anda melakukan refaktorisasi Java. Artinya, IDE dapat mengoptimalkan kode untuk performa latensi rendah, meskipun kemampuan ini masih terbatas saat bekerja dengan C++. Meskipun kode Java tidak cukup menyamai kecepatan C++, sebagian besar pengembang masih merasa lebih mudah untuk mencapai kinerja yang dapat diterima di Java dibandingkan di C++.

Apa yang kami maksud dengan "lebih cepat"?

Faktanya, ada alasan bagus untuk meragukan bahwa C++ benar-benar "lebih cepat" atau bahkan memiliki "latensi lebih rendah" dibandingkan Java. Saya menyadari bahwa saya sedang menghadapi masalah yang cukup suram, dan banyak pengembang akan mulai mempertanyakan kewarasan saya. Tapi dengarkan aku. Mari kita bayangkan situasi ini: Anda memiliki dua pengembang - satu menulis dalam C++ dan yang lainnya di Java, dan Anda meminta mereka untuk menulis platform perdagangan berkecepatan tinggi dari awal. Akibatnya, sistem yang ditulis dalam Java akan membutuhkan waktu lebih lama untuk menyelesaikan transaksi perdagangan dibandingkan sistem yang ditulis dalam C++. Namun, Java memiliki lebih sedikit contoh perilaku tidak terdefinisi dibandingkan C++. Sebagai contoh saja, pengindeksan di luar array adalah bug di Java dan C++. Jika Anda secara tidak sengaja melakukan ini di C++, Anda mungkin mendapatkan segfault atau (lebih sering) Anda hanya mendapatkan nomor acak. Di Java, keluar batas selalu menimbulkan kesalahan ArrayIndexOutOfBoundsException . Ini berarti proses debug di Java jauh lebih mudah karena kesalahan biasanya langsung teridentifikasi dan lokasi kesalahan lebih mudah dilacak. Selain itu, setidaknya menurut pengalaman saya, Java lebih baik dalam mengenali potongan kode mana yang tidak perlu dijalankan dan mana yang penting untuk pengoperasian perangkat lunak Anda. Anda tentu saja dapat menghabiskan waktu berhari-hari untuk mengubah kode C++ Anda sehingga tidak mengandung kode asing sama sekali, namun di dunia nyata, setiap perangkat lunak mengandung beberapa bloat, dan Java lebih baik dalam mengenalinya secara otomatis. Artinya di dunia nyata, Java sering kali lebih cepat dibandingkan C++, bahkan berdasarkan metrik latensi standar. Dan meskipun hal ini tidak terjadi, perbedaan latensi antar bahasa sering kali diliputi oleh faktor-faktor lain yang tidak terlalu penting bahkan dalam perdagangan berkecepatan tinggi.

Manfaat Java untuk Sistem Latensi Rendah

Semua faktor ini, menurut pendapat saya, memberikan argumen yang cukup kuat untuk menggunakan Java untuk menulis platform perdagangan berkecepatan tinggi (dan sistem latensi rendah secara umum, akan dibahas lebih lanjut sebentar lagi). Namun, untuk sedikit mempengaruhi para penggemar C++, mari kita lihat beberapa alasan tambahan untuk menggunakan Java:
  • Pertama, kelebihan latensi yang dimasukkan Java ke dalam perangkat lunak Anda kemungkinan besar akan jauh lebih kecil dibandingkan faktor lain yang memengaruhi latensi—seperti masalah internet. Ini berarti bahwa kode Java apa pun (yang ditulis dengan baik) dapat dengan mudah bekerja sebaik C++ di sebagian besar situasi perdagangan.

  • Waktu pengembangan Java yang lebih singkat juga berarti bahwa, di dunia nyata, perangkat lunak yang ditulis dalam Java dapat beradaptasi terhadap perubahan perangkat keras (atau bahkan strategi perdagangan baru) lebih cepat dibandingkan C++.

  • Jika Anda menggali lebih dalam hal ini, Anda akan melihat bahwa bahkan mengoptimalkan perangkat lunak Java bisa lebih cepat (jika dipertimbangkan di seluruh perangkat lunak) dibandingkan tugas serupa di C++.

Dengan kata lain, Anda dapat menulis kode Java dengan baik untuk mengurangi latensi. Anda hanya perlu menulisnya sebagai C++, dengan mempertimbangkan manajemen memori di setiap tahap pengembangan. Keuntungan tidak menulis dalam C++ adalah proses debug, pengembangan tangkas, dan beradaptasi dengan berbagai lingkungan menjadi lebih mudah dan cepat di Java.

kesimpulan

Kecuali Anda mengembangkan sistem perdagangan latensi rendah, Anda mungkin bertanya-tanya apakah hal di atas berlaku untuk Anda. Jawabannya, dengan sedikit pengecualian, adalah ya. Perdebatan tentang cara mencapai latensi rendah bukanlah hal baru atau unik dalam dunia keuangan. Oleh karena itu, pelajaran berharga dapat dipetik darinya untuk situasi lain. Secara khusus, argumen di atas bahwa Java "lebih baik" karena lebih fleksibel, lebih toleran terhadap kesalahan, dan pada akhirnya lebih cepat untuk dikembangkan dan dipelihara dapat diterapkan pada banyak bidang pengembangan perangkat lunak. Alasan saya (secara pribadi) lebih memilih untuk menulis sistem latensi rendah di Java adalah alasan yang sama yang membuat bahasa ini begitu sukses selama 25 tahun terakhir. Java mudah untuk ditulis, dikompilasi, di-debug, dan dipelajari. Ini berarti Anda dapat menghabiskan lebih sedikit waktu untuk menulis kode dan lebih banyak waktu untuk mengoptimalkannya. Dalam praktiknya, hal ini menghasilkan sistem perdagangan yang lebih andal dan lebih cepat. Dan itulah yang penting untuk perdagangan berkecepatan tinggi.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION