Menulis Ulang dengan Rails
(dirkjonker.bearblog.dev)- Setelah meninjau beberapa stack untuk aplikasi pembuatan formulir deklarasi bea cukai, Ruby on Rails yang sudah familier dipakai untuk implementasi awal karena terasa jauh lebih cepat untuk membangun fitur dibanding opsi baru
- “version 2” yang dibuat dengan backend Rust dan frontend SvelteKit memang cepat dan terlihat bagus, tetapi hanya mencakup sekitar 10% dari fitur yang dibutuhkan, dan pekerjaan plumbing lebih besar daripada kode bisnis
- Migrasi bertahap hampir tidak menambah nilai bagi pengguna karena harus merangkai sendiri routing, akses data, otorisasi, pelacakan perubahan, pencarian, pekerjaan latar belakang, pub/sub, email, OAuth 2.0, SMTP/POP, object storage, hingga pembuatan PDF
- Diputuskan untuk mengembalikan hanya bagian yang sudah dipindahkan ke stack baru kembali ke Rails; situasi ketika sendirian memelihara aplikasi Rails, stres karena tidak bisa memenuhi kebutuhan pengguna, dan kompleksitas memperbaiki banyak tempat sekaligus turut memengaruhi keputusan ini
- Setelah kembali ke Rails, kecepatan pengembangan fitur, perbaikan fitur lama, pembaruan UI, dan perbaikan bug kembali meningkat; kekurangan Ruby/Rails ditangani dengan testing, refactoring, Turbo, dan caching sambil memilih untuk fokus pada pengembangan produk
Titik awal: memilih Rails sebagai opsi sementara
- Pada 2022, saat mulai membuat aplikasi pembuatan formulir deklarasi bea cukai, berbagai bahasa dan framework seperti .NET/F#, Go, Rust, dan React ditinjau dan bahkan dicoba ditulis kodenya
- Pilihan akhirnya adalah Ruby on Rails
- Itu adalah alat yang sudah familier, dan terasa bisa maju 10 kali lebih cepat dibanding opsi yang harus dipelajari dari awal
- Implementasi Rails saat itu nyaris merupakan proof of concept sementara, dan rencananya nanti akan ditulis ulang ke bahasa lain yang tidak semudah Ruby untuk melakukan kesalahan
- Aplikasi Rails dengan cepat menambah fitur, dan rekan kerja pun menyukai hasilnya
- Fitur yang meningkatkan produktivitas bisa dibuat dengan cepat
- Situasi error yang awalnya sering terjadi dapat dicegah lewat kode
Titik buntu pada “version 2” dengan Rust dan SvelteKit
- “version 2” memilih Rust untuk backend dan SvelteKit untuk frontend
- Versi awal terlihat bagus dan berjalan cepat, tetapi hanya memiliki sekitar 10% dari fitur yang dibutuhkan
- Di Rust tidak ada framework terpadu yang sebanding dengan Rails, sehingga lebih banyak waktu dihabiskan untuk menulis kode fondasi dan koneksi dibanding logika bisnis
- Menjadi jelas bahwa untuk membuat version 2 yang lengkap, pengembangan version 1 harus dihentikan sepenuhnya, dan pada akhirnya version 2 dibatalkan
- Ini menegaskan bahwa penulisan ulang bisa memakan waktu hampir sama lamanya dengan saat pertama kali membangun aplikasi aslinya
Kompleksitas operasional akibat migrasi bertahap
- Keinginan untuk memasukkan Rust ke aplikasi tetap ada karena tipe yang kuat, performa cepat, dan rasa yakin saat kompilasi berhasil
- Meski telah memakai Ruby lebih dari 4 tahun, masalah runtime juga terus terjadi
- Utamanya masalah nilai null dan exception yang tidak tertangani
- Setelah deployment, masalah produksi diperbaiki cepat sambil melihat alat pelaporan error
- Di frontend Rails, ada ketidakpuasan karena logika dan markup tersebar di banyak file, sementara Svelte memudahkan penggabungan logika terkait dalam satu file
- Rencananya adalah menulis frontend baru dengan SvelteKit dan backend baru dengan Rust secara perlahan, menggantikan bagian Rails yang ada sedikit demi sedikit hingga akhirnya Rails dihapus
- Pada awalnya, pemindahan halaman “index” yang berisi daftar record dan filter ke stack baru berlangsung cepat
- Stack baru berjalan cepat dan bagian Rust hampir tidak memiliki masalah runtime
- Aturan deployment untuk menentukan route mana yang harus menuju Rails, Rust, atau SvelteKit menjadi rumit
- Kompleksitas ini diterima sebagai keadaan sementara sampai transisi penuh selesai
Pekerjaan teknis yang membesar melebihi nilai bagi pengguna
- Seiring waktu, fitur baru yang berguna terus ditambahkan di sisi Rails, dan fitur yang ada pun menjadi lebih dalam dan lebih canggih
- Beberapa refactoring dilakukan untuk memperbaiki asumsi awal yang keliru, dan disimpulkan bahwa skema database yang dirancang baik akan membantu versi apa pun
- UI Rails dianggap akan segera diganti, sehingga diputuskan untuk tidak lagi menghabiskan banyak waktu di sana
- Beberapa bulan kemudian, bisnis cukup berhasil sehingga pengembang penuh waktu dapat direkrut, dan transisi ke Rust diharapkan akan dipercepat
- Kenyataannya, banyak waktu di stack baru dihabiskan untuk menulis abstraksi dan mekanisme
- Akses database
- Penanganan otorisasi agar pengguna hanya melihat data yang diizinkan
- Pelacakan semua perubahan
- Pencarian dan filter
- Penegakan batasan melalui sistem tipe
- Daftar fitur yang dibutuhkan juga terus bertambah
- Pekerjaan latar belakang
- Sistem pub/sub untuk pembaruan klien
- Fitur email
- OAuth 2.0 untuk menghubungkan layanan eksternal
- SMTP dan POP
- Object storage
- Pembuatan PDF
- Library Rust sebenarnya cukup banyak, tetapi memilih library yang tepat dan menghubungkannya semua merupakan pekerjaan besar
- Makin banyak diskusi tentang detail implementasi teknis seperti pemilihan Rust ORM, waktu rilis Svelte 5, dan perbaikannya
- Setelah sekitar 1 tahun menulis dengan Rust dan Svelte, menjadi jelas bahwa pengguna hampir tidak mendapat manfaat dari pekerjaan ini
- Beberapa layar di stack baru memang mulus dan cepat, tetapi bukan di situlah masalah utama berada
- Halaman yang paling sering dipakai masih berjalan di Rails, dan memiliki fitur 10 kali lebih banyak daripada “versi beta” di stack baru
- Waktu terpakai berhari-hari atau berminggu-minggu untuk pekerjaan yang tidak menambah nilai langsung
Keputusan untuk kembali ke Rails
- Diputuskan untuk menulis ulang ke Rails hanya bagian yang sedang berjalan di stack baru
- Ini bukan menulis ulang seluruh aplikasi, melainkan mengembalikan bagian yang sudah dipindahkan ke Rust/SvelteKit kembali ke Rails
- Keputusannya sulit, tetapi masuk akal
- Sudah banyak waktu dan kode yang diinvestasikan
- Ada kemungkinan anggota tim tidak menyukai Ruby atau Rails
- Untungnya, tim memahami keputusan ini dan terbuka untuk mempelajari hal baru
- Kekuatan Rails adalah banyak fitur sudah tersedia secara bawaan, ekosistem library yang matang dan stabil, serta desain yang kuat dalam konvensi dan opini sehingga kode tetap ringkas
- Rails membantu tetap fokus membangun produk dan mengurangi beban menulis kode pendukung tingkat bawah sendiri
Pelajaran yang tersisa setelah kembali ke Rails
- Percobaan dengan Rust dan Svelte bukan sepenuhnya pemborosan
- Dengan mempelajari bahasa dan framework baru, diperoleh wawasan dan ide yang juga berguna di bahasa lain
- Menulis aplikasi web adalah rangkaian pilihan dan kompromi
- Kita harus menerima kekurangan framework atau berinvestasi untuk mengimplementasikannya sendiri, sambil mempertimbangkan apakah investasi itu memberi keunggulan kompetitif dan imbal hasil jangka panjang
- Pekerjaan untuk kembali ke Rails ternyata cukup sederhana dalam banyak hal, dan stres pun berkurang
- Dalam beberapa minggu terakhir, produktivitas kembali terasa dalam pengembangan fitur baru, peningkatan fitur lama, pembaruan UI, dan perbaikan bug
- Kekurangan Ruby dan Rails diterima sebagai kondisi yang harus diperhitungkan saat menulis kode
- Jika masalah runtime banyak, maka testing harus ditambah
- Kode spaghetti yang sulit dirawat lebih mudah diciptakan oleh pengembang daripada oleh bahasa atau framework
- Perlu lebih banyak waktu untuk refactoring dan penyusunan kode
- Jika Rails sulit diperluas, maka kemungkinan hal lain juga sulit diperluas
- Rails sudah cukup cepat, dan ada cara untuk mengakalinya dengan Turbo dan caching
- Dari sudut pandang pengguna, stack Rust tidak terasa jauh lebih cepat
- Di Rails, durasi P95 halaman yang paling berat adalah 338ms; masih ada ruang untuk peningkatan, tetapi tingkat ini sudah terasa cukup cepat
- Tidak ada bahasa atau framework yang sempurna; yang dibutuhkan adalah memahami dan menangani kekuatan serta kelemahannya
- Rails adalah salah satu framework yang sangat baik bagi orang yang ingin fokus membangun produk, dan framework lain yang telah lama bertahan serta punya banyak kontributor aktif juga bisa menjadi pilihan yang sama baiknya
2 komentar
Tulis Ulang dengan Ruby
Tulis Ulang dengan Rails
Opini Hacker News
Menurut saya Rails jauh lebih unggul daripada stack lain untuk membuat aplikasi web, bahkan dibanding Django atau Laravel
Rails sudah menangani semua bagian yang membosankan, memahami kebutuhan yang diperlukan, dan lebih jarang menghalangi saat membuat aplikasi nyata. Selama 15 tahun mengembangkan aplikasi web, saya pernah memakai Meteor, Remix, Next.js, Node.js berbasis Express, dan lainnya, tetapi saya merasa pengembangan web pada dasarnya sudah menjadi masalah yang cukup terpecahkan. Di sisi JavaScript, karena dorongan pendanaan perusahaan besar, para developer lebih seperti sedang memainkan mainan baru; sementara Rust atau Go bagus untuk pengembangan sistem dan infrastruktur deployment, tetapi memaksakannya ke pengembangan web terasa tidak masuk akal
Mudah diintegrasikan dengan banyak sekali library Java, dan sebagai bahasa bertipe statis, ia membantu dalam berbagai situasi. Data binding berbasis konvensi lewat Jackson saja sudah sangat bagus sejak lama, sedangkan pada bahasa bertipe dinamis bagian seperti ini terasa kuat sebagai sesuatu yang ditambahkan belakangan
Namun setelah masuk cukup dalam ke Rails, Django, atau Laravel, lalu harus melakukan sesuatu di luar konvensi, hal itu bisa menjadi rumit. Karena kita tidak menulis sendiri kode perekatnya, sering kali yang muncul bukan hambatan teknis melainkan celah pemahaman. Meski begitu, jika benar-benar mempelajari bagian dalamnya, hanya dengan membaca kode saja kita bisa menghemat waktu coding yang luar biasa banyak. Tentu saja pada praktiknya kita tidak melakukan itu, dan karena menulis ulang semuanya terlalu menyenangkan, kita jadi menikmati mencoba hal baru meskipun secara bisnis tidak masuk akal
Jangan hanya percaya pendapat saya, lihat datanya: https://www.youtube.com/watch?v=Qp9SOOtgmS4
Jika memakai Rails untuk layanan yang jumlah pengguna atau request per detiknya belum jelas, Anda mungkin menghemat biaya saat peluncuran, tetapi bisa mengeluarkan lebih banyak biaya server
Demo Rails tidak terasa begitu menarik selain menunjukkan betapa pentingnya keberuntungan dalam adopsi dan perhatian. Sampai sekarang saya masih kurang melihat nilainya, dan akan memilih Spring atau ASP.NET. Para pendiri startup berbasis Tcl itu kemudian membuat OutSystems, salah satu dari sedikit tool RAD yang sukses dalam pengembangan web skala enterprise, sekaligus salah satu kisah sukses industri IT Portugal
Dulu saya lebih menyukai Rails, tetapi dengan pertumbuhan besar Python selama lebih dari 10 tahun terakhir, Django menjadi pilihan yang lebih praktis. Developer machine learning dan data science sudah terbiasa dengan Python, dan dokumentasi Django sangat bagus sehingga bila perlu mereka bisa produktif dalam waktu yang sangat singkat. Saya melihatnya sendiri di beberapa proyek
Django juga mengurangi keputusan dan perdebatan soal struktur aplikasi dibanding library atau microframework yang kurang opinionated. Komunitas Django/FLOSS juga jauh lebih aktif daripada dugaan saya, dan interaksinya menyenangkan. Namun saya berharap ada generator seperti Rails serta fitur seeding data bawaan, misalnya
rake db:seedSaya sudah memakai Rails selama 17 tahun, masih menyukainya, dan juga lebih memilihnya untuk frontend
Rails memberi semua opsi untuk memisahkan kode tanpa membuat bagian atas file menjadi daftar
includesyang panjang tanpa perlu seperti yang terlihat pada aplikasi Angular. Saya tidak melihat kekurangan dalam memisahkan logic dan markup di frontend. Logic bisa diuji secara independen, dan biasanya saat mencari bug kita bisa tahu apakah masalahnya ada di markup atau logic, sehingga lebih mudah dilacak. Saya juga cukup sering menulis method Ruby lebih dari 200 baris, tetapi itu benar-benar salah saya sendiri, dan bisa dicegah jika ada sistem unit test yang lebih granularincludesyang panjang adalah menjadikan semuanya globalSaya tidak yakin apakah itu sebuah keunggulan. Import memang bisa memakan banyak ruang, tetapi ia secara eksplisit menunjukkan bagaimana semuanya terhubung. Jika mengganggu, tinggal lipat saja di IDE
Saya suka tulisan ini karena realistis. Kalimat intinya layak selalu disimpan di samping tempat tidur
“Menariknya, hal-hal yang dulu membuat saya kesal pada Ruby dan Rails kini jauh lebih tidak mengganggu. Saya sudah menerima bahwa tidak ada bahasa atau framework yang sempurna. Kita hanya perlu mengetahui kekuatan dan kelemahannya lalu mengelolanya”
Dalam banyak kasus mereka belum cukup memahami framework itu, dan tidak tahu mengapa bentuknya seperti itu. Namun mengetahui batasannya dan bekerja bersama framework jauh lebih efisien. Kita perlu meluangkan waktu untuk benar-benar memahami tool yang kita pakai
“Selama itu saya mulai membuat ‘versi 2’ dari aplikasi. Saya memilih Rust sebagai bahasa backend dan SvelteKit untuk frontend.”
Karena v1 dimulai dengan Rails, tulisan ini terbaca sebagai peringatan agar berhati-hati saat meninggalkan framework yang sudah bekerja dengan baik
Rust adalah bahasa yang dibuat oleh orang-orang yang sangat cerdas, tetapi fokusnya tampak lebih pada teori tipe dan menghemat beberapa alokasi daripada membantu developer lapangan seperti saya membuat sesuatu yang berguna dan konsisten
Saya sudah memakai Rust sejak 2020, tetapi saat membaca artikel blog Rust, secara harfiah separuhnya tidak saya pahami
Terutama jika dibandingkan dengan bahasa arus utama yang besar. Misalnya, trait mencakup use case abstract class dan concept di C++, serta abstract class dan protocol di Python. Tidak ada juga inkonsistensi antara memakai exception atau mengembalikan nilai untuk menangani error. Ada panic, tetapi digunakan seperti assertion. Jika
if-elseadalah expression, tidak perlu operator ternary terpisahBelakangan ada tren memakai Rust untuk segala hal, tetapi bahasa ini tidak dibuat untuk aplikasi CRUD. Tulisan ini pada akhirnya lebih mirip studi kasus bahwa “pakailah alat yang sesuai untuk pekerjaan. Bahasa favoritmu di waktu luang atau bahasa yang sedang tren belum tentu cocok”
Jika Anda bisa menanggung garbage collector, tidak perlu memakai Rust atau C++ dan mengkhawatirkan manajemen memori. Ada juga orang yang mempromosikan Rust sebagai bahasa pemrograman serbaguna, dan secara teori itu benar, tetapi C++ pada era 90-an juga dipromosikan begitu. Meminimalkan alokasi memori biasanya justru sifat yang diinginkan saat memilih Rust atau C++
Sulit menulis aplikasi web besar dengan cepat memakai Rust
Aplikasi besar yang ditulis dengan Rails bisa saja tidak berjalan cepat, penuh bug, atau sulit dipelihara dan diskalakan. Pilihan seperti Java, C#, dan Go mungkin tidak terlihat seksi atau keren, tetapi bisa menyelesaikan pekerjaan secepat Rails sambil berjalan dengan kecepatan yang mendekati Rust. Biasanya bug juga lebih sedikit, dan proyeknya lebih mudah dipelihara serta diskalakan
Sebenci apa pun Anda pada Rails, ini mirip mengatakan bahwa Anda bisa membuat blog lebih cepat dengan C++ daripada dengan WordPress
Jika dibuat dengan cermat, tidak harus begitu. Saya sudah melihat banyak aplikasi Rails yang besar, nyaris tanpa bug, stabil, dan mudah diubah, dan saya juga pernah melihat aplikasi Rails maupun Go yang berantakan. Bahasa atau framework tertentu bisa membuat orang lebih mudah jatuh ke kondisi seperti itu, tetapi apa pun punya kemungkinan, dan ada trade-off yang menjadi sulit karena alasan lain. Dengan disiplin, apa pun bisa dibuat bekerja
Untuk developer dengan kemampuan serupa, Rails lebih cepat dikembangkan daripada Java, C#, atau Go untuk sebagian besar fitur aplikasi web. Dari pengalaman saya, bahkan bisa sampai 3 kali lebih cepat. Saya pernah menangani monolith besar maupun arsitektur berorientasi layanan, dan juga pernah bekerja dengan tim Java. Pada suatu masa, dengan keyakinan yang sama, saya bahkan memperkenalkan Go ke organisasi Rails
Pada akhirnya masalah sebenarnya adalah MVC tidak cocok untuk semua hal dan namespace tidak digunakan dengan cukup ketat. Jika masalah itu diperbaiki di area kecil yang terarah, Rails sudah cukup baik
Jadi, dengan manajemen yang memadai, arsitektur yang baik, dan pemeliharaan, saya rasa Rails juga bisa
Belakangan saya mulai menguji AdonisJS sebagai alternatif Rails berbasis TypeScript
Jika tertarik pada “Rails dalam TypeScript”, saya menyarankan untuk mencobanya. Rasanya jauh lebih dekat ke Rails atau Laravel dibanding stack TypeScript paling populer, dan pendekatannya batteries included, alih-alih membuat Anda memilih sendiri setiap bagian stack atau mempercayai template pihak ketiga
Belakangan saya tertarik pada framework backend batteries included seperti Rails, Laravel, dan Django, tetapi sepanjang karier saya hampir selalu memakai TypeScript, jadi lebih mudah meneruskannya daripada berganti sekarang. Saya penasaran dengan kesan Anda setelah mencobanya, dan apakah Anda bisa membandingkannya dengan framework lain yang disebutkan
Untuk proyek pribadi belakangan ini saya memilih NestJS, tetapi tak lama kemudian tahu tentang Adonis, dan sekarang benar-benar mempertimbangkan untuk pindah
Teknologi seperti Next.js dan SvelteKit populer di kalangan developer JavaScript karena membantu mengurangi masalah buruknya pengalaman pengembangan backend di Node.js
Membuat backend dengan TypeScript terasa mirip seperti membuatnya dengan C#, tetapi tanpa sebagian keunggulan bahasa yang dirancang dengan baik. Pengalamannya sangat berbeda dari membuat backend dengan Rails. Developer Node.js juga mulai menyadari bahwa masalahnya bukan hanya ekosistem dan tooling, melainkan pentingnya framework yang menyediakan solusi menyeluruh untuk membuat aplikasi. Di situlah Next.js dan SvelteKit membantu, dan itu pula yang diinnovasikan Rails pada 2006
Apakah bisa menjalankan kode di backend lalu dibandingkan dengan Rails? Di mana dukungan untuk akses database, migration, ORM, queue, scheduled job, validation, translation, authentication, dan authorization? Satu-satunya hal yang dibantu Next.js adalah mendorong orang masuk ke platform Vercel
Untuk frontend, saya lebih memilih TypeScript daripada JavaScript
Komentar-komentar yang bilang Rust kurang cocok untuk backend web agak membingungkan
Dari pengalaman saya yang terutama membuat layanan kecil seperti beampaint.com atau probablyup.net, justru kebalikannya. Kalau membuat aplikasi yang lebih besar, kompleksitasnya mungkin—dan kemungkinan besar memang—akan naik tajam, tetapi untuk memberi rasa percaya diri yang dibutuhkan dalam codebase besar, Rust sangat bagus
Framework yang sudah lama biasanya menyediakan hal-hal seperti itu secara bawaan, tetapi framework Rust kecil kemungkinannya demikian karena usianya. Bayangkan saja fitur yang belum ada bertambah dari dua menjadi enam
Tulisan ini hampir seperti kisah hidup saya
Setelah memakai Rails, pada 2013 saya meluncurkan aplikasi SaaS yang ditulis dengan Go, dan harus mencari tahu semuanya sendiri. Migrasi, lapisan database, asset pipeline, deployment, validasi, logging, pembayaran, dan banyak hal lain yang Rails sediakan begitu saja
Saya tidak menyukai Go, tetapi dalam hal ini yang patut disalahkan bukan Go. Menggunakan Go untuk aplikasi CRUD sejak awal adalah keputusan yang buruk sekali
Django juga terasa serupa
Masalah performa jauh lebih sering muncul karena query database daripada karena Django itu sendiri
Optimasi mudah yang sering terlupakan antara lain membuat indeks database, menyerahkan lebih banyak logika ke database daripada ke kode, misalnya menggunakan pipeline MongoDB atau indeks parsial Postgres, mengaktifkan kompresi Brotli/zstd untuk sebagian besar request, melakukan caching objek atau request dengan cache memori seperti Redis, serta mengatur header cache control yang tepat. Di frontend, optimasi seperti tidak merender ribuan objek sebagai node DOM dan memakai canvas juga diperlukan. Baru-baru ini saya melihat masalah seperti ini di aplikasi peta