69 poin oleh xguru 2024-07-15 | 6 komentar | Bagikan ke WhatsApp

Jika Anda terus menembak kaki sendiri, perbaiki senjatanya

  • Dalam tim, sering ada bagian sistem yang kerap memicu kesalahan, tetapi banyak kasus di mana orang tidak memikirkan cara untuk mengurangi kesalahan itu
  • Dalam situasi seperti ini, penting untuk memperbaiki sistem agar kesalahan bisa berkurang
  • Pengalaman:
    • Saat mengembangkan iOS dan menggunakan CoreData, pembaruan UI hanya bisa dilakukan di main thread
    • Callback langganan terjadi baik di main thread maupun background thread sehingga masalah sering muncul
    • Anggota tim lama memahami hal ini dan menanganinya dengan baik, tetapi hal ini sering muncul dalam review anggota tim baru
    • Setiap kali sesekali terjadi kesalahan, kami melihat crash report lalu menambahkan DispatchQueue.main.async
    • Untuk menyelesaikannya, layer subscription diperbarui agar memanggil subscriber di main thread. Hanya butuh 10 menit.
    • Satu kelas crash penuh dan sedikit beban mental pun hilang
  • Siapa pun yang memikirkannya beberapa menit akan sadar bahwa ini masalah yang jelas
  • Namun, karena tidak pernah ada momen yang terasa alami untuk memperbaiki masalah seperti ini, anehnya hal itu bisa bertahan lama
    • Artinya, jika terlalu lama berada di tim, masalah seperti ini mudah memudar menjadi latar belakang
  • Perlu perubahan pola pikir
    • Sesekali kita harus mengingatkan diri sendiri bahwa saat masalah seperti ini muncul, kita sebenarnya bisa membuat hidup sendiri dan tim menjadi lebih mudah

Menyeimbangkan kualitas dan kecepatan

  • Selalu ada trade-off antara kecepatan implementasi dan keyakinan terhadap ketepatannya
    • Kita perlu bertanya pada diri sendiri seberapa bisa diterimanya jika merilis bug dalam situasi saat ini
    • Jika jawaban atas pertanyaan itu tidak memengaruhi cara Anda bekerja, berarti Anda terlalu kaku
  • Di pekerjaan pertama, saat mengerjakan proyek pemrosesan data, tersedia sistem yang bagus untuk memproses ulang data secara retrospektif
    • Dampak dari merilis bug sangat kecil, dan di lingkungan seperti ini kita bisa cukup mengandalkan guardrail dan bergerak lebih cepat
    • 100% test coverage atau proses QA yang luas hanya akan memperlambat kecepatan pengembangan
  • Di pekerjaan kedua, produk yang digunakan puluhan juta orang menangani data finansial bernilai tinggi dan informasi identitas pribadi, sehingga bug bisa berakibat fatal
    • Bahkan bug kecil pun membutuhkan postmortem
    • Fitur dirilis dengan sangat lambat, tetapi rasanya tahun itu kami merilis 0 bug
  • Dalam kebanyakan kasus, kita tidak berada dalam situasi seperti perusahaan kedua
    • Dalam situasi di mana bug tidak fatal, misalnya 99% web app, lebih baik merilis cepat dan memperbaiki bug dengan cepat
    • Anda bisa berkembang lebih jauh dibanding menghabiskan waktu untuk merilis fitur yang sempurna sejak awal

Waktu untuk mengasah gergaji hampir selalu berharga

  • Penting untuk menguasai alat yang digunakan
  • Anda harus bisa menulis kode dengan cepat, mengetahui shortcut utama, dan mahir dengan sistem operasi serta shell
    • Anda akan sering melakukan rename, go to type definition, find references, dan sebagainya
    • Anda harus tahu semua shortcut utama editor dan bisa mengetik dengan percaya diri serta cepat
    • Menggunakan browser developer tools secara efektif juga penting
  • Memilih alat yang tepat dan menggunakannya dengan mahir adalah keunggulan besar
  • Salah satu green flag terbesar yang terlihat pada engineer baru adalah minat terhadap pemilihan alat dan penggunaan yang mahir

Jika Anda tidak bisa menjelaskan kesulitannya dengan sederhana, kemungkinan itu adalah kompleksitas insidental, dan masalah ini layak diselesaikan

  • Manajer favorit saya punya kebiasaan terus menekan setiap kali saya mengatakan bahwa implementasinya sulit
    • Sering kali jawabannya berbunyi seperti, "Bukankah ini cuma soal mengirim X saat Y?" atau "Bukankah ini sama seperti Z yang kita lakukan beberapa bulan lalu?"
    • Itu adalah keberatan di level yang sangat tinggi, bukan di level fungsi dan class konkret yang sedang coba saya jelaskan
  • Pandangan umum adalah bahwa penyederhanaan dari manajer seperti ini cuma menjengkelkan
  • Namun secara mengejutkan, cukup sering ketika manajer terus bertanya, saya sadar bahwa sebagian besar kompleksitas yang saya jelaskan ternyata adalah kompleksitas insidental
  • Dan dengan menyelesaikan bagian itu lebih dulu, masalahnya benar-benar bisa dibuat sesederhana seperti yang dikatakan manajer
  • Pendekatan seperti ini cenderung membuat perubahan di masa depan lebih mudah

Berusahalah memperbaiki bug satu lapisan lebih dalam

  • Daripada memperbaiki bug secara dangkal, penting untuk menemukan dan memperbaiki akar penyebabnya
  • Misalkan ada komponen React di dashboard yang menangani objek User yang diambil dari status pengguna yang sedang login
    • Muncul bug report di Sentry bahwa saat render, user ternyata null
      • Anda bisa cepat-cepat menambahkan if (!user) return null atau
    • Kalau diselidiki sedikit lebih jauh, Anda akan tahu bahwa fungsi logout melakukan dua pembaruan state yang terpisah
      • Yang pertama mengatur user menjadi null, dan yang kedua me-redirect ke homepage
    • Jika urutan keduanya dibalik, tidak akan ada komponen mana pun yang mengalami bug ini lagi
    • Karena di dalam dashboard, objek user seharusnya tidak pernah null
  • Jika Anda terus melakukan jenis perbaikan bug yang pertama, sistem akan jadi berantakan, tetapi
    jika Anda terus melakukan jenis perbaikan bug yang kedua, Anda akan mendapatkan sistem yang bersih dan pemahaman mendalam tentang invariants

Jangan meremehkan nilai menggali histori untuk menyelidiki bug

  • Saya cukup mahir men-debug masalah aneh menggunakan alat umum seperti println dan debugger
  • Karena itu saya tidak terlalu sering melihat git untuk memahami histori bug, tetapi untuk beberapa bug hal ini sangat penting
  • Baru-baru ini, di server tampaknya ada memory leak yang terus berlangsung, lalu proses dihentikan oleh OOM dan dimulai ulang
    • Semua penyebab yang tampak masuk akal sudah dieliminasi, dan masalahnya tidak bisa direproduksi secara lokal
    • Rasanya seperti melempar dart sambil menutup mata
    • Setelah melihat commit history, ternyata masalah mulai muncul setelah menambahkan dukungan pembayaran Play Store
    • Itu cuma beberapa HTTP request, jadi tempat ini tidak akan saya curigai bahkan sejuta tahun pun
    • Ternyata ada loop tak terbatas saat mengambil access token setelah access token pertama kedaluwarsa
    • Setiap request mungkin hanya menambah sekitar 1kB di memori, tetapi jika di-retry setiap 10ms dari beberapa thread, akumulasinya jadi sangat cepat
    • Biasanya hal seperti ini akan menyebabkan stack overflow, tetapi karena menggunakan async recursion di Rust, stack overflow tidak terjadi
    • Ini tidak akan pernah terlintas di pikiran saya, tetapi begitu saya melihat kode spesifik yang jelas memicu masalah, teorinya tiba-tiba muncul
  • Tidak ada aturan pasti kapan pendekatan seperti ini harus dipakai
    • Ini lebih berdasarkan intuisi; jenis rasa "loh?" yang berbeda saat melihat bug report bisa memicu investigasi seperti ini
    • Seiring waktu Anda bisa mengembangkan intuisi itu, tetapi setidaknya mengetahui bahwa pendekatan ini kadang sangat berharga saja sudah cukup
  • Jika masalahnya cocok, cobalah git bisect
    • Saat Anda punya satu commit yang Anda tahu rusak dan satu commit yang Anda tahu baik

Kode buruk memberi umpan balik, kode sempurna tidak. Lebih baik keliru ke arah menulis kode buruk

  • Menulis kode yang mengerikan itu sangat mudah
  • Tetapi menulis kode yang benar-benar mengikuti semua best practice juga sangat mudah
    • Anda harus melewati unit test, integration test, fuzz test, mutation test, dan startup akan kehabisan uang sebelum itu selesai
  • Sebagian besar pemrograman adalah soal menemukan keseimbangan
  • Jika Anda cenderung keliru ke arah menulis kode dengan cepat...
    • Kadang Anda akan kena masalah karena technical debt yang buruk
    • Anda akan belajar bahwa "pengujian yang bagus untuk pemrosesan data harus ditambahkan"
      • Karena memperbaikinya nanti sering kali tidak mungkin
    • Anda juga akan belajar bahwa "desain tabel harus benar-benar dipikirkan baik-baik"
      • Karena mengubahnya tanpa downtime bisa sangat sulit
  • Jika Anda cenderung keliru ke arah menulis kode sempurna...
    • Anda tidak mendapat umpan balik apa pun
    • Semua hal akan memakan waktu lama secara konsisten
    • Anda tidak tahu di mana waktu digunakan dengan tepat dan di mana waktu terbuang sia-sia
    • Mekanisme umpan balik sangat penting untuk belajar, tetapi Anda tidak mendapatkannya
  • Memperjelas arti kode "buruk"
    • Ini bukan berarti "saya tidak ingat sintaks membuat hashmap, jadi saya memakai internal loop dua kali"
    • Maksudnya seperti ini:
      • Alih-alih menulis ulang pengumpulan data agar status tertentu tidak bisa direpresentasikan, Anda cukup menambahkan beberapa assertion terhadap invariants di beberapa checkpoint penting
      • Karena server model persis sama dengan DTO yang akan ditulis, Anda cukup men-serialize-nya saja. Daripada menulis semua boilerplate sekarang, DTO bisa dibuat nanti saat memang diperlukan
      • Komponen-komponen ini sepele dan kalau ada bug pun dampaknya kecil, jadi Anda melewatkan penulisan test

Buat proses debugging lebih mudah

  • Selama bertahun-tahun saya mempelajari banyak trik kecil untuk membuat software lebih mudah di-debug
    • Jika Anda tidak berupaya membuat debugging lebih mudah, maka seiring software menjadi makin kompleks, Anda akan menghabiskan waktu yang sangat besar untuk men-debug setiap isu
    • Anda akan mulai takut melakukan perubahan. Karena memahami beberapa bug baru saja bisa memakan waktu seminggu
  • Perhatikan berapa banyak waktu debugging yang habis untuk setup, reproduksi, dan pembersihan setelahnya
    • Jika lebih dari 50%, Anda harus mencari cara untuk membuatnya lebih mudah meskipun kali ini butuh sedikit lebih lama
    • Dengan kondisi lain tetap sama, memperbaiki bug seharusnya makin mudah seiring waktu

Saat bekerja dalam tim, selalu bertanya

  • Ada spektrum dari "berusaha mencari tahu semuanya sendiri" sampai "mengganggu rekan kerja dengan pertanyaan sepele"
    • Saya rasa kebanyakan orang di awal karier terlalu condong ke sisi pertama
  • Selalu ada orang di sekitar Anda yang lebih lama berada di codebase, jauh lebih paham teknologi X, lebih mengenal produk, atau sekadar engineer yang lebih berpengalaman
  • Dalam 6 bulan pertama bekerja di suatu tempat, sering kali Anda bisa menghabiskan lebih dari satu jam untuk memahami sesuatu, padahal jawabannya bisa didapat dalam beberapa menit
  • Bertanyalah. Satu-satunya saat pertanyaan benar-benar mengganggu orang lain adalah ketika jelas bahwa Anda sebenarnya bisa menemukan jawabannya sendiri dalam beberapa menit

Siklus deployment sangat penting. Pikirkan baik-baik cara agar bisa deploy dengan cepat dan sering

  • Startup memiliki runway yang terbatas, dan proyek memiliki tenggat waktu
  • Saat berhenti kerja dan menjadi independen, tabungan Anda mungkin hanya cukup untuk beberapa bulan
  • Idealnya, kecepatan proyek meningkat secara majemuk dari waktu ke waktu, sehingga Anda bisa merilis fitur lebih cepat daripada yang Anda bayangkan
  • Banyak hal dibutuhkan untuk bisa deploy cepat
    • Sistem yang tidak rentan terhadap bug
    • Turnaround time yang cepat antar tim
    • Kemauan untuk memotong 10% fitur baru yang akan memakan 50% waktu engineering, serta wawasan untuk mengenali bagian itu
    • Pola yang konsisten dan bisa digunakan ulang untuk merakit screen/fitur/endpoint baru
    • Deployment yang cepat dan mudah
    • Proses yang tidak memperlambat (test yang flaky, CI yang lambat, linter yang cerewet, review PR yang lambat, JIRA yang diperlakukan seperti agama, dan sebagainya)
    • Dan sejuta hal lainnya
  • Deploy yang lambat seharusnya mendapat postmortem sama seperti production outage
    • Industri kita memang tidak berjalan seperti itu, tetapi bukan berarti Anda tidak bisa secara pribadi menjadikan deployment cepat sebagai bintang utara

6 komentar

 
carnoxen 2024-07-19

"menembak kaki sendiri" = menggali lubang sendiri

Apakah artinya begitu?

 
yunghn 2024-07-25

Jika ada masalah karena kode yang salah (pistol rusak) (menembak kaki sendiri), maksudnya adalah perbaiki pistolnya.

 
gargoyle92 2024-07-16

Rasanya seperti isi kepala saya dikeluarkan begitu saja, saking mengena banget, duh duh..

 
cbbatte 2024-07-16

Saya membacanya dengan baik!!

 
hannah0su 2024-07-15

Saya membacanya dengan baik.

 
arfwene 2024-07-15

Saya memang bukan developer, tetapi ada banyak bagian yang terasa relevan.