Menggunakan Rust saat memulai: Kisah peringatan

Nov 25 2022
Karat itu luar biasa, untuk hal-hal tertentu. Tapi pikirkan dua kali sebelum mengambilnya untuk startup yang perlu bergerak cepat.

Karat itu luar biasa, untuk hal-hal tertentu. Tapi pikirkan dua kali sebelum mengambilnya untuk startup yang perlu bergerak cepat.

Semua seni untuk posting ini dihasilkan menggunakan DALL-E.

Saya ragu-ragu menulis posting ini, karena saya tidak ingin memulai, atau terlibat dalam, perang suci atas bahasa pemrograman. (Hanya untuk menghilangkan umpan api, Visual Basic adalah bahasa terbaik yang pernah ada!) Tetapi saya memiliki sejumlah orang yang bertanya kepada saya tentang pengalaman saya dengan Rust dan apakah mereka harus menggunakan Rust untuk proyek mereka. Jadi, saya ingin berbagi beberapa pro dan kontra yang saya lihat tentang penggunaan Rust dalam pengaturan startup, di mana pergerakan tim yang cepat dan penskalaan sangat penting.

Saya ingin memperjelas bahwa saya adalah penggemar Rust untuk hal-hal tertentu . Posting ini bukan tentang bagaimana Rust buruk sebagai bahasa atau semacamnya. Apa yang ingin saya bicarakan, bagaimanapun, adalah bagaimana menggunakan Rust hampir pasti akan melibatkan hit produktivitas nontrivial yang bisa menjadi faktor utama jika Anda mencoba untuk bergerak cepat. Timbang dengan hati-hati apakah dampak kecepatan sepadan dengan manfaat bahasa untuk perusahaan dan produk Anda.

Tepat di depan, saya harus mengatakan bahwa Rust sangat bagus dalam apa yang dirancang untuk dilakukannya , dan jika proyek Anda membutuhkan manfaat khusus dari Rust (bahasa sistem dengan kinerja tinggi, pengetikan super kuat, tidak perlu pengumpulan sampah, dll.) maka Rust adalah pilihan yang bagus. Tapi saya pikir Rust sering digunakan dalam situasi di mana itu tidak cocok, dan tim membayar harga kerumitan dan overhead Rust tanpa mendapatkan banyak keuntungan.

Pengalaman utama saya dari Rust berasal dari bekerja dengannya selama lebih dari 2 tahun di startup sebelumnya. Proyek ini adalah produk SaaS berbasis cloud yang, kurang lebih, merupakan aplikasi CRUD konvensional: ini adalah sekumpulan layanan mikro yang menyediakan titik akhir REST dan gRPC API di depan database, serta beberapa back- end microservices (diimplementasikan sendiri dalam kombinasi Rust dan Python). Rust digunakan terutama karena beberapa pendiri perusahaan adalah pakar Rust. Seiring waktu, kami mengembangkan tim secara signifikan (meningkatkan jumlah staf teknik hampir 10x lipat), dan ukuran serta kompleksitas basis kode juga meningkat pesat.

Saat tim dan basis kode berkembang, saya merasa bahwa, seiring waktu, kami membayar pajak yang semakin berat untuk terus menggunakan Rust. Pengembangan terkadang lamban, peluncuran fitur baru memakan waktu lebih lama dari yang saya perkirakan, dan tim merasakan produktivitas nyata terpukul dari keputusan awal untuk menggunakan Rust. Menulis ulang kode dalam bahasa lain, dalam jangka panjang, akan membuat pengembangan jauh lebih gesit dan mempercepat waktu pengiriman, tetapi menemukan waktu untuk pekerjaan penulisan ulang utama akan sangat sulit. Jadi kami agak terjebak dengan Rust kecuali kami memutuskan untuk menggigit peluru dan menulis ulang sejumlah besar kode.

Karat seharusnya menjadi yang terbaik sejak mengiris roti, jadi mengapa itu tidak bekerja dengan baik untuk kita?

Karat memiliki kurva belajar yang sangat besar.

Saya telah bekerja dalam lusinan bahasa dalam karier saya, dan dengan sedikit pengecualian, sebagian besar bahasa prosedural modern (C++, Go, Python, Java, dll.) semuanya sangat mirip dalam hal konsep dasarnya. Setiap bahasa memiliki perbedaannya tetapi biasanya ini adalah masalah mempelajari beberapa pola kunci yang berbeda di seluruh bahasa dan kemudian seseorang dapat menjadi produktif dengan cepat. Namun, dengan Rust, seseorang perlu mempelajari ide- ide yang sama sekali baru — hal-hal seperti masa hidup, kepemilikan, dan pemeriksa pinjaman. Ini bukanlah konsep yang familiar bagi kebanyakan orang yang bekerja dalam bahasa umum lainnya, dan ada kurva belajar yang cukup curam, bahkan untuk pemrogram berpengalaman.

Beberapa dari ide-ide "baru" itu, tentu saja, hadir dalam bahasa lain - terutama yang fungsional - tetapi Rust membawanya ke pengaturan bahasa "arus utama", dan karenanya akan menjadi hal baru bagi banyak pendatang baru Rust.

Meskipun menjadi beberapa pengembang paling cerdas dan paling berpengalaman yang pernah bekerja dengan saya, banyak orang di tim (termasuk saya sendiri) berjuang untuk memahami cara kanonik untuk melakukan hal-hal tertentu di Rust, bagaimana mencari pesan kesalahan yang sering misterius dari kompiler, atau cara memahami cara kerja pustaka kunci (lebih lanjut tentang ini di bawah). Kami mulai mengadakan sesi “belajar Rust” mingguan untuk membantu tim berbagi pengetahuan dan keahlian. Ini semua sangat menguras produktivitas dan moral tim karena semua orang merasakan lambatnya perkembangan.

Sebagai titik perbandingan untuk mengadopsi bahasa baru pada tim perangkat lunak, salah satu tim saya di Google adalah salah satu yang pertama beralih sepenuhnya dari C++ ke Go, dan butuh waktu tidak lebih dari dua minggu sebelum seluruh Tim beranggotakan 15 orang dengan cukup nyaman membuat kode di Go untuk pertama kalinya. Dengan Rust, bahkan setelah berbulan-bulan bekerja setiap hari dalam bahasa tersebut, kebanyakan orang di tim tidak pernah merasa kompeten sepenuhnya. Sejumlah pengembang memberi tahu saya bahwa mereka sering merasa malu karena butuh waktu lebih lama dari yang mereka perkirakan untuk menampilkan fitur mereka dan bahwa mereka menghabiskan waktu begitu lama untuk mencoba memahami Rust.

Ada cara lain untuk memperbaiki masalah yang coba dipecahkan oleh Rust.

Seperti disebutkan di atas, layanan yang kami buat adalah aplikasi CRUD yang cukup sederhana. Beban yang diharapkan pada layanan ini akan berada di urutan tidak lebih dari beberapa kueri per detik, maks, selama masa pakai sistem khusus ini. Layanan ini merupakan bagian depan dari pipa pemrosesan data yang cukup rumit yang dapat memakan waktu berjam-jam untuk dijalankan, sehingga layanan itu sendiri tidak diharapkan menjadi hambatan kinerja. Tidak ada kekhawatiran khusus bahwa bahasa konvensional seperti Python akan mengalami kesulitan memberikan kinerja yang baik. Tidak ada kebutuhan keamanan atau konkurensi khusus di luar apa yang perlu ditangani oleh layanan yang menghadap ke web. Satu-satunya alasan kami menggunakan Rust adalah karena penulis asli sistem ini adalah pakar Rust, bukan karena sangat cocok untuk membangun layanan semacam ini.

Rust telah membuat keputusan bahwa keselamatan lebih penting daripada produktivitas pengembang. Ini adalah tradeoff yang tepat untuk dilakukan dalam banyak situasi — seperti membuat kode dalam kernel OS, atau untuk sistem tertanam yang dibatasi memori — tetapi menurut saya ini bukan tradeoff yang tepat dalam semua kasus, terutama pada startup di mana kecepatan sangat penting. Saya seorang pragmatis. Saya lebih suka tim saya menyisihkan waktu untuk men-debug kebocoran memori sesekali atau kesalahan ketik untuk kode yang ditulis dalam, katakanlah, Python atau Go, daripada meminta semua orang di tim mengalami penurunan produktivitas 4x karena menggunakan bahasa yang dirancang untuk menghindari masalah ini sepenuhnya .

Seperti yang saya sebutkan di atas, tim saya di Google membangun sebuah layanan, seluruhnya dalam Go, yang dari waktu ke waktu tumbuh untuk mendukung lebih dari 800 juta pengguna dan kira-kira 4x QPS Google Penelusuran pada puncaknya. Di satu sisi, saya dapat menghitung berapa kali kami mengalami masalah yang disebabkan oleh sistem tipe Go atau pengumpul sampah selama bertahun-tahun membangun dan menjalankan layanan ini. Pada dasarnya, masalah yang dirancang untuk dihindari oleh Rust dapat diselesaikan dengan cara lain — dengan pengujian yang baik, linting yang baik, tinjauan kode yang baik, dan pemantauan yang baik. Tentu saja, tidak semua proyek perangkat lunak memiliki kemewahan ini, jadi saya dapat membayangkan bahwa Rust mungkin merupakan pilihan yang baik dalam situasi lain tersebut.

Anda akan kesulitan mempekerjakan pengembang Rust.

Kami mempekerjakan banyak orang selama saya bekerja di perusahaan ini, tetapi hanya sekitar dua atau tiga dari 60+ orang yang bergabung dengan tim teknik memiliki pengalaman sebelumnya dengan Rust. Ini bukan karena ingin mencoba menemukan Rust devs - mereka tidak ada di luar sana. (Dengan cara yang sama kami ragu-ragu untuk mempekerjakan orang yang hanya ingin membuat kode di Rust, karena saya pikir itu adalah harapan yang buruk untuk ditetapkan dalam pengaturan startup di mana pilihan bahasa dan teknologi lainnya perlu dibuat dengan cara yang gesit.) Kekurangan ini bakat dev Rust akan berubah seiring waktu, karena Rust menjadi lebih utama, tetapi membangun di sekitar Rust dengan asumsi Anda akan dapat mempekerjakan orang yang sudah mengetahuinya tampaknya berisiko.

Faktor sekunder lainnya adalah penggunaan Rust hampir pasti akan menyebabkan perpecahan antara orang-orang dalam tim yang mengenal Rust dan mereka yang tidak. Karena kami telah memilih bahasa pemrograman "esoteris" untuk layanan ini, insinyur lain di perusahaan yang mungkin telah membantu dalam membangun fitur, men-debug masalah produksi, dan sebagainya sebagian besar tidak dapat membantu karena mereka tidak dapat membuat kepala atau ekor dari basis kode Rust. Kurangnya kesepadanan dalam tim teknik ini dapat menjadi tanggung jawab nyata saat Anda mencoba untuk bergerak cepat dan memanfaatkan kekuatan gabungan dari semua orang di tim. Dalam pengalaman saya, orang umumnya memiliki sedikit kesulitan berpindah antar bahasa seperti C ++ dan Python, tetapi Rust cukup baru, dan cukup kompleks, sehingga menjadi penghalang bagi orang yang bekerja bersama.

Perpustakaan dan dokumentasi belum matang.

Ini adalah masalah yang (saya harap!) akan diperbaiki dari waktu ke waktu, tetapi dibandingkan dengan, katakanlah, Go, ekosistem perpustakaan dan dokumentasi Rust sangat belum matang. Sekarang, Go mendapat manfaat karena dikembangkan dan didukung oleh seluruh tim khusus di Google sebelum dirilis ke dunia, sehingga dokumen dan pustaka cukup disempurnakan. Karat, sebagai perbandingan, telah lama terasa seperti pekerjaan yang sedang berjalan. Dokumen untuk banyak pustaka populer cukup jarang, dan sering kali perlu membaca kode sumber pustaka tertentu untuk memahami cara menggunakannya. Ini buruk.

Pembela karat di tim sering mengatakan hal-hal seperti "async/menunggu masih sangat baru" dan "ya dokumen untuk perpustakaan itu kurang" tetapi kekurangan ini berdampak cukup signifikan pada tim. Kami membuat kesalahan besar sejak awal dengan mengadopsi Actix sebagai kerangka kerja web untuk layanan kami, sebuah keputusan yang menyebabkan rasa sakit dan penderitaan yang luar biasa saat kami menemukan bug dan masalah yang terkubur jauh di dalam perpustakaan yang tidak dapat diperbaiki oleh siapa pun. (Agar adil, ini beberapa tahun yang lalu dan mungkin keadaan sudah membaik sekarang.)

Tentu saja, ketidakdewasaan semacam ini tidak terlalu spesifik untuk Rust, tetapi itu merupakan pajak yang harus dibayar oleh tim Anda. Tidak peduli seberapa bagus dokumentasi dan tutorial bahasa inti, jika Anda tidak tahu cara menggunakan perpustakaan, itu tidak masalah (kecuali jika Anda berencana untuk menulis semuanya dari awal, tentu saja).

Karat membuat fitur baru menjadi sangat sulit.

Saya tidak tahu tentang orang lain, tetapi setidaknya bagi saya, ketika saya membuat fitur baru, saya biasanya tidak memiliki semua tipe data, API, dan detail bagus lainnya yang berfungsi di awal. Saya sering hanya mengeluarkan kode mencoba membuat beberapa ide dasar berfungsi dan memeriksa apakah asumsi saya tentang cara kerja sesuatu kurang lebih benar. Melakukan hal ini, katakanlah, Python sangat mudah, karena Anda dapat bermain cepat dan lepas dengan hal-hal seperti mengetik dan tidak khawatir jika jalur kode tertentu rusak saat Anda menyusun ide Anda. Anda dapat kembali lagi nanti dan merapikan semuanya dan memperbaiki semua kesalahan ketik dan menulis semua pengujian.

Di Rust, "draft coding" semacam ini sangat sulit, karena kompiler dapat dan akan mengeluh tentang setiap hal yang tidak lulus pemeriksaan tipe dan seumur hidup - seperti yang dirancang secara eksplisit untuk dilakukan. Ini sangat masuk akal ketika Anda perlu membangun implementasi akhir Anda yang siap produksi, tetapi benar-benar menyebalkan ketika Anda mencoba menyatukan sesuatu untuk menguji ide atau mendapatkan fondasi dasar. Makro unimplemented!sangat membantu sampai titik tertentu, tetapi masih mengharuskan semua jenis pemeriksaan atas dan ke bawah tumpukan bahkan sebelum Anda dapat mengompilasi.

Apa yang benar-benar menggigit adalah ketika Anda perlu mengubah tanda tangan jenis dari antarmuka penahan beban dan menemukan diri Anda menghabiskan berjam-jam mengubah setiap tempat di mana jenis itu digunakan hanya untuk melihat apakah percobaan awal Anda pada sesuatu layak dilakukan. Dan kemudian ulangi semua pekerjaan itu saat Anda menyadari bahwa Anda perlu mengubahnya lagi.

Apa yang bagus dari Rust?

Pasti ada hal-hal yang saya sukai dari Rust, dan fitur-fitur dari Rust yang ingin saya miliki dalam bahasa lain. Sintaksnya matchbagus. Sifat Option, Result, dan Errorsangat kuat, dan ?operator adalah cara yang elegan untuk menangani kesalahan. Banyak dari ide-ide ini memiliki padanan dalam bahasa lain, tetapi pendekatan Rust dengan mereka sangat elegan.

Saya benar-benar akan menggunakan Rust untuk proyek yang membutuhkan kinerja dan keamanan tingkat tinggi dan untuk itu saya tidak terlalu khawatir tentang kebutuhan untuk mengembangkan bagian utama kode secara cepat dengan seluruh tim yang berkembang pesat. Untuk proyek individu, atau tim yang sangat kecil (katakanlah, 2–3 orang), Rust kemungkinan akan baik-baik saja. Karat adalah pilihan tepat untuk hal-hal seperti modul kernel, firmware, mesin game, dll. di mana kinerja dan keamanan adalah yang terpenting, dan dalam situasi di mana mungkin sulit untuk melakukan pengujian menyeluruh sebelum pengiriman.

Oke, sekarang saya sudah cukup membuat marah setengah dari pembaca Berita Peretas, saya kira sekarang adalah waktu yang tepat untuk mengumumkan topik artikel saya berikutnya: Mengapa nanoeditor teks unggul. Sampai jumpa lain waktu!