Jika sebelumnya sudah membahas tipe-tipe bug dalam pemrograman, kali ini mari kita bahas lebih lanjut cara mengatasi bug dan error.
Definisi Bug
Seperti yang kita tahu bug diartikan sebagai sebuah kecacatan, error, ataupun kegagalan fungsi yang menyebabkan suatu solusi (aplikasi) tidak dapat berjalan sesuai dengan kebutuhan atau harapan. Bug bisa disebabkan oleh berbagai hal, contohnya seperti human error, kegagalan integrasi dengan sumber daya eksternal, tidak memberikan validasi pada data yang berasal dari luar, maupun ketidakcocokan antara desain software dan lingkungan penggunaan.
Cara Mengatasi Bug Berdasarkan Jenisnya
Syntax Error
Bug ini terjadi ketika aturan sintaksis dalam bahasa pemrograman tidak diikuti dengan benar. Misalnya, kesalahan penulisan kata kunci (keyword) sehingga program tidak dapat dijalankan, cara mengatasinya tentunya dengan menuliskan keyword atau syntax yang benar.
💻 Mulai Belajar Pemrograman
Belajar pemrograman di Dicoding Academy dan mulai perjalanan Anda sebagai developer profesional.
Daftar SekarangSelain itu untuk pencegahan syntax error IDE dengan fitur syntax highlighting dan intelisense juga dapat membantu kamu mengurangi kemungkinan kesalahan penulisan sintaksis dan keyword.
Intellisense akan memberi kamu suggestion bahkan auto-completion ketika kamu menuliskan baris-baris kode.
Ia juga akan memberikan highlight pada keyword yang tidak sesuai. Misalnya, ketika kamu belum melakukan import module yang diperlukan.
Logical Error
Logical error adalah kesalahan dalam logika program yang menyebabkan hasil tidak sesuai dengan harapan. Ini dapat terjadi jika alur logika atau perhitungan matematis yang dituliskan oleh programmer tidak sesuai. Ini merupakan salah satu bug yang tricky untuk ditemukan karena biasanya tidak menghasilkan error apa pun pada console ataupun log.
Salah satu cara untuk menemukan dan memperbaiki logical error adalah dengan melakukan debug and trace terhadap kode tersebut, hal ini bisa dicapai secara manual dengan membuat tracing table ataupun dengan fitur debugger yang biasanya disediakan oleh IDE. Kamu bisa melihat fitur-fitur debugging dari IDE Visual Studio Code disini.
Logical error juga dapat diketahui lebih awal jika kita membuat unit testing untuk fungsi – fungsi dalam program kita. Bahkan ada paradigma yang disebut test driven development (TDD) dimana kita dianjurkan untuk terlebih dahulu menuliskan kode pengujian sebelum mengimplementasikannya ke fungsi dalam bahasa pemrograman.
Concurrency Bug
Concurrency bug adalah jenis kesalahan yang terjadi dalam program yang melibatkan eksekusi serentak (concurrent execution) dari beberapa proses atau thread. Concurrency bug dapat sangat sulit untuk dideteksi dan diperbaiki karena perilaku program mungkin saja bergantung pada urutan eksekusi dari proses atau thread yang berjalan secara bersamaan.
Bayangkan pada sebuah sistem yang menyimpan data saldo rekening bersama (joint account) di mana dua orang dapat bertransaksi dengan rekening yang sama. Suatu ketika, si wanita masuk ke akun dan membaca nilai saldo awal bernilai $100. Di tempat lain si pria, juga masuk ke akun yang sama dan menyelesaikan transaksi terlebih dahulu senilai $20 sehingga saldo tersisa $80. Lalu, si wanita tadi baru menyelesaikan transaksinya setelah si pria dengan nilai $30, tetapi menurut data cache yang ia dapat sebelumnya, saldo awal masih $100 sehingga saldo tersisa adalah $70. Kemudian, ketika data tersebut disimpan ke database,ia akan menggantikan saldo tanpa peduli dengan saldo yang sudah berkurang sebelumnya. Hal ini tentunya menimbulkan kerancuan karena uang keluar dan sisa saldo terdapat perbedaan.
Untuk mengatasi ini salah satunya kita bisa melakukan locking (penguncian) untuk memastikan bahwa sumber daya bersama hanya dapat diakses oleh satu proses atau thread pada satu waktu. Namun, penerapan locking juga dapat menyebabkan masalah seperti deadlock dan livelock jika tidak diterapkan dengan benar.
Deadlock terjadi ketika dua atau lebih proses atau thread saling menunggu untuk mendapatkan sumber daya yang telah dikunci oleh proses atau thread lain sehingga mengakibatkan tidak ada proses yang dapat melanjutkan eksekusi.
Sementara livelock terjadi ketika dua atau lebih proses atau thread terus-menerus bekerja, tetapi tidak menyelesaikan tugasnya karena mereka terjebak dalam siklus yang tidak dapat dipecahkan. Livelock menyebabkan penggunaan sumber daya CPU yang tinggi, tetapi proses yang diharapkan tidak terjadi.
Runtime Error
Runtime error adalah jenis error yang terjadi saat program sedang dieksekusi. Kesalahan jenis ini biasanya tidak teridentifikasi ketika menuliskan kode ataupun ketika tahap kompilasi (pada bahasa compiled). Runtime error dapat terjadi karena berbagai alasan, termasuk input yang tidak valid, kesalahan logika dalam kode, kekurangan memori, atau interaksi yang tidak diinginkan antara program dan lingkungan eksekusi.
Untuk mengatasi runtime error, kamu perlu memastikan untuk melakukan handling terhadap kemungkinan-kemungkinan ketidaksesuaian yang diakibatkan oleh data yang tidak terprediksi (misalnya data yang diambil dari input user ataupun response dari API). Pada bahasa yang tidak mendefinisikan tipe datanya secara eksplisit, runtime error sering terjadi karena programmer berpikir bahwa data yang dimasukkan user atau didapat dari API memiliki tipe data sesuai yang diharapkan. Contoh solusi runtime error adalah dengan melakukan validasi tipe data untuk data yang berasal dari sumber eksternal.
Memory Leak
Memory leak terjadi ketika program tidak membebaskan atau mengosongkan memori yang sudah tidak diperlukan dan akibatnya penggunaan memori terus meningkat seiring waktu. Bahasa pemrograman terkini umumnya telah memiliki garbage collector bawaan yang dapat membebaskan memori secara otomatis.
Untuk mengatasi memory leak, kamu perlu memastikan alokasi memori yang sebelumnya kamu gunakan dibebaskan setelah tidak lagi digunakan. Beberapa bahasa pemrograman memiliki tools, seperti Valgrind untuk C/C++ atau VisualVM untuk Java yang dapat membantu Anda mendeteksi memory leak dengan menganalisis alokasi memori dan mengidentifikasi area yang tidak dibebaskan dengan benar.
Integration Bug
Integration bug terjadi ketika terdapat kesalahan atau ketidakcocokan antara dua atau lebih komponen atau sistem yang diintegrasikan. Kasus ini sering terjadi pada sistem yang memiliki banyak external agent, seperti database, cloud storage, API, dan sebagainya.
Untuk mengatasinya kamu perlu terlebih dahulu mengetahui bagian mana yang menyebabkan masalah dari sebuah sistem yang terintegrasi tersebut. Dari sana, kamu bisa melakukan beberapa hal, seperti menyesuaikan versi database, melakukan update driver, mengubah struktur response API, melakukan integration test, dan sebagainya.
Floating-Point Imprecision
Floating point imprecision adalah kondisi ketika operasi matematika dengan bilangan desimal berbasis floating point dalam komputer menghasilkan hasil yang tidak sepenuhnya akurat. Akibat dari floating point imprecision dapat bervariasi, mulai dari perbedaan kecil dalam nilai hasil hingga perhitungan yang sepenuhnya tidak valid.
Misalnya dalam contoh sederhana ini, kamu akan menambahkan angka 0.1 sebanyak 10 kali, secara matematis ini akan menghasilkan nilai 1.1 namun pada bahasa python ini menghasilkan nilai 1.0999999999999999. Walaupun mendekati jika kamu membutuhkan presisi yang tinggi maka ini akan menjadi masalah.
Untuk mengatasi masalah yang disebabkan oleh floating point imprecision, ketahuilah akurasi yang diperlukan pada perhitungan yang kamu lakukan. Setelah itu, kamu dapat melakukan pembulatan pada hasil kalkulasi floating point sesuai kebutuhan. Jika hal itu tidak cukup untuk memenuhi kebutuhan (misalnya ketika bilangan dengan presisi sangat tinggi diperlukan), kamu bisa memanfaatkan library seperti: mpmath, SymPy ( Python), GMP, Arb (C), dan BigDecimal (Java).
Compatibility Bug
Compatibility bug terjadi ketika perangkat lunak tidak berfungsi dengan benar di lingkungan, versi, atau konfigurasi sistem tertentu. Ini bisa disebabkan oleh perbedaan antara versi perangkat lunak, perangkat keras, perubahan API, atau konfigurasi sistem yang berbeda. Untuk mengatasi hal ini, kamu bisa mendesain aplikasi dalam sistem yang terkontainerisasi (misalnya dengan docker) sehingga kamu memiliki sebuah environment yang dapat dengan mudah dibongkar pasang pada berbagai lingkungan mulai dari development, staging, hingga production.
Kesimpulan
Dalam kesehariannya, seorang programmer sehebat apa pun tidak akan terbebas dari bug. Oleh karena itu, sebagai programmer perlu untuk memahami berbagai jenisnya sehingga ketika menemui kasusnya di kehidupan nyata, kita bisa mengambil keputusan yang tepat untuk mengatasi bug tersebut. Selain mengatasi, kita juga harus dapat mencegah bug terjadi dengan sebisa mungkin untuk meminimalisasi kemungkinan terjadinya bug melalui pengujian yang komprehensif dan juga penggunaan alat bantu seperti Intellisense dan Linter.