01 — Situasinya
Satu aplikasi, lima layanan, dua sisi pengguna.
Klien kami ingin satu aplikasi yang menampung banyak layanan sekaligus: antar orang, sewa mobil, kirim barang, sampai dompet untuk membayarnya. Bukan lima aplikasi terpisah — satu, dengan satu akun dan satu saldo.
Yang membuatnya berat bukan jumlah layanannya, tapi karena setiap layanan punya dua sisi yang harus ketemu: penumpang yang memesan dan pengemudi yang menerima. Keduanya bergerak, keduanya buru-buru, dan keduanya memakai ponsel di jalan.
02 — Masalahnya
Dua hal yang tidak bisa dibeli jadi.
Sebagian besar kebutuhan sistem seperti ini sudah ada versi siap pakainya. Dua hal tidak.
Mencari pengemudi terdekat. Terdengar sederhana sampai jumlah pengemudinya ribuan dan tersebar. Memeriksa jarak satu per satu setiap kali ada pesanan itu tidak mungkin — pesanan datang tiap detik, dan pengemudinya terus berpindah.
Menghitung tarif di rute melingkar. Rutenya tidak lurus A ke B. Kendaraan berputar melewati beberapa titik, dan penumpang bisa naik di titik mana pun lalu turun di titik mana pun — termasuk yang membuatnya memutar hampir satu lingkaran penuh. Tarif tiap ruas berbeda, dan totalnya harus benar dari arah mana pun orang naik.
Dua masalah ini tidak ada contekannya. Kami turunkan sendiri dari nol.
03 — Yang kami lakukan
Menurunkan dua algoritma dari penalaran, bukan dari contoh.
Empat keputusan yang menentukan.
- 01
Saring kasar dulu, baru hitung teliti
Untuk mencari pengemudi terdekat, kami tidak menghitung jarak semua pengemudi. Petanya dipotong lebih dulu jadi kotak di sekitar penumpang, dan hanya pengemudi di dalam kotak itu yang jaraknya dihitung sungguhan. Menyaring dulu dengan cara murah, baru menghitung dengan cara mahal — itu yang membuatnya tetap cepat meski jumlah pengemudinya bertambah.
- 02
Jarak dihitung di atas permukaan bola, bukan di atas kertas
Jarak antara dua titik di peta bukan garis lurus biasa; bumi melengkung. Kami hitung jaraknya mengikuti lengkungan itu, supaya urutan “paling dekat” benar-benar sesuai kenyataan di jalan, bukan sekadar sesuai gambar peta.
- 03
Tarif dihitung per ruas, bukan per jarak total
Rute melingkar dipecah jadi ruas-ruas kecil antar titik. Tarif sebuah perjalanan adalah jumlah ruas yang benar-benar dilewati, dihitung searah putaran. Dengan begitu naik di titik terakhir dan turun di titik pertama tetap dihitung benar — bukan dianggap jarak pendek padahal memutar hampir penuh.
- 04
Dompetnya dibuat bisa diperiksa, bukan sekadar bisa berkurang
Isi ulang, penarikan, bonus, dan pembayaran semuanya dicatat sebagai riwayat yang tidak bisa diubah — bukan sekadar angka saldo yang naik-turun. Saat ada selisih, yang dicari bukan “kenapa saldonya salah” tapi “transaksi mana yang tidak cocok”. Itu perbedaan antara masalah yang bisa ditelusuri dan masalah yang cuma bisa ditebak.
04 — Hasilnya
Rilis ke publik, lalu tumbuh selama tiga tahun.
Aplikasinya rilis di kedua toko aplikasi dan dipakai penumpang sungguhan. Layanannya bertambah bertahap, dan sistemnya berkembang jadi beberapa bagian terpisah supaya tiap layanan bisa dikembangkan tanpa mengganggu yang lain.
Tim yang mengerjakannya tumbuh dari empat orang jadi belasan. Kami tetap ikut menulis kodenya sambil membagi pekerjaan — bukan berpindah jadi pengawas yang hanya membaca laporan.
05 — Yang membuatnya bertahan
Dua algoritma itu masih kami pakai sampai sekarang.
Cara mencari yang terdekat dan cara menghitung tarif per ruas ternyata bukan hanya soal kendaraan. Pola yang sama muncul lagi di sistem lain yang kami kerjakan bertahun-tahun sesudahnya — mencari yang paling dekat dari sekumpulan titik, dan menjumlahkan biaya yang berbeda-beda per bagian.
Kami menurunkannya dari penalaran, bukan menyalin dari contoh. Konsekuensinya kami paham betul kenapa tiap bagiannya ada, jadi saat kebutuhannya berubah kami tahu bagian mana yang boleh diubah dan bagian mana yang akan merusak hitungannya.
