Kode program yang identik tidak selalu menghasilkan keluaran serupa. Perbedaan lingkungan, konfigurasi, dan cara komputer memproses data dapat mengubah hasilnya.

Seorang programmer menyelesaikan pekerjaannya setelah berjam-jam memperbaiki kesalahan pada aplikasi. Seluruh pengujian di laptopnya berhasil, data ditampilkan dengan benar, dan tidak ada pesan kesalahan yang muncul. Ia kemudian mengirimkan kode kepada rekan kerjanya, tetapi ketika dijalankan di komputer lain, aplikasi tersebut justru menunjukkan hasil berbeda.

Situasi seperti ini sering memunculkan kalimat yang sangat akrab di lingkungan pengembangan perangkat lunak: “Di komputer saya berjalan normal, kok!” Bagi orang yang tidak terbiasa dengan pemrograman, pernyataan tersebut mungkin terdengar seperti alasan untuk menghindari tanggung jawab. Padahal, perbedaan hasil dari kode yang sama memang dapat terjadi, bahkan ketika tidak ada satu baris pun yang diubah.

Persoalannya terletak pada kenyataan bahwa kode program hanyalah salah satu bagian dari proses komputasi. Untuk bekerja, sebuah aplikasi membutuhkan penerjemah atau pengompilasi kode, pustaka perangkat lunak, konfigurasi sistem, data masukan, dan berbagai sumber daya lain. Ketika salah satu unsur tersebut berbeda, perilaku program juga dapat berubah.

Baca Juga: Mengapa Program Bisa Berjalan Benar, tetapi Masih Punya Kemungkinan Menghasilkan Jawaban yang Salah?

Kode Boleh Sama, tetapi Lingkungan yang Menjalankannya Belum Tentu

Bayangkan dua komputer menjalankan aplikasi yang dibuat menggunakan bahasa Python. Komputer pertama menggunakan versi Python dan pustaka tertentu yang dipasang beberapa bulan lalu, sedangkan komputer kedua menggunakan versi yang lebih baru. Walaupun berkas kode aplikasinya identik, perbedaan perilaku pustaka atau perubahan antarmuka pemrograman dapat membuat aplikasi menghasilkan keluaran berbeda atau bahkan gagal dijalankan.

Keadaan tersebut menunjukkan pentingnya dependency, yaitu perangkat lunak atau komponen lain yang dibutuhkan sebuah program agar dapat bekerja. Sebagian aplikasi bergantung pada puluhan bahkan ratusan pustaka yang dikembangkan oleh pihak berbeda. Ketika versi pustaka tidak dikendalikan, dua komputer dapat menjalankan susunan komponen yang berbeda meskipun pengembang menggunakan berkas kode utama yang sama.

Proyek Reproducible Builds, sebuah inisiatif yang mendorong pembuatan perangkat lunak dengan hasil kompilasi yang dapat direproduksi, menjelaskan bahwa lingkungan pembangunan perangkat lunak mencakup peralatan, versi, sistem operasi, dan berbagai asumsi konfigurasinya. Versi pengompilasi yang berbeda, misalnya, dapat menghasilkan berkas program yang berbeda sekalipun kode sumbernya identik. Perbedaan berkas hasil kompilasi tersebut tidak selalu berarti hasil perhitungan program juga berbeda, tetapi memperlihatkan betapa pentingnya lingkungan komputasi.

Pengaturan waktu dan wilayah juga dapat menimbulkan masalah yang tidak langsung terlihat. Komputer di Jakarta menggunakan zona waktu berbeda dari komputer di London, sehingga program yang mengolah tanggal tanpa informasi zona waktu dapat menampilkan atau menafsirkan waktu secara berlainan. Dokumentasi Python membedakan objek tanggal dan waktu yang memiliki informasi zona waktu, disebut aware, dengan objek naive yang tidak mempunyai informasi cukup untuk menentukan suatu waktu secara pasti.

Perbedaan serupa dapat muncul akibat pengaturan bahasa dan wilayah atau locale. Aplikasi yang mengolah data angka, tanggal, atau teks mungkin menghadapi format yang tidak sama antara lingkungan satu dan lainnya. Sebuah program yang mengharapkan pemisah desimal berupa titik, misalnya, perlu dirancang dengan hati-hati ketika menerima data dari sistem yang menggunakan tanda koma.

Bahkan urutan data dapat berubah apabila programmer mengandalkan perilaku yang sebenarnya tidak dijamin oleh bahasa pemrograman. Dokumentasi Python menjelaskan bahwa urutan iterasi pada struktur data set tidak memiliki jaminan tertentu, sementara mekanisme pengacakan nilai hash dapat menyebabkan urutan yang berbeda antarsesi program. Jika sebuah aplikasi menganggap urutan tersebut selalu tetap, hasil tampilannya dapat berubah meskipun isi datanya sama.

Baca Juga: Programnya Berjalan dengan Baik, Kenapa Developer Masih Mau Mengubah Kodenya?

Ketika Angka, Waktu, dan Proses Komputasi Mengubah Hasil

Ada persoalan yang lebih mendasar daripada perbedaan versi perangkat lunak, yakni cara komputer merepresentasikan angka. Dalam matematika, penjumlahan 0,1 dan 0,2 tentu menghasilkan 0,3. Akan tetapi, banyak bahasa pemrograman menggunakan representasi bilangan pecahan biner atau floating-point, yang tidak selalu dapat menyimpan pecahan desimal secara tepat.

Dokumentasi resmi Python menjelaskan bahwa sebagian besar pecahan desimal tidak memiliki representasi biner yang benar-benar persis. Akibatnya, hasil perhitungan dapat mengandung selisih yang sangat kecil dari angka yang diharapkan. Pada Python, misalnya, ekspresi 0.1 + 0.2 menghasilkan nilai yang secara umum ditampilkan sebagai 0.30000000000000004.

Fenomena tersebut bukan berarti komputer melakukan kesalahan penjumlahan secara sembarangan. Selisih muncul karena keterbatasan representasi angka dalam sistem komputasi, dan perilaku serupa ditemukan pada berbagai bahasa yang menggunakan aritmetika floating-point. Dalam proses komputasi tertentu, perbedaan urutan operasi, presisi yang digunakan, atau optimasi perangkat keras dapat menghasilkan perbedaan pembulatan.

Masalah ini menjadi penting dalam aplikasi keuangan, simulasi ilmiah, pemrosesan data, dan sistem lain yang membutuhkan ketelitian angka. Perhitungan uang, misalnya, tidak seharusnya mengandalkan perbandingan langsung antarbilangan pecahan biner tanpa mempertimbangkan aturan presisi yang dibutuhkan. Bahasa Python menyediakan modul decimal untuk perhitungan desimal dengan perilaku yang lebih sesuai bagi sejumlah kebutuhan tersebut.

Faktor lain yang sering dilupakan adalah penggunaan angka acak. Sebuah aplikasi dapat menggunakan proses acak untuk mengurutkan data, memilih sampel, menjalankan simulasi, atau melatih model kecerdasan buatan. Jika dua komputer menjalankan proses tersebut dengan keadaan awal pengacak yang berbeda, hasilnya dapat berbeda meskipun instruksi program sama.

Dalam komputasi paralel, urutan pelaksanaan pekerjaan juga dapat berpengaruh. Dua proses yang menggunakan sumber daya bersama tanpa pengaturan sinkronisasi memadai dapat menghadapi kondisi yang disebut race condition, ketika hasil bergantung pada proses mana yang lebih dahulu melakukan suatu operasi. Perbedaan kecepatan komputer atau penjadwalan tugas dapat membuat masalah ini muncul pada satu lingkungan tetapi tidak terlihat pada lingkungan lainnya.

Lalu, bagaimana memastikan sebuah program dapat memberikan hasil yang konsisten? Panduan reproduksibilitas komputasi dari Kempner Institute, Harvard University, menekankan pentingnya mencatat versi kode dan pustaka, mengendalikan sumber keacakan, mengisolasi lingkungan perangkat lunak, serta memastikan data masukan dapat ditelusuri. Pendekatan tersebut membantu pengembang mengulang proses komputasi dan memeriksa sumber perbedaan secara sistematis.

Dalam praktiknya, pengembang dapat menggunakan virtual environment, berkas pengunci versi dependensi atau lockfile, dan teknologi container untuk membantu menyamakan lingkungan. Pengujian otomatis pada lebih dari satu sistem operasi atau versi perangkat lunak juga dapat menemukan masalah yang tidak terlihat pada komputer pengembang. Meski begitu, penggunaan container bukan jaminan mutlak bahwa seluruh hasil akan identik karena perangkat keras, layanan eksternal, waktu, dan sumber keacakan masih dapat memengaruhi proses tertentu.

Hal lain yang tidak kalah penting adalah membedakan hasil yang memang seharusnya identik dari hasil yang secara desain dapat berubah. Aplikasi cuaca, misalnya, tidak mungkin terus menampilkan informasi sama apabila data terbaru yang diterimanya sudah berubah. Begitu pula sistem yang mengambil data dari internet dapat memberikan hasil berbeda ketika sumber informasinya diperbarui, meskipun kode aplikasinya tidak mengalami perubahan.

Karena itu, ketika program memberikan hasil berbeda pada dua komputer, langkah pertama bukan langsung menyalahkan perangkat keras atau menganggap kode pasti keliru. Pengembang perlu memeriksa apakah versi perangkat lunak, konfigurasi, data masukan, serta kondisi eksekusinya benar-benar setara. Menemukan perbedaan tersebut sering kali merupakan bagian paling penting dari proses penelusuran kesalahan atau debugging.

Pemrograman memang berlandaskan aturan logika yang ketat, tetapi program dijalankan dalam lingkungan nyata yang memiliki banyak variabel. Kode yang sama dapat menghasilkan hasil berbeda bukan karena komputer memiliki penafsiran sesuka hati, melainkan karena kondisi yang memengaruhi pelaksanaan instruksinya belum tentu sama. Memahami hal tersebut mengajarkan bahwa menulis kode yang benar hanyalah satu bagian dari pekerjaan pengembang perangkat lunak. Tantangan berikutnya adalah memastikan kode tersebut tetap dapat diandalkan ketika meninggalkan komputer tempat ia pertama kali dibuat. [][Rudi Tenggarawan/KK]

Penulisan artikel ini dibantu AI dan telah melewati proses kurasi Redaksi.