
Setiap Software Engineer pasti pernah melakukan kesalahan saat development. Sekalipun yang jago atau yang udah master pasti pernah bikin kesalahan. Yang namanya manusia tentu ga ada yang sempurna. Dari kesalahan itu justru yang menjadikan kita menjadi versi yang lebih baik. Gw sendiri juga pernah bikin kesalahan, baik itu kesalahan besar maupun kesalahan kecil. Berikut ini gw share beberapa "dosa" yang pernah gw lakukan selama jadi Software Engineer biar bisa dipetik pelajarannya☺️.
Convert XLSX to JSON as Request Body
Ini mungkin "dosa terbesar" gw sebagai Software Engineer sih. Kejadiannya saat gw kerja di sebuah konsultan IT. Ini projek aplikasi untuk perusahaan produsen obat. Sebenarnya bukan dosa yang gw inisiasi, gw cuma ngikutin perintah aja🫡. Gw waktu itu masih cupu banget, masih fresh graduate, jadi cuma manut aja. Team Leader gw ngide bikin fitur upload data dengan cara front end mengekstrak file XLSX lalu dikonversi menjadi JSON, dan itu dikirimkan sebagai request body ke back end. Team Leader ini seingat gw saat itu juga baru aja dipromosikan buat nge-lead. Team Leader ini kemudian resign dan pindah ke startup lain. Saat projek ini dimulai pengembangannya dia emang lagi masa notice 30 hari. Dia ga ada penggantinya di projek ini hingga projek kelar. Gw dan teman-teman lainnya yang sama-sama fresh graduate ngelanjutin develop ini pake cara itu. Katanya ini lebih efisien karena ga perlu simpan file di server. Saat develop dan internal test ini aman-aman aja. Lanjut ke UAT, saat client mencoba ngetes aplikasinya dengan sample asli data penjualan bulanan, kemudian BOOM!! Browsernya crash sampai bikin laptop yang digunakan client freeze, not responding dan harus force restart💥.
Ukuran file yang di-upload cuma kisaran 15MB doang. Technical Manager gw saat itu pun bingung. Gw coba debug di local pake file yang sama. Di laptop gw ga crash, tapi emang sempat hang proses uploadnya🫣. Mungkin karena spec laptop gw lebih bagus daripada punya client, makanya di laptop gw tetap ter-upload walau sempat hang. Gw pantau di log back end, ga ada tanda-tanda request masuk saat hang sih🤔. Sampai sini gw udah yakin, masalahnya bukan di server. Pas gw cek di network tools pada browser, ternyata request yang dikirim ukurannya lebih dari 2GB! Ini yang bikin aplikasinya lemot dan bikin laptop client crash saat upload. Gw terheran-heran, kok bisa file 15MB jadi 2GB di payload?
Sample data yang di-upload client berisi puluhan ribu baris data per file. Pada file XLSX, data ini udah di-compress menggunakan ZIP archive yang berisi XML sesuai standar OpenXML, makanya ukuran filenya cuma belasan MegaBytes. Masalahnya adalah data di file XLSX itu diekstrak jadi JSON di front end untuk dikirim sebagai request body ke server, yang mana itu Plain Text! Jelas aja ukurannya jadi gendut🫄. Bandwidth yang digunakan jadi bengkak sehingga proses call API jadi lama. Selain itu, mengekstrak puluhan ribu data di front end tentu sangat berpengaruh pada performa laptop yang digunakan client. Apalagi pada laptop kentang, tentu akan sangat berat🥲. JavaScript di browser bukan tempat yang cocok untuk memproses data sebanyak ini sekaligus. Waktu gw coba proses filenya di back end pakai Java aman, ga sampai bikin laptop jadi hang. Kalaupun back end ga kuat ya tinggal upgrade server. Tapi kalau laptop client yang ga kuat ga mungkin kita nyuruh client beli laptop baru hanya untuk aplikasi ini😅.
Sampai sini masalah udah gw identifikasi. Gw melapor temuan ini ke Project Manager dan Technical Manager. Mereka nanyain solusi alternatif. Gw merekomendasikan di-upload di server aja file XLSX tersebut lalu dibaca di server sehingga ga akan berat di client. Technical Manager malah nantangin gw, "Ini lu bisa kerjain semua sendirian dalam waktu sehari ga? Kalau ga bisa ya udah, biarin aja kayak gini!". Dia yang nanya pendapat gw, dia juga yang judes ngeresponnya😠. Padahal maksud gw cuma ngasih tau temuan gw aja, gw ga nuntut ini harus dirombak saat itu juga. Dia sendiri malah selama ini ga ketemu root cause-nya apa dan malah nyalahin client. Mereka malah bilang ke client bahwa ini karena client make database SQL Server sehingga ga kuat buat handle data banyak. Padahal masalahnya itu bukan di database, requestnya aja belum nyampe ke server, boro-boro nyampe ke database. Mau pake database manapun kalau desain uploadnya kayak gitu udah pasti jebol browsernya. Entah karena mereka ingin blaming ke client aja atau emang strategi mereka biar projek tetap lanjut sesuai deadline, entahlah🙄. Sebelumnya client emang ngotot ingin make SQL Server karena alasan tertentu sehingga membuat gw dan tim harus migrasiin beberapa query manual yang ga compatible dengan SQL Server karena aplikasinya waktu itu ga pake ORM😑.
Pada akhirnya aplikasi ini tetap go live dan client secara legowo menerima kecacatan aplikasi ini apa adanya. Untungnya client tersebut tipe client yang ga enakan dan ga banyak maunya. Aplikasinya tetap mereka gunakan dengan catatan data yang di-upload dipecah jadi maksimal 500 baris per file. Jarang-jarang ada client kayak gini😁. Ga tega gw sebenarnya deliver aplikasi busuk kayak gini ke mereka yang cukup baik, ramah, dan ga rewel. Saat UAT dan menjelang go live di kantor mereka, gw dan tim dikasih cemilan yang mana di kantor gw ini malah ga ada. Tiap siang ini langsung ludes sama gw dan di-refill lagi sama OB kantor mereka🤭. Bahkan 2x seminggu ada jatah makan siang gratis dengan menu beragam😋. Gw yang bukan karyawan sana juga dapat jatah.
Pagination on Front End
Dosa kedua masih pada projek yang sama😂. Ini juga warisan ide dari Team Leader yang resign di awal projek. Fiturnya waktu itu adalah menampilkan data yang di-upload ke halaman web. Sebelum resign dia bilang bahwa ini bakal lebih efisien karena ga perlu request berkali-kali ke back end tiap ganti halaman. Jadi, ketika ngirim request ke back end, front end akan mendapatkan response dari back end berupa list data penjualan tanpa pagination! Semua data dikirimkan sekaligus dan pagination dilakukan di front end, meskipun ada ratusan ribu data🫨. Gw dan tim yang masih fresh graduate unyu-unyu tentu saja nurut dan mikir bahwa ini adalah ide cemerlang✨.
Lagi-lagi ini ketahuannya saat UAT. Saat internal test karena QA masih pake sample data yang sedikit tentu ga jadi masalah. Client ngetes menggunakan sample data tahunan yang berisi ratusan ribu baris data. Saat dibuka halamannya, loading-nya bisa lebih dari 5 menit bahkan kadang ga berhenti. Bayangin aja saat UAT petinggi-petinggi perusahaan tersebut ikhlas bersabar nungguin datanya muncul🫣. Jujur aja, gw yang jadi ngerasa malu sama mereka. Udah gitu mereka mau-maunya lagi bengong 5 menit nungguin datanya muncul, awkward banget😂.
Ini masalahnya jelas, karena ratusan ribu data dikirim sekaligus ke front end. Query database jadi berat, pembungkusan data dari back end jadi ikutan lambat, dan front end menampung semua data tersebut untuk diproses juga ga kuat. Apalagi laptopnya kentang, sudah pasti prosesnya sangat lemot di browser🥲. Kalaupun udah pake pagination di back end dan itu masih lambat karena datanya banyak, solusinya dengan mengganti behavior pagination, bukan dengan kirim semua data dari server dong! Ini juga gw lapor temuan gw ini ke Project Manager dan Technical Manager berbarengan dengan temuan sebelumnya. Project Manager gw kekeh dengan sotoy-nya bilang ini masalah di SQL Server😂. Ga tau deh, ini dia aja yang nyari-nyari alasan buat disalahkan atau emang sotoy aja. Padahal sebelum jadi Project Manager dia ini salah satu Senior Software Engineer di sana, masa ini ga paham?
Summary for Huge Data
Ini juga terjadi pada projek yang sama. Apes banget client ini😅. Di projek ini ada fitur dashboard yang menampilkan chart analitik penjualan tahunan per bulan dan dibandingkan dengan data penjualan per bulan pada tahun sebelumnya. Masalahnya, karena datanya ratusan ribu, melakukan summary data jadi lambat. Ini membuat loading aplikasi untuk menampilkan dashboard sangat berat. Kali ini bottleneck-nya emang di database, tapi bukan SQL Server doang, semua database relasional pasti akan mengalami kendala yang sama kalau kasusnya seperti ini. Melakukan summary pada data transaksi yang banyak emang bakal berat.
Seharusnya database untuk OLTP (Online Transactional Processing) dan database untuk OLAP (Online Analytical Processing) dipisah. Bagian OLTP itu isinya data transaksi real time sebagai sumber data utama. Sedangkan OLAP itu isinya data summary analitik, misalnya data yang sudah diagregasi perhitungannya per hari. Jadi tiap ada data masuk, data tersebut tersimpan ke masing-masing database. Database OLAP mencatat perhitungan data harian dari 1 Januari sampai 31 Desember masing-masing per hari ada berapa. Jadi saat nampilin data tahunan dari database OLAP tinggal jumlahin aja nilai akumulasi hariannya dalam setahun tanpa perlu join atau membaca data transaksi per baris. Misalkan dalam setahun ada ratusan ribu data. Kalau di OLTP ini akan membaca ratusan ribu baris data tahunan lalu menjumlahkannya, ini yang bikin lambat🤯. Sedangkan kalau di OLAP, karena data yang disimpan adalah data harian yang sudah diagregasikan, maka data tahunan yang dibaca hanyalah 365 baris data, ga perlu baca ratusan ribu data sehingga perhitungan lebih cepat. Solusi lainnya jika menggunakan database yang support Materialize View ini juga bisa dipertimbangkan. Atau bisa juga menggunakan Columnar Database, jaman sekarang juga lagi populer menggunakan NoSql untuk kebutuhan analitik.
Input Validation Only on Front End
Ini projek terakhir gw di konsultan IT tersebut sebelum gw resign. Waktu itu gw masih Junior. Gw ditempatkan di projek yang anggota development awalnya 1 Web Developer, 1 Mobile Developer, dan 1 Back End Engineer (yaitu gw). Tim ini ga ada senior ataupun Team Leader. Projek ini duplikasi dari projek lain dengan requirement yang mirip. Hanya perlu ubah dan tambah beberapa fitur saja. Di sini gw ngide validasi input cukup di front end aja. Kayak validasi input nama harus diisi, nomor KTP harus 16 digit, dan sejenisnya. Gw mikirnya dengan alasan "efisiensi" validasi ga perlu dilakukan lagi di back end🫣.
Padahal validasi input di back end lah yang berfungsi sebagai security dan itu wajib, meskipun validasi juga sudah dilakukan di front end. Ini celah yang bisa di-eksploitasi pake curl atau Postman untuk mengirimkan data kotor. Melakukan validasi input ga bakal bikin aplikasi berat. Secara teknis memang ada code tambahan, tapi itu akan tereksekusi dalam hitungan nanosecond, ga akan terasa. Sedangkan validasi input di front end itu hanya untuk kepentingan UX agar tampilannya responsif saat terjadi kesalahan, kalau ada validasi bagus, kalau ga ada juga gapapa. Gw resign sebelum projek ini kelar dan meninggalkan lubang keamanan pada aplikasi tanpa gw sadari saat itu🫣. Ga tau deh setelah gw resign apakah validasi ini ditambahin sama penerus gw atau nggak.
Transitive Dependency Issue
Kalau yang ini terjadi pada saat awal-awal gw bekerja di startup. Waktu itu ada modul yang menggunakan library Jackson untuk serialize/deserialize JSON jadi object atau sebaliknya. Modul tersebut digunakan pada beberapa modul lainnya. Ada fitur serialize/deserialize dari Jackson untuk immutable object yang waktu itu belum support di versi lama yang ingin gw pake. Setelah upgrade ke versi terbaru gw pastikan beberapa modul lain yang dipake di tim gw yang bergantung pada modul tersebut berjalan secara normal. Setelah aman, gw push ke branch master dan deploy. Tanpa sepengetahuan gw, modul tersebut juga dipake di modul milik tim lain. Mereka kebingungan semalaman karena ada error di modul mereka dan mereka ga ketemu penyebabnya sehingga aplikasi mereka ga bisa jalan🫣. Sekitar jam setengah dua belas malam ada salah satu anggota tim mereka yang kenal gw chat gw ngasih tahu tentang error ini karena deployment terakhir dari gw. Untung saat itu gw belum tidur😅.
Ternyata itu dampak dari upgrade Jackson tadi. Modul mereka ada yang make modul yang gw upgrade tadi😅. Awalnya gw juga bingung dan ga tau root cause-nya karena gw ga familiar sama modul tim mereka. Setelah kurang lebih sejam gw cari tahu ternyata itu karena gw upgrade minor versinya kejauhan. Mungkin library tersebut ga mengikuti Semantic Versioning, jadi ada breaking changes di minor versionnya🫣. Gw cek ternyata beberapa modul dari tim lain juga ada dependency pake modul tim gw dan di modulnya pake Jackson dengan versi berbeda. Agak tricky kalau semua modul tim lain versi Jackson-nya ikut di-upgrade karena perlu pastiin fitur-fiturnya berjalan normal setelah upgrade. Apalagi saat itu udah tengah malam. Setelah tes beberapa versi, gw downgrade dikit versinya beberapa minor di modul gw itu sehingga gw tetap bisa menggunakan fitur yang gw inginkan tanpa menyebabkan error pada modul lain. Untuk solusi jangka panjangnya, harusnya perlu bikin BOM pada Maven agar library antar modul bisa serasi versinya dan lebih gampang maintain saat upgrade.
Verdict
Dari sini gw belajar bahwa projek yang diisi junior semua tanpa Team Leader terlalu beresiko. Kehadiran Team Leader yang benar-benar kompeten itu sangat penting biar ga sesat di jalan. Komunikasi dan koordinasi antar sesama tim dan tim lain baik itu sesama Software Engineer maupun lintas role juga penting untuk menghindari miskomunikasi. Tentunya itu jadi pelajaran berharga buat gw. Dari kesalahan-kesalahan ini lah gw belajar dan mendapatkan pengalaman baru. Ga ada system yang sempurna karena ga ada Software Engineer yang sempurna. Melakukan kesalahan bukan aib, semuanya pasti pernah melakukannya. Yang terpenting bukan seperti apa kesalahannya, tapi apa yang bisa kita ambil sebagai pelajaran dari kesalahan tersebut😎.