- Budaya pengembangan yang menjadikan instalasi paket sebagai default memperbesar dependency churn yang berujung pada pembaruan, patch, audit, dan pengelolaan dependensi transitif, sehingga menciptakan biaya tersembunyi bagi produktivitas
- Dampaknya makin besar pada ekosistem dengan sistem packaging yang matang seperti JavaScript dan Rust; contohnya proyek Tokio baru membawa 28 crate, Rocket 172 crate, dan MiniJinja CLI 142 dependensi
- Bahkan fitur yang sudah lama stabil seperti
terminal_size menimbulkan paradoks karena perubahan pada library abstraksi platform memicu crate tambahan dan rilis berulang
- Untuk fitur kecil, membuat implementasi tanpa dependensi dengan ChatGPT atau Cursor bisa lebih cepat daripada menelusuri dependensi dan terus-menerus meng-upgrade, sekaligus mengurangi beban kompilasi kode eksternal
- Library untuk area sulit seperti HTTP, QUIC, grafis, atau tokio memang diperlukan, tetapi keputusan menerima graph dependensi besar demi satu fungsi seharusnya dipertanyakan lebih kritis
Treadmill pemeliharaan yang diciptakan oleh pertumbuhan dependensi
- Pengembang mudah memasang paket demi produktivitas, tetapi akibatnya mereka masuk ke dalam dependency churn berupa pembaruan, patch, audit, dan pengelolaan dependensi transitif yang tak ada habisnya
- Masalah ini semakin menonjol pada ekosistem yang solusi packaging-nya sangat matang, dan JavaScript serta Rust sangat terdampak
- Contoh di Rust:
- Proyek Tokio baru membawa 28 crate
- Proyek Rocket baru bisa membengkak hingga 172 crate
- MiniJinja sendiri bisa ada dengan satu dependensi, tetapi varian CLI-nya membawa 142 dependensi
- Masalah intinya adalah demi satu fitur kecil, kita akhirnya membangun dan mengelola jauh lebih banyak kode eksternal daripada kode yang benar-benar dibutuhkan
Paradoks kode stabil yang ditunjukkan oleh terminal_size
terminal_size adalah crate yang, sesuai namanya, mengetahui ukuran terminal
- API dasar yang dipakai fitur ini pada praktiknya sudah stabil sejak awal terminal komputasi, tetapi tergantung OS tetap menarik 3~4 crate tambahan
- Situasi pun muncul di mana kita mengompilasi ribuan fungsi lain hanya untuk memeriksa apakah terminal berukuran 80x25 atau 120x40
- Crate tersebut telah dirilis 26 kali, tetapi implementasi buatan sendiri yang dimasukkan ke proyek 10 tahun lalu untuk fungsi yang sama masih tetap bekerja tanpa pembaruan
- Alasan banyaknya rilis bukan karena fungsinya berubah, melainkan karena library abstraksi platform yang menjadi fondasinya terus berubah
- Di UNIX ada pengecualian bahwa dependensi
libc memang diperlukan
- Ini karena Rust tidak mengekspos konstanta libc milik platform, dan konstanta tersebut juga tidak terstandardisasi
- Namun
libc adalah dependensi yang umum dan ringan, sehingga sulit dihindari
Keamanan dan budaya penggunaan ulang kode memperkuat dependensi
- Pendekatan ala “big supply chain” mewaspadai tindakan menyalin-tempel fungsi atau memakai
unsafe secara langsung, dan mendorong agar semuanya diserahkan ke lapisan abstraksi platform
- Ada juga perusahaan yang memasok alat untuk menangani masalah dependensi, dan atas nama keamanan mereka mendorong dependensi agar terus dipelihara dan diperbarui ke versi terbaru
- Namun, banyak dependensi justru bisa menjadi sumber utama masalah keamanan
- Tujuan penulisan kode seharusnya adalah mencapai kondisi stabil pada suatu titik sehingga tidak lagi memerlukan pembaruan
- Di ekosistem Rust, bahkan dependensi yang berjalan stabil pun bisa mendapat penilaian rendah di RUSTSEC hanya karena bug tracker-nya agak tidak aktif
- Budaya code review ala perusahaan juga memengaruhi open source
- Engineer yang membawa library baru dan mengilap cenderung lebih mungkin dihargai daripada ditegur
- Akibatnya, muncullah alat seperti Dependabot, dan proyek terus menerima PR pembaruan dependensi
- Di dalam perusahaan, hanya dengan vendoring, audit internal, dan upgrade skala organisasi pun tim engineering bisa dibuat terus sibuk
Fitur kecil bisa dibuat sendiri
- Jalan yang lebih sederhana adalah menulis sendiri kode yang dibutuhkan
- Pekerjaan awal mungkin lebih besar, tetapi setelah selesai, kodenya tidak memerlukan crate baru dan tidak perlu menunggu penulis upstream memperbaiki edge case
- Jika kode rusak di tempat pemakaiannya sendiri, kita bisa langsung memperbaikinya, dan kode yang berfungsi tidak harus selalu naik ke treadmill pemeliharaan
- Per 2025, ChatGPT atau Cursor bisa dengan cepat membuat implementasi tanpa dependensi untuk fitur-fitur kecil yang umum
- Banyak fungsi kecil memiliki overhead pemeliharaan yang rendah dan bisa lebih ringan daripada beban upgrade dependensi terus-menerus
- Jika hanya beberapa baris kode, tidak perlu mengompilasi ribuan baris kode orang lain demi satu fungsi tunggal
Memberi nilai lebih tinggi pada dependensi yang rendah
- Tidak semua dependensi itu buruk
- Library grafis yang mengabstraksi driver kompleks
- Implementasi protokol seperti HTTP dan QUIC
- Library penting seperti tokio yang tidak bisa dan memang tidak ingin dihapus
- Namun, jika hanya memakai satu fungsi tetapi harus mengompilasi ratusan fungsi, itu patut dianggap sebagai sinyal peringatan
- Kita perlu lebih menghargai pilihan menulis fungsi kecil sendiri demi menghindari graph dependensi transitif
- Graph crate yang besar seharusnya dipandang dengan lebih curiga, dan kode sederhana serta stabil yang bisa dibiarkan tanpa disentuh selama bertahun-tahun perlu dinilai positif
sha1-smol awalnya menjadi crate standar untuk menghitung hash SHA1 dengan nama sha1, tetapi kemudian nama itu diserahkan ke rust-crypto dan mendapat tekanan untuk menyesuaikan diri dengan ekosistem crypto yang lebih besar
- Jika memakai crate
sha1 yang baru, akan ikut terbawa 10 dependensi
- Hal ini sulit dihindari karena nama di registry itu penting dan ada tuntutan kompatibilitas trait
- MiniJinja menekankan rendahnya dependensi di README-nya
$ cargo tree
minimal v0.1.0 (examples/minimal)
└── minijinja v2.6.0 (minijinja)
└── serde v1.0.144
- MiniJinja memiliki PR untuk menghapus dependensi terakhir
- Dalam situasi yang tepat, kita perlu merayakan pendekatan membuatnya sendiri, dan memberi lebih banyak pengakuan kepada penulis yang membuat library open source dengan dependensi rendah atau tanpa dependensi sama sekali
1 komentar
Komentar Hacker News
Saya suka bahasa Rust itu sendiri, tetapi tidak suka ekosistem dependensi Rust. Banyak keluhan bahwa C++ sulit menambahkan dependensi, tetapi justru itu terasa seperti sebuah fitur. Karena hal itu membuat kita berpikir apakah benar-benar diperlukan
Di C++, saya mengendalikan dependensi, tetapi di Rust jumlahnya cepat melampaui 100 dan akhirnya saya menyerah. Dari sudut pandang keamanan, terus terang saya tidak bisa tahu apa yang sebenarnya saya distribusikan
Selain itu Rust juga tidak punya kompatibilitas ABI dan tidak punya budaya pustaka bersama. Jadi rasanya merusak model distribusi paket sistem operasi. Saat memilih distro Linux, kita mempercayai orang-orang yang membangun distro itu, tetapi Rust tampak lebih dekat ke Python, di mana siapa pun bisa mengunggah sesuatu ke PyPI
Bagaimana dengan Docker/Python/Rust? Saya sama sekali tidak mengenal orang-orang yang membuat image Docker, paket PyPI, atau crate Rust saya
Pada dasarnya kita kembali ke masa ketika EXE dan DLL dikirim-kirim lewat ZIP. Hanya saja sekarang kita menyebutnya container, dan dengan bangga menjalankannya sebagai root
Seperti kata penulis, terkadang yang terbaik adalah sekadar menggabungkan kode sumber dependensi. Dulu ini disebut vendoring, dan cukup penting di Rails/Ruby. Keuntungan besarnya adalah kelak tidak terdampak oleh pengambilalihan paket yang berbahaya, dan jika mau, patch keamanan upstream bisa digabungkan sendiri
Saya tidak bisa memikirkan proyek di mana sindrom NIH menghasilkan efek bersih yang positif. Bahkan dependensi yang tidak esensial pun menghemat banyak waktu
Jika sebagian dependensi opsional dibuat ulang di setiap proyek, saya penasaran dari mana datangnya waktu untuk memperbaiki bug tambahan, kondisi batas, berbagai versi dependensi turunan, dan dukungan berbagai platform
Jika ini digabungkan dengan repositori yang bisa diunggah siapa saja dan kurasinya lemah seperti PyPI, npm, Cargo, serta standard library yang kecil, bersiaplah untuk menderita
Developerlah yang memilih dependensi mana yang akan diambil. Dependensi yang tidak dipakai siapa pun akan hilang, dan alasan sebagian besar library punya banyak dependensi adalah karena banyak developer lebih suka membangun sesuatu di atas dependensi
Kalau yang dibahas adalah build system, Cargo tidak memaksa penggunaan Crates.io. Ia hanya mempermudahnya. Dependensi berbasis path seperti CMake/Vcpkg, Conan juga bisa dipakai, atau library bisa dibuat sendiri
Bahkan jika memakai Crates.io, kalau tidak suka perubahan, cukup kunci versinya. Ia hanya memudahkan mendapatkan versi terbaru
Di Rust, mudah membangun software di atas software yang sudah ada. Jika tidak suka software yang ada atau laju perubahannya, jangan salahkan Cargo; lakukan dengan cara yang diinginkan
Distro masih membangun paket Rust dari sumber dan melakukan vendoring dependensi crate ke repositori. Karena dependensinya lebih banyak dan pembaruannya juga sering, ini lebih menyakitkan, tetapi ini terpisah dari shared library
Pernyataan bahwa API untuk mengetahui ukuran terminal sudah stabil selama 50 tahun tidak akurat. Setahu saya, ioctl TIOCGWINSZ tidak pernah distandardisasi, dan namanya pun beragam di berbagai Unix dan BSD
Fungsi
tcgetwinsize()baru masuk POSIX pada 2024, dan keseluruhan topik ini punya sejarah yang cukup menyedihkan https://news.ycombinator.com/item?id=42039401. Maksudnya, bahkan sebelum masuk ke sisi Windows pun sudah begituKadang itu tidak masalah, tetapi bagi orang dengan use case lain atau orang yang menjalankannya di sistem yang tidak dipahami dan tidak dipakai penulis, software itu bisa menjadi lebih buruk
Nilai sebenarnya dari sebuah library adalah menangani fakta bahwa bahkan masalah yang tampak sederhana pun sebenarnya punya banyak kompleksitas. Saya juga tidak menganggap 3–4 dependensi untuk library yang berjalan di Windows/Linux itu terlalu banyak. Dalam kasus yang baik, orang yang memakai library itu lebih berpengalaman di area tersebut dan bisa menangani bagian-bagian tak diketahui yang tidak saya ketahui
ioctl memang punya masalah, tetapi perubahan yang membuat
terminal-sizeatau dependensinya merilis beberapa versi tidak berkaitan dengan konstantaioctl/TIOCGWINSZatau structwinsize. Kode itu tidak berubahterminal-sizehanya memanggiltcgetwinsizemilik Rustix, lalu Rustix kembali memanggiltcgetwinsizemilik libc. Jadi jika melakukan hal yang sama secara langsung, dependensi bisa cukup dikurangi, dengan biaya kira-kira dukungan WindowsApakah API ini stabil selama 50 tahun atau 25 tahun adalah detail. Dependensi tersebut bahkan tidak pura-pura menangani kompleksitas itu, dan kecil kemungkinan fungsi itu akan berubah atau dihapus dalam waktu dekat
Kebanyakan orang menulis langsung ke sana, tetapi fitur seperti ukuran terminal atau raw mode berantakan dan membutuhkan sesuatu seperti
ioctl. Terus terang, itu tidak bagusNamun library lebih tidak bagus lagi. Kalau tidak ingin link ke
ncurses, semoga Tuhan menolong AndaBaru-baru ini saya menghidupkan kembali web app startup pertama yang saya buat pada 2006. Itu adalah situs media sosial yang berfokus pada berbagi media, dan menurut standar saat itu merupakan LAMP stack yang cukup sederhana. PHP 5, MySQL 3.2, tetapi secara umum sudah punya fitur media sosial pada masanya
Karena ingin mencoba sendiri teknologi CI/CD baru, saya sedang membuat proses deployment dengan merekayasa app ini secara berlebihan untuk belajar. Bisa saja memakai WordPress atau app Hello World, tetapi ini jauh lebih menarik
Hampir semua PHP saya tulis sendiri. Saya juga membuat sendiri library untuk autentikasi/otorisasi, template, pemrosesan form, dan sebagainya, dan hanya memakai satu library PEAR untuk pengiriman email. Frontend-nya HTML murni, hampir tidak ada JavaScript, dan Flash dipakai untuk pemutaran media. Pada 2006, kebanyakan orang membuatnya seperti ini
Hanya butuh sekitar satu jam untuk menjalankan kembali app berusia 19 tahun itu. Saya mengganti driver PHP
mysqllama denganmysqli, lalu menyesuaikan skema dan sebagian query untuk MySQL 8. Utamanya hanya membungkus kata-kata yang kini menjadi reserved word dengan backtick dan memperbaiki default value kolom yang sekarang lebih ketat. Satu-satunya yang tidak jalan hanya FlashSebaliknya, di tempat kerja sekarang kami mengoperasikan puluhan app Spring Boot yang ditulis dengan Java 8, dan daftar vulnerability yang berasal dari puluhan dependency menumpuk sampai berhalaman-halaman. Kalau satu di-update, library lain juga harus ikut naik berantai, dan karena transitive dependency ini menjadi mimpi buruk. Jadi kami hanya menangani seminimal mungkin vulnerability yang paling kritis, dan tidak ada rencana realistis untuk menaikkan semuanya
Yang lucu, apa yang dilakukan app PHP tahun 2006 itu tidak jauh berbeda dari apa yang dilakukan app-app Spring Boot saat ini. Pada akhirnya semuanya CRUD, hanya saja kini di sekelilingnya jauh lebih banyak hiasan dan tooling enterprise
Tidak menarik satu dependency untuk setiap item di checklist. Mungkin ada pekerjaan yang duplikatif, tetapi jalur upgrade menjadi jauh lebih mudah
scp, ini umumnya bukan masalahMisalnya, untuk format pesan komunikasi standar seperti FHIR atau HL7, orang tentu tidak ingin mengimplementasikan sendiri seluruh definisi standar yang sudah kompleks itu
Menulis sendiri fungsi kriptografi juga biasanya sama saja menembak kaki sendiri, dan berbagai masalah keamanan serius yang ditemukan selama bertahun-tahun sudah membuktikannya
Sekarang ini eranya ingin fokus menyelesaikan masalah bisnis, bukan bagaimana sebuah solusi dibuat dengan benar. Dengan hadirnya AI, ketika semua kode terasa seperti disambung-sambung sambil mata tertutup, hal ini menjadi makin penting
Menghabiskan waktu membuat semuanya sendiri mungkin menguntungkan dalam jangka panjang, tetapi pertama-tama kita harus bertahan dalam persaingan. Kompetitor mungkin sudah merebut pasar sejak awal dengan kode yang cepat dibuat dan bisa dibuang
Baru-baru ini kami pindah dari Java 8, Spring Boot 2, Swagger ke Java 17, Spring Boot 3.3, OpenAPI 3, dan prosesnya cukup painless
Masih ada beberapa dependency langsung dan transitive dependency yang perlu dinaikkan lagi, tetapi hambatan terbesar sudah tertangani lewat migrasi
Namun selama tidak menautkan ke library C, private transitive dependency sama sekali tidak menjadi masalah. Dalam dependency tree yang sama Anda bisa menaruh sebanyak mungkin versi crate yang tidak kompatibel secara SemVer, dan jika perlu Anda juga bisa bergantung langsung pada beberapa versi
Tidak perlu upgrade massal ala Java; cukup naikkan satu yang punya vulnerability. Setahu saya C# juga punya kemampuan serupa, tetapi sedikit lebih verbose
Saya 100% setuju. NodeJS punya pengaruh besar pada karier saya, tetapi NPM memberi trauma yang lebih besar daripada masa kecil yang kacau
Bayangkan seorang programmer baru sedang membuat app baru untuk ditunjukkan kepada teman-temannya. Ia ingin menambahkan dependency baru, tetapi tidak cocok dengan dependency lain, jadi ia memutuskan meng-update semuanya. Sesaat kemudian tidak ada yang berjalan dan Babel berteriak
Mungkin ia berpikir bagaimanapun nanti akan bisa diselesaikan, tetapi tak lama kemudian ia melihat issue Git terbuka yang menunjukkan bahkan hal mendasar secara harfiah tidak berjalan. Misalnya, di Expo ada issue terbuka bahwa proyek React Native baru default tidak bisa di-build di Android
Separuhnya terasa seperti tidak ada yang peduli, dan dalam kasus itu solusinya pun bukan berada di ekosistem Node, melainkan di suatu tempat di ekosistem Android. Dari atas sampai bawah semuanya duct tape. Meski begitu, kalau proyek bernilai miliaran dolar saja bisa merilis template yang tidak berfungsi, itu juga memberi keyakinan bahwa saya tidak perlu merasa imposter syndrome hanya karena side project saya separuhnya tidak jalan
Saya mulai melihat momen memasukkan dependency pertama sebagai kegagalan pribadi. Karena pada saat itu, alih-alih sekadar memuat JS biasa dengan tag script, seluruh urusan packaging dan organisasi menjadi diperlukan hanya demi memakai satu
package.jsonIni adalah hal yang mengejutkan saat beralih dari Go ke ekosistem Rust. Proyek Go yang matang, misalnya backend web produksi sebuah perusahaan, bisa saja hanya memiliki 10–20 dependensi, termasuk dependensi transitif
Seperti yang disebutkan dalam tulisan itu, proyek Rust kecil pun kemungkinan besar akan memiliki jauh lebih banyak dari itu, dan jika melakukan pekerjaan asinkron, hampir pasti demikian
Saya tidak yakin apakah ini karena budaya atau karena fitur bahasa. Misalnya, di Go, interface dipenuhi secara implisit, jadi tidak perlu mengambil sesuatu hanya untuk menyatakan bahwa kita mengimplementasikannya
Hal-hal yang ada di bahasa atau standard library Go tetapi membutuhkan dependensi di Rust antara lain green thread, channel, regex, HTTP client, HTTP server, waktu, flag command-line, logger, membaca/menulis GIF animasi, dan sebagainya
Saya tidak terlalu menyukai bahasa Go itu sendiri, tetapi dalam hal tooling dan standard library, Go berada di depan, dan jelas yang terbaik dari yang pernah saya pakai
Saya sangat setuju dengan argumennya. Membiarkan abstraksi dari library lain terekspos ke luar library kita sendiri memiliki banyak biaya tersembunyi. Bukan berarti itu sama sekali tidak boleh dilakukan, tetapi saat mengambil keputusan, biaya di masa depan harus dipertimbangkan secara seimbang
Jika paket pembungkus sering mengubah desain atau mengubah tujuannya, akan muncul ketidakstabilan. Fitur yang semula merupakan bentuk jaminan paling sederhana dalam rekayasa perangkat lunak bisa hilang atau terpecah
Selain itu, ini membuat pemilik yang bukan kontributor open source karier tetapi memahami bidang tertentu menjadi sulit berpartisipasi dalam ekosistem. Jika “saya membuat cara yang rapi untuk melakukan X” berubah menjadi diskusi, negosiasi, dan politik selama berminggu-minggu tentang “karena orang mungkin menyukai Z, X harus cocok di bawah Y”, itu membuang waktu semua orang
Satu hal yang saya pelajari dalam hidup adalah bahwa hal yang paling sederhana bertahan paling lama. Minilith dan monolith seharusnya lebih sering dipuji. Ini juga bukan masalah khusus Rust; saya sudah melihatnya di berbagai bahasa. Komunitas open source sering sangat mendorong paket berukuran atomik, dan saya sering bertanya-tanya apakah tujuannya lebih untuk menancapkan bendera atau memindahkan kepemilikan daripada untuk kepentingan komunitas pengguna yang sebenarnya
Pada 2025, saya sedikit banyak secara kebetulan sampai pada pandangan bahwa lebih cepat meminta ChatGPT atau Cursor membuat implementasi tanpa dependensi untuk fungsi-fungsi umum, dan saya makin setuju dengannya. Terutama setelah mengalami dependency hell di aplikasi React besar
Dependensi pada SaaS atau layanan pihak ketiga juga perlu dipikirkan. Banyak di antaranya adalah pola umum dan masalah yang sudah terselesaikan, sehingga LLM dapat menirunya dengan cepat
Untuk masalah dengan cakupan terbatas, ini cukup efektif, dan saya bisa meminta AI membuat implementasi yang lebih lengkap dan kokoh daripada jika saya menulisnya sendiri
Kalaupun nanti memutuskan menambahkan library, akan ada enkapsulasi yang alami. Cukup ubah implementasi fungsi saya agar memakai library, tanpa harus menyentuh semua tempat yang menggunakannya. Saat waktunya tiba, mencoba beberapa library juga jadi mudah
Ironisnya, ini cukup menarik. Armin adalah penulis asli framework web Python Flask. Pada periode yang mirip, ada juga library yang sangat serupa bernama Bottle
Fungsinya hampir sama, tetapi Flask menjadi sangat populer, sementara saya selalu lebih menyukai Bottle. Alasannya, Bottle berupa satu file dan tanpa dependensi, sehingga sangat mudah disalin begitu saja ke proyek
Mudah juga untuk diutak-atik, dan akhirnya saya sampai pada titik bisa memahami keseluruhannya. Untuk server dan WebSocket saya memasangkan Gevent, tetapi dengan cara itu saya bisa membuat proyek yang cukup berat
Sampai sekarang pun saya masih punya dorongan kuat untuk memakai Bottle pada proyek web kecil. Sayangnya, Bottle tidak banyak mengikuti praktik modern yang diperkenalkan Python selama bertahun-tahun, jadi kini terlihat agak usang
Untuk membuat sendiri, diperlukan kemampuan engineering yang mumpuni. Jika yang ada hanya engineer yang selama ini selalu mengambil library dari ekosistem seperti NPM atau PyPI, mereka akan kesulitan mengembangkan sendiri solusi untuk banyak masalah. Terutama jika solusinya harus tahan lama dan memiliki fleksibilitas yang dibutuhkan
“Tidak memprogram diri sendiri ke jalan buntu” membutuhkan banyak latihan
Saya juga sering melihat kasus di mana kita bisa dengan mudah membuat sesuatu yang lebih baik daripada library yang ada. Dalam satu proyek, saya mengimplementasikan parser untuk varian Markdown yang memiliki metadata di bagian atas file. Sintaksnya kecil, dan parser-nya jadi dengan kode kurang dari satu layar
Namun library frontend yang mem-parse file yang sama ternyata jauh lebih buruk dari perkiraan. Jika identifier metadata memiliki tanda hubung, ia rusak, dan ternyata identifier metadata itu dipakai langsung sebagai nama anggota objek. Alih-alih memakai objek JSON sederhana, mereka membatasi pilihan nama secara artifisial dan membuatnya rusak jika ada tanda hubung seperti
something-somethingPada akhirnya parser saya dibuang, dengan alasan orang-orang harus “memeliharanya”. Padahal parser itu berjalan begitu saja, dan mudah beradaptasi terhadap perubahan sintaks. Jika tahu sedikit saja tentang parser, tidak ada yang sulit dipahami
Sulit dipercaya, tetapi sepertinya tidak ada orang lain di tim selain saya yang pernah menulis parser dengan library parser generator. Ada banyak contoh lain seperti ini
Jika sampai harus mengompilasi ratusan hal hanya untuk memakai satu fungsi, seharusnya itu menjadi lampu peringatan. Sekitar setahun lalu, saya mengerjakan proyek untuk memperbarui dependensi pihak ketiga.
Salah satunya adalah pustaka matematika yang kaya, berisi berbagai macam fungsi matematika. Setelah ditelusuri sedikit, ternyata yang kami pakai hanya satu metode untuk mencari median dari sebuah list.
Saya mengarahkan engineer yang bertanggung jawab ke halaman Wikipedia, menghapus dependensi itu, lalu memintanya menulis satu metode saja untuk melakukan operasi matematika tersebut.
Namun masalah sebenarnya bukanlah penggunaan dependensi pihak ketiga itu sendiri, melainkan perlunya konsep untuk hanya mengambil bagian sempit dari sebuah pustaka. Jika yang dibutuhkan hanya sebagian kecil dari pustaka raksasa, mengapa harus membawa semuanya? Saya pernah mendengar usulan pendekatan “microframework” untuk hal ini.
Sayangnya, tampaknya orang-orang tidak benar-benar meninjau dengan saksama kumpulan fitur default yang digunakan dependensi dan secara aktif memangkasnya. Sintaks untuk menambahkan fitur tambahan memang sederhana, tetapi untuk menghapus fitur opsional yang aktif secara default, Anda harus menentukan
no-default-featureslalu tetap menambahkan kembali satu per satu fitur default yang masih diinginkan, sehingga lebih merepotkan.Yang lebih buruk, agar sebuah pustaka bisa membuat pengguna memangkas fitur yang tidak perlu dari dependensinya sendiri, pustaka itu harus membuat fiturnya sendiri dan memetakannya ke fitur tiap dependensi. Misalnya ada 5 dependensi dan masing-masing punya 1 dependensi wajib serta 4 dependensi opsional; agar pengguna bisa mengontrol penuh fitur transitif, pustaka Anda harus membuat 20 fitur pemetaan. Itu pun belum termasuk fitur yang akan Anda buat demi mempertimbangkan pengguna hilir untuk kode Anda sendiri.
Saya makin melihat bahwa usability di sekitar fitur, terutama untuk mengurangi pembengkakan yang tidak perlu, sangat buruk sehingga menjadi pemicu masalah waktu kompilasi Rust. Sepertinya topik seperti ini pun tidak banyak dibahas, jadi mungkin saya perlu menulis pemikiran kuat saya ini sebagai artikel blog agar bisa dirujuk jika kondisi saat ini terus berlanjut.
Di satu sisi, menurut saya itu bukan masalah jika sistem kepercayaannya bagus.
Saya juga cukup menyukai pendekatan seperti Shadcn, yaitu gagasan bahwa jika Anda menyukai sebuah komponen, Anda menyalinnya ke pustaka Anda sendiri. Namun jika muncul kerentanan, saya tidak bisa tahu apakah saya terdampak.
Untuk sebagian kode itu tidak masalah, tetapi untuk kode lain kita benar-benar harus bergantung pada sebanyak mungkin orang yang meninjaunya.
Median(list) { let len = length(list) if len % 2 == 0 { let x = floor(len/2) return (list[x] + list[x+1]) / 2 } return list[len/2] }Dengan asumsi list sudah diurutkan. Saya menahan godaan untuk memanggil
is_odddi sini.