6 poin oleh GN⁺ 2025-09-27 | 3 komentar | Bagikan ke WhatsApp
  • Dalam manajemen memori, Zig menawarkan pendekatan yang lebih sederhana dan intuitif dibandingkan Rust
  • Borrow checker Rust memang kuat, tetapi untuk pengembangan alat CLI kecil, ia memicu kompleksitas berlebihan dan beban bagi pengembang
  • Manajemen memori manual Zig memungkinkan tercapainya keamanan memori yang efisien hanya dengan alat yang tepat dan sedikit disiplin dari pengembang
  • Keamanan program tidak hanya soal keamanan memori, tetapi juga dipengaruhi berbagai faktor seperti perilaku yang dapat diprediksi, kinerja yang mudah dikelola, dan perlindungan data
  • Rust cocok untuk sistem berskala besar, tetapi untuk alat CLI kecil yang praktis, Zig lebih unggul dari sisi produktivitas pengembangan dan pemeliharaan

Gambaran umum

Belakangan ini, saat membuat alat CLI, saya cenderung memilih Zig lebih dulu daripada Rust

Dasar manajemen memori: stack dan heap

  • Stack adalah area memori berukuran tetap yang cepat untuk menyimpan data yang sangat sementara seperti parameter fungsi, variabel lokal, dan alamat pengembalian
  • Heap adalah area untuk alokasi memori dinamis, digunakan ketika umur data lebih panjang atau ukurannya ditentukan saat runtime
  • Stack secara struktural sederhana tetapi ruangnya terbatas, sedangkan heap punya lebih banyak hal yang perlu diperhatikan dari sisi kecepatan dan fragmentasi

Borrow Checker Rust

  • Borrow checker Rust menjamin keamanan memori pada waktu kompilasi
  • Dengan menegakkan aturan seperti referensi, kepemilikan, dan lifetime, ia mencegah sejak awal kesalahan seperti dereferensi null pointer dan dangling pointer
  • Namun, keamanan memori hanya diperiksa berdasarkan waktu kompilasi, dan ini tidak serta-merta menghilangkan kesalahan pengguna atau masalah rancangan kepemilikan yang rumit itu sendiri

Contoh: Notes CLI buatan saya

  • Saat mencoba menulis CLI untuk mengelola catatan pribadi dengan Rust, saya harus bersusah payah merancang ulang strukturnya karena borrow checker
  • Sebaliknya, di Zig, hanya dengan memakai allocator, pembuatan indeks berbasis pointer serta perubahan/penghapusan secara bebas bisa dilakukan jauh lebih sederhana
  • Borrow checker Rust punya tujuan yang jelas, tetapi dengan Zig, hanya dengan pengetahuan dasar manajemen memori dan sedikit disiplin, tingkat efisiensi dan keamanan yang tinggi tetap bisa dicapai

Keamanan alat CLI tidak berhenti pada keamanan memori

  • Keamanan sejati sebuah produk mencakup banyak unsur seperti perilaku yang dapat diprediksi, umpan balik yang bermakna saat terjadi kesalahan, perlindungan data sensitif, dan ketahanan terhadap serangan
  • Baik Rust maupun Zig tidak bisa disebut “aman” jika selain keamanan memori, syarat-syarat lain ini tidak terpenuhi
  • Misalnya, jika CLI diam-diam menimpa data saat terjadi error atau salah mengatur izin file, pengguna bisa mengalami masalah serius
  • Keamanan alat CLI

    • Perilaku yang dapat diprediksi: perlu menjamin perilaku yang konsisten dan jelas meski ada input salah atau situasi tak terduga
    • Pencegahan crash dan kerusakan data: error harus ditangani dengan baik, serta perlu mencegah kerusakan data atau crash yang tak terinformasikan
    • Pengelolaan kinerja: meski memproses data dalam jumlah besar, tidak boleh terjadi pemborosan sumber daya atau penurunan responsivitas
    • Perlindungan informasi sensitif: perlu berhati-hati terhadap file sementara dan pengaturan izin
    • Ketahanan terhadap serangan: perlu kuat terhadap validasi input, memory overflow, serangan injeksi, dan sejenisnya

Kekuatan dan keterbatasan Borrow Checker Rust

  • Kekuatan

    • Memblokir data race dan referensi ganda: compiler menjamin aturan satu mutable reference dan banyak immutable reference
    • Jaminan compile-time yang kuat: sebagian besar bug terkait memori diblokir sebelum program dijalankan
    • Menemukan bug lebih awal: ini menjadi keuntungan besar pada layanan produksi atau sistem konkurensi
  • Keterbatasan dan ketidaknyamanan

    • Cognitive overhead: bahkan untuk pekerjaan CLI kecil, pengembang tetap harus memikirkan kepemilikan/lifetime/manajemen referensi
    • Boilerplate/distorsi struktural: wrapper seperti Rc, RefCell, penggunaan clone berlebihan, dan perancangan ulang struktur membuat fokus bergeser dari “memecahkan masalah” ke “memuaskan compiler”
    • Lemah terhadap bug logis/keadaan: hanya menjamin aturan memori; tidak menjamin prediktabilitas, kesalahan logika, atau integritas data
    • Kompleksitas edge case: benturan lifetime mudah terjadi pada cache, state global, mutable index, dan sebagainya
  • Akibatnya, pada proyek CLI kecil, borrow checker Rust menjadi “pajak mental” bagi pengembang dan dapat membuat segalanya lebih rumit daripada yang sebenarnya diperlukan

Pendekatan Zig terhadap keamanan dan kesederhanaan

  • Zig berbasis pemeriksaan keamanan opsional dan manajemen memori manual
  • Konsep allocator sudah tertanam sehingga penggunaan memori yang terstruktur dan dapat diprediksi bisa diimplementasikan
  • Kita juga bisa membuat allocator kustom untuk menentukan cara pengelolaan memori yang sesuai dengan karakteristik proyek
  • Berkat sintaks defer di Zig, pelepasan otomatis dan pembersihan resource saat scope berakhir juga jauh lebih intuitif
  • Tidak seperti Rust, Zig lebih menekankan tanggung jawab pengembang sehingga dibutuhkan disiplin, tetapi jika dirancang dengan baik, keamanan memori lebih mudah dicapai dan dipertahankan
  • Zig menghasilkan kode yang ringkas, dan perubahan struktur seperti pointer, list, dan indeks jauh lebih sederhana dibanding Rust
  • Tanpa merasa terikat seperti di Rust, tingkat keamanan dan efisiensi kode yang setara tetap bisa diwujudkan
  • Selain itu, fitur comptime Zig sangat membantu untuk eksekusi kode, pengujian, dan optimasi pada waktu kompilasi

Pentingnya pengalaman pengembang (Developer Ergonomics)

  • Pengalaman pengembang (ergonomics) mencakup unsur-unsur seperti sintaks bahasa, tooling, dokumentasi, hingga komunitas
  • Rust pada akhirnya menjamin keamanan memori berkat aturan yang sangat ketat, tetapi aturan yang berlebihan dan ceremony justru menurunkan produktivitas
  • Zig menekankan desain yang digerakkan pengembang sehingga kode lebih mudah dan cepat ditulis, diubah, serta dipahami
  • Dengan kode yang intuitif, iterasi yang cepat, dan beban mental yang rendah, Zig membuat pengembang fokus memecahkan masalah tanpa harus bertarung dengan alat
  • Zig mempercayai pengembang dan memberi alat serta pilihan yang tepat, sedangkan Rust bisa terasa terlalu mengawasi dan membatasi
  • Alih-alih “melindungi pengembang dari kesalahan”, lingkungan yang ramah pengembang adalah yang menjamin kesempatan untuk belajar dan berkembang melalui kesalahan sendiri

Kesimpulan

  • Untuk bidang seperti sistem besar, multithread, dan berjalan lama, tempat keunggulan Rust benar-benar maksimal, Rust tetap merupakan pilihan terbaik
  • Namun, untuk alat CLI kecil dan praktis, ringannya Zig, kesederhanaannya, serta cepatnya implementasi dan pemeliharaan lebih cocok
  • Keamanan memori hanyalah satu bagian dari teka-teki keamanan, dan unsur penting bagi alat CLI seperti perilaku yang dapat diprediksi, kemudahan pemeliharaan, dan ketangguhan lebih mudah dicapai di Zig
  • Pada akhirnya, yang penting bukanlah ‘bahasa yang lebih baik’, melainkan workflow yang cocok untuk saya dan ‘pemilihan alat’ yang sesuai dengan karakteristik proyek
  • Zig adalah bahasa yang sangat pas untuk pengembangan alat kecil karena menggabungkan "keamanan memori + biaya mental rendah + keramahan/p produktivitas bagi pengembang"

3 komentar

 
shakespeares 2025-10-05

Sepertinya ekosistemnya masih belum se-stabil Rust.

 
bus710 2025-09-27

Karena Zig cukup sering mengalami breaking change di versi-versi barunya... jadi sepertinya meskipun proyeknya kecil, sebaiknya tetap dipasangi CI agar bisa terus dikelola.

 
GN⁺ 2025-09-27
Opini Hacker News
  • Kelebihan Zig adalah memungkinkan kita tetap berpikir seperti developer C, meski sampai batas tertentu ini juga cuma soal kebiasaan

    • Developer yang sudah cukup terbiasa dengan Rust tidak lagi “berkelahi” dengan borrow checker, karena mereka sudah berpikir dengan struktur kode seperti itu

    • Pendekatan seperti “object soup” di Rust memang tidak terlalu cocok, tetapi sebenarnya itu bukan berarti pendekatan itu secara fundamental lebih mudah, hanya terasa mudah karena kita sudah terbiasa

    • Jika menerima premis bahwa ergonomics (pengalaman penggunaan) sulit diukur atau dikuantifikasi, diskusi seperti ini akan terus terasa kabur

      • Mirip dengan mengatakan, "Kursi ini tidak akan roboh jadi duduk saja dengan tenang, hanya mungkin sedikit kurang nyaman dan lebih berat, tapi kebanyakan orang akan segera terbiasa dan tidak lagi merasa tidak nyaman"
      • Seperti kalimat di tulisan asli, "Rust memberi keamanan memori dengan pengalaman developer yang kurang nyaman, sedangkan Zig bisa memberi pengalaman developer yang lebih baik dan keamanan memori dengan sedikit kehati-hatian", pada akhirnya ini adalah pertukaran antara keamanan dan kemudahan penggunaan
      • Menurut saya komunitas Rust perlu mengakui trade-off ini dengan jujur, karena memastikan keamanan selalu datang bersama berkurangnya kenyamanan
      • Ini adalah dasar yang muncul di keamanan, kehidupan, keseharian, dan perangkat lunak secara umum, dan kebanyakan argumennya memang ambigu atau subjektif
      • Ada juga orang yang terlalu mudah mengabaikan isu ergonomics dengan berkata, “Bagi yang sudah terbiasa tidak ada masalah”, dan itu bisa terdengar seperti, “Kalau itu saja sulit berarti kamu kurang pintar”
    • “Berkelahi dengan borrow checker” berasal dari masa ketika orang baru memahami lifetime leksikal di Rust

      • Saat saya belajar Rust pada 2021, itu sudah menjadi cerita lama
      • Memang, bagi orang yang sebelumnya hanya memakai Python, C, JavaScript, dan sejenisnya, beradaptasi dengan Rust bisa jadi tidak mudah
      • Dalam kasus saya itu terasa mudah diterima, tetapi tampaknya kebanyakan orang tidak merasakannya begitu
      • Namun, mengatakan “di Rust kita harus membaca pesan diagnostik lalu memperbaiki kode” tidak terdengar semenarik “dengan berani melawan borrow checker”, padahal itu lebih menggambarkan situasi yang sebenarnya
    • Dalam pengalaman saya, developer Rust yang mahir sering menaburkan Arc di mana-mana dan praktis memakainya seperti garbage collection otomatis

      • Manajemen memori statis cukup ketat sehingga pada struktur data kompleks hal itu secara realistis terasa sulit
      • Jalur yang harus ditelusuri karena lifetime sering kali melampaui kemampuan kognitif manusia
    • Saya juga sering melihat proyek Rust open source yang ditulis developer berpengalaman tetap memakai Arc, Clone, Copy, dan semacamnya di banyak tempat

    • Kelebihan Zig adalah kita bisa mengembangkan secara familier seperti di C sambil tetap mendapat fitur keamanan dari bahasa dan tooling

      • Misalnya, optional di Zig bisa membantu menghindari masalah nil dereference
      • Saat debugging atau testing, kita juga bisa langsung meneruskan allocator debug/custom untuk memeriksa runtime check, akses memori, dan kebocoran resource dengan mudah
      • Saya memang kurang suka tidak adanya interface/trait yang eksplisit, tetapi adopsinya sederhana sehingga terasa praktis
  • Saya tidak setuju dengan sebagian besar isi tulisan aslinya

    • Rust, sama seperti C atau Zig, tetap membuat kita memikirkan lifetime, ownership, dan borrow scope; bedanya adalah ada atau tidaknya bantuan compiler

    • Manusia, secerdas apa pun, tetap bisa membuat kesalahan saat lelah atau terdistraksi, dan mengakui itu justru adalah kebijaksanaan

    • Ruang program yang dianggap aman oleh compiler Rust tidak cukup luas, sehingga cukup sering menolak program yang sebenarnya valid

    • Contoh: jika pada struct Foo, bar dan baz masing-masing adalah string, lalu bar diambil sebagai mutable reference dan baz sebagai immutable reference, itu tidak akan terkompilasi, sehingga kita terpaksa mengakali struktur kode dalam situasi seperti ini

    • Sebagai sanggahan, harus mengubah kode ke desain yang kualitasnya urutan kedua atau ketiga hanya untuk “menghindari kasus ketika kondisi sebenarnya aman tetapi kompilasi ditolak” itu sendiri adalah beban besar

      • Ini bisa mengubah desain seluruh codebase
      • Ini juga menjelaskan mengapa adopsi Rust terasa berat bagi orang yang mengerjakan hal sulit seperti developer game
      • Jika Rust compiler bisa bekerja secara tepat tanpa false warning, dari sisi ergonomics itu akan luar biasa, tetapi tentu kenyataannya tidak semudah itu
    • Contoh di atas tampaknya benar-benar kasus yang sangat bagus, saya ingin bertanya apakah boleh membahasnya di blog atau artikel saya

    • Setelah melihat kode di atas, justru saya jadi makin tidak yakin dengan klaim tersebut

  • Kita perlu ingat bahwa tidak semua program harus se-“aman” itu

    • Kita tumbuh sambil menikmati banyak perangkat lunak Unsafe, seperti Star Fox 64, MS Paint, dan FruityLoops

    • Saya juga pernah membaca bahwa pencipta Zig, Andrew Kelley, membuat Zig karena tidak ada lingkungan pengembangan untuk perangkat lunak produksi musik (DAW), dan saya rasa Zig cocok untuk perangkat lunak kreatif semacam itu

    • Siapa pun yang sensitif terhadap bug memori bisa memakai Rust

    • Saya bahkan percaya Super Mario World jadi lebih seru karena bug memori

    • “Aman” adalah kependekan dari “program saya berjalan sesuai yang saya maksudkan”

      • Kode yang tidak logis dan tidak disengaja (semantic gibberish) justru menghambat pencapaian tujuan itu
      • Ada juga kasus sengaja menulis kode yang rumit secara artistik, seperti IOCCC, hacking, atau puisi kode, tetapi dalam kasus seperti itu tetap harus dibuat dengan sangat hati-hati
      • Di Rust pun hal seperti itu bisa diimplementasikan secara sengaja lewat escape hatch (unsafe)
      • Klaim di tulisan itu pada dasarnya adalah bahwa menulis kode gibberish tanpa sengaja adalah kelebihan, dan ini sulit saya setujui
      • Jika kita bisa membuat semua kode aman tanpa kekurangan apa pun, bukankah semua orang menginginkannya?
      • Speedrun Super Mario World dan sejenisnya juga bisa diwujudkan lewat binary patch; saya tidak menganggap manipulasi memori lewat input sebagai satu-satunya kesenangan di sana
    • Saya agak bingung, apakah alasan orang menganggap komentar saya buruk adalah karena mereka menafsirkannya seolah saya bilang keamanan memori tidak penting?

  • Saya merasa nilai borrow checker terlalu diremehkan

    • Borrow checker Rust menjamin akses memori yang tidak valid dicegah pada waktu kompilasi

    • Tentu ada ketidaknyamanan karena kita harus mengubah struktur kode agar sesuai aturan compiler

    • Saat saya memakai Rust sendiri, saya tidak pernah merasa lifetime annotation itu salah; memang terasa seperti chore yang merepotkan, tetapi cepat terbiasa

    • Selama tidak memakai unsafe, di Rust dua thread tidak bisa menulis ke memori yang sama secara bersamaan

    • Saya tidak terlalu setuju dengan klaim “mengapa Zig terasa lebih praktis untuk alat CLI”, karena Rust tetap punya keunggulan dalam mencegah CVE (kerentanan)

    • Dalam praktiknya, saya sendiri melakukan sebagian besar pekerjaan dengan bahasa GC, dan saat berkontribusi ke bahasa lain, saya tidak terlalu peduli apakah itu Rust, Zig, atau C/C++

    • Memangnya alat CLI itu istimewa?

      • Umumnya alat CLI tidak terlalu besar atau sering dibuat sendiri, sehingga lebih mudah dikelola
      • Zig atau C mungkin kurang cocok untuk codebase yang sangat besar; pada proyek yang lebih kompleks, kita butuh babysitter (penjaga)
      • Ada perdebatan lama yang mirip ketika Java juga disebut “bahasa babysitter”, tetapi kenyataannya banyak codebase memang membutuhkannya
    • Pernyataan bahwa tanpa unsafe dua thread tidak bisa menulis ke memori yang sama secara bersamaan juga tidak sepenuhnya sesederhana itu

      • Dukungan compiler yang saya inginkan justru lebih pada menyelesaikan masalah memory ordering
      • Dalam bagian seperti ini, Rust tetap menggolongkan race tertentu sebagai safe, bukan unsafe
  • Saya setuju bahwa mengimplementasikan backlinks di Rust terlalu rumit

    • Itu bisa dilakukan dengan Rc, Weak, RefCell, .borrow(), dan sebagainya, tetapi tidak mudah

    • Jika programnya berjalan singkat, alokasi arena juga bisa menjadi solusi, dan mungkin itulah yang dimaksud dengan alat CLI

    • Rust benar-benar menunjukkan kekuatannya pada aplikasi besar, multithread, dan berjalan lama

    • Saya sendiri pernah menulis klien metaverse besar dengan Rust, dan meski puluhan thread berjalan 24 jam, tidak ada kebocoran memori maupun crash

    • Jika hal yang sama dibuat dengan C++, tim QA dan alat seperti Valgrind akan menjadi keharusan, sementara bahasa skrip terlalu lambat dari sisi performa

    • Saya juga pernah membuat pesawat simulasi fisika dengan Rust yang bahkan memperhitungkan kelengkungan bumi dan variasi gravitasi

      • Saya menjalankan pengujian rute 5 jam dan 22 jam selama bertahun-tahun tanpa masalah
      • Dalam 7 tahun memakai Rust, saya hanya mengalami sangat sedikit crash; C/C++ sekarang saya pakai hanya saat harus memperbaiki kode warisan lama
  • Zig memang menarik, tetapi D juga masih ada, dan secara pribadi saya merasa D adalah pengganti C/C++ yang saya inginkan

    • Sintaks Zig terasa agak canggung, dan Rust sudah menjadi pusat dalam ekosistem

    • Go juga punya pangsa besar di banyak alat bahasa, dan di bidang AI dipakai paling banyak setelah Python

    • Sebelum Rust, dulu ada perdebatan Go vs. D, dan saya bahkan sempat membeli buku D sebelum akhirnya beralih ke Go

      • Bagi saya standard library Go jauh lebih praktis, dan nama tipe data seperti int64 juga terasa lebih intuitif
    • D memang bagus, tetapi belum melahirkan killer app yang membuatnya benar-benar populer

  • Saya tidak terlalu paham mengapa kita harus bersikeras memakai Rust atau Zig untuk alat CLI

    • Bottleneck-nya ada di I/O, bukan karena GC lambat

    • Menurut saya isu GC bukan poin utama kecuali pada hal yang sangat intensif memori seperti game atau database

    • Saya ingin menekankan bahwa ketimbang berdebat soal keamanan memori, saya lebih memikirkan alasan memilih bahasa yang tidak memerlukan GC

    • Kalau alasannya “karena no-GC itu menyenangkan”, itu sendiri sudah cukup, tidak perlu diperdebatkan

    • Waktu startup yang instan, tanpa jeda eksekusi, sangat bermanfaat

      • Saat membuat alat pembungkus, kita bisa menjalankannya ribuan kali tanpa terasa berat
      • Distribusi juga jadi mudah karena tidak ada kerumitan deployment seperti pada lingkungan Python
    • Membuat CLI dengan Go terasa sangat baik, meski saya sendiri tidak terlalu menyukai bahasa Go

      • CLI Python bisa merepotkan saat dependensinya banyak, sementara Rust/Zig juga populer karena seperti Go mudah didistribusikan sebagai binary statis
    • Saya memprioritaskan bahasa yang punya sum type, pattern matching, dan dukungan async

      • Bahkan kalau bukan Rust, saya tetap menyukai fitur yang bisa menangkap error pada waktu kompilasi
    • Soal pernyataan bahwa pengembangan tanpa GC hanya relevan untuk dunia game

      • Pada kenyataannya, banyak game mobile juga memakai GC, seperti lingkungan Unity + il2cpp, dan performa GC-nya pun sering tidak bagus
    • Perdebatan soal GC ini terasa seperti bandwagon

      • Lima puluh tahun lalu, workstation besar seperti Interlisp dan Cedar sudah berhasil dibangun dengan bahasa berbasis GC
      • Performa hardware saat ini jauh lebih baik daripada CLI era 1970-an atau aplikasi Electron, tetapi pemanfaatan efisiennya masih kurang
  • Saya membuat alat catatan sederhana dengan borrow/referencing bawaan Rust, dan ternyata tidak serumit yang dibayangkan

    • Jika kita membayangkan struktur yang menyimpan indeks daftar notes lalu menghubungkannya lewat map, perbedaan kecepatannya nyaris tidak ada dan juga tidak punya kelemahan keamanan

    • Kalaupun salah indeks, itu akan tertangkap sebagai error out-of-range, yang jauh lebih baik daripada menimpa memori kernel

    • Bahkan saat printf debugging pun itu terasa jauh lebih mudah dan intuitif

    • Raw pointer atau reference biasanya hanya saya pakai di tempat yang benar-benar perlu seperti allocator atau async runtime; untuk logika umum, pendekatan berbasis indeks lebih cocok

    • Ini juga terkenal sebagai alasan async Rust tidak bisa memakai self-referential struct, sehingga muncul isu terkait Pin

    • Pointer ke nilai yang disimpan di vec akan menjadi tidak valid jika terjadi realloc dan sejenisnya, dan dalam kasus seperti ini Miri akan langsung memberi error

  • Sebagai developer C++, jika saya mencari bahasa yang aman, saya merasa Swift paling cocok

    • Bahasa yang terasa familier atau mirip memang lebih cepat diadaptasi

    • Dukungan lintas platform Swift juga belakangan makin kuat, dan ada beberapa orang dari komite standar C++ yang ikut terlibat

    • Namun, karena keterkaitannya dengan Apple dan tidak adanya framework UI native, ekspansinya di luar ekosistem Apple relatif lebih terbatas

    • Saya berharap Swift bisa menjadi lebih populer

    • Kalau ada sumber yang membandingkan Swift dengan Zig/C, saya akan senang jika direkomendasikan

  • Ada yang bilang Zig juga bisa dipakai membuat perangkat lunak yang aman dari sisi memori dengan kehati-hatian yang cukup, tetapi sebenarnya C pun bisa mencapai hasil serupa jika dipakai dengan disiplin

    • Pada akhirnya, “sedikit disiplin (latihan)” inilah yang dalam kenyataan sering kurang, dan di situlah masalah muncul

    • Zig juga secara tambahan menyelesaikan masalah-masalah berikut

      • Out of bounds access (mencakup 70% dari seluruh CVE)
      • null pointer dereference
      • keamanan tipe
      • Jauh lebih unggul daripada C, dan error seperti use-after-free juga jauh lebih mudah dihindari selama tidak melampaui batas
      • Sistem build lintas platform Zig yang sangat baik, optimasi comptime, serta build time yang puluhan kali lebih cepat daripada C++/Rust juga menjadi kekuatan besar
      • Standard library-nya memang masih kurang matang dan masih ada masalah kecil, tetapi saya pikir masa depannya cerah untuk program yang berorientasi performa
    • Jika C sudah gagal selama lebih dari 50 tahun dalam masalah discipline seperti ini, berarti ini sesuatu yang lebih sulit daripada sekadar “jalan Shaolin”