22 Desember 2020 [Java, Programming, Programming Languages, Rust, Tech]
Beberapa kode Java dengan bug
Inilah metode utama saya (di Jawa). Bisakah Anda menebak bugnya?
Db db = new Db(); Monitoring monitoring = new Monitoring(); Monitoring mon2 = new Monitoring(); Billing billing = new Billing(db, monitoring); monitoring.setDb(db); runMainLoop(billing, mon2); db.stop(); billing.stop(); monitoring.stop();
Jika Anda ingin memburu 2 bug tersebut secara manual, coba baca kode lengkapnya di sini: ShutdownOrder.java
Tapi mungkin Anda sudah punya ide? Mungkin Anda pernah melihat kode seperti ini sebelumnya? Jika pernah, Anda mungkin memiliki naluri bahwa ada semacam bug, meskipun Anda tidak dapat memastikan apa itu bug. Kode seperti ini hampir selalu memiliki bug!
Kode ini dapat dikompilasi dengan baik, tetapi mengandung dua bug.
Pertama, kami lupa setDb() pada mon2. Hal ini menyebabkan NullPointerException, karena Pemantauan selalu mengharapkan Db yang berfungsi.
Kedua, dan secara umum lebih sulit dikenali, kami menutup layanan kami dengan urutan yang salah. Ternyata Monitoring menggunakan Db-nya saat dimatikan, jadi kami mendapat pengecualian. Lebih buruk lagi, jika beberapa kode lain perlu dijalankan setelah monitoring.stop(), kode tersebut tidak akan dijalankan, karena pengecualian tersebut menghalangi kita untuk melangkah lebih jauh.
Tentu saja, ini adalah kode mainan, tetapi masalah seperti ini umum terjadi (dan lebih sulit dikenali) dalam kode kehidupan nyata. Faktanya, tim saya menangani bug serupa minggu ini.
Pada dasarnya sulit untuk mengetahui perintah penutupan Anda. Lebih rumit lagi jika kelas memiliki metode start() juga, yang telah saya lihat di banyak kode Java.
Mengingat ini hanyalah masalah yang sulit, mungkin tidak ada gunanya mencari alat untuk mempermudahnya?
Beberapa kode Rust tanpa bug tersebut
Mari kita coba menulis kode ini di Rust. Inilah metode utamanya:
let db = Db::new(); let monitoring = Monitoring::new(&db); let mon2 = Monitoring::new(&db); let billing = Billing::new(&db, &monitoring); run_main_loop(&billing, &mon2); // drop() is called automatically on all objects here
Berikut kode lengkapnya: shutdown_order.rs
Kode ini mematikan semua layanan secara otomatis pada akhirnya, dan kesalahan apa pun yang kami buat dalam urutan tersebut adalah kesalahan kompilasi, bukan hal yang kami temukan nanti saat kode kami berjalan.
Kode untuk mematikan setiap layanan terlihat seperti ini:
impl Drop for Monitoring<'_> {
fn drop(&mut self) {
// [Disconnect from monitoring API]
self.db.add_record("MonitorShutDown");
}
}
Ini adalah implementasi sifat Drop untuk struct Monitoring (sifatnya mirip dengan Antarmuka Java). Sifat Drop itu spesial: ini menunjukkan apa yang harus dilakukan ketika sebuah instance dari struct ini dihilangkan. Di Rust, hal ini dijamin akan terjadi ketika instance berada di luar cakupan, itulah sebabnya komentar kami di akhir metode utama terdengar sangat percaya diri.
Selain itu, kompiler Rust mematikan segala sesuatu dalam urutan terbalik saat ia dibuat, dan menjamin bahwa tidak ada yang digunakan setelah ia dihapus.
Dunia Rust yang indah memberi kita dua suguhan yang relevan: tidak ada hal yang tidak terduga, dan masa hidup.
Perlakukan nomor 1: tidak ada nol yang tidak terduga
Pertama, di Rust, seperti bahasa modern lainnya seperti Kotlin, kita harus menjelaskan secara eksplisit item yang mungkin hilang. Dalam contoh kami, kami dapat mengatur ulang kode sehingga db tidak akan pernah hilang (atau nol), dan kompiler mendorong kami untuk melakukannya. Jika kita benar-benar memerlukannya agar hilang pada suatu waktu, kita dapat menggunakan tipe Option, dan kompiler akan memaksa kita untuk menangani kasus ketika kasus tersebut hilang, daripada secara tidak terduga mendapatkan NullPointerException seperti yang kita lakukan di Java. (Faktanya, jika kita menyusun kode kita untuk menggunakan final di sebanyak mungkin tempat, pada dasarnya kita juga bisa terdorong untuk menggunakan solusi yang sama di Java.)
Perlakukan nomor 2: seumur hidup
Kedua, jika Anda melihat lebih dekat kode lengkap shutdown_order.rs Anda akan melihat banyak anotasi yang tampak membingungkan seperti <'a> dan &’a:
struct Monitoring<'a> { db: &'a Db, }
Perkiraan arti anotasi tersebut adalah: Pemantauan memiliki referensi ke Db, dan Db tersebut harus bertahan lebih lama daripada Pemantauan.
Kata-kata “bertahan lebih lama dari” inilah yang dimaksud dengan Rust Lifetimes. Seumur hidup adalah cara untuk mengatakan berapa lama sesuatu akan bertahan.
Masa hidup benar-benar membingungkan ketika Anda memulai dengan Rust, dan telah membuat saya sangat kesakitan. Kode seperti ini adalah tempat yang paling menyakitkan dan paling membantu. Seperti yang saya sebutkan sebelumnya, masalah perintah penutupan pada dasarnya sulit. Karat memberi Anda rasa sakit pada awalnya, dan sampai Anda memahami apa yang terjadi, rasa sakit itu sangat membingungkan dan akut. Namun, setelah kode Anda dikompilasi, kode tersebut sudah benar, setidaknya sejauh menyangkut masalah seperti ini.
Saya menyukai rasa aman yang diberikan kepada saya untuk menulis kode Rust dan mengetahui bahwa kompiler telah memeriksa kode saya untuk masalah seperti ini, artinya kode tersebut tidak dapat muncul pada jam 3 pagi pada Hari Natal…
Catatan/peringatan terakhir
Kode Rust ini mungkin terlalu disederhanakan, karena semua referensi tidak dapat diubah (Anda tidak dapat mengubah objek yang ditunjuknya). Dalam praktiknya, kita mungkin memiliki referensi yang bisa berubah, dan jika kita memilikinya, kita harus menghadapi kesulitan lebih lanjut karena Rust tidak akan mengizinkan dua objek berbeda untuk menyimpan referensi ke suatu objek jika salah satu referensi tersebut bisa berubah. Sehingga akan keberatan dengan Billing dan Monitoring yang menggunakan objek Db secara bersamaan. Kita harus membuatnya tidak dapat diubah (seperti yang kita lakukan di sini), atau mencari cara lain untuk menyusun kode: misalnya, kita dapat menyimpan instance Db hanya dalam kode run_main_loop, dan meneruskannya sementara ke objek Penagihan dan Pemantauan saat kita memanggil metodenya. Bagian terbesar dari seni, kesenangan dan kesulitan mempelajari Rust adalah menemukan pola baru untuk kode Anda yang melakukan apa yang perlu Anda lakukan dan juga membuat compiler senang. Ketika Anda mengelolanya, Anda mendapatkan manfaat yang luar biasa!
News
Berita Teknologi
Berita Olahraga
Sports news
sports
Motivation
football prediction
technology
Berita Technologi
Berita Terkini
Tempat Wisata
News Flash
Football
Gaming
Game News
Gamers
Jasa Artikel
Jasa Backlink
Agen234
Agen234
Agen234
Resep
Download Film
A gaming center is a dedicated space where people come together to play video games, whether on PCs, consoles, or arcade machines. These centers can offer a range of services, from casual gaming sessions to competitive tournaments.
