- Clojure bukan salah satu bahasa pemrograman arus utama, dan bagi sebagian orang mungkin terasa asing
- Keunggulan utama Clojure
- Produktivitas pengembang: Clojure bersifat interaktif, mengurangi pekerjaan berulang, dan menyediakan lingkungan pengembangan yang efisien. Pengembang bisa merilis produk dengan cepat sambil tetap merasa puas dengan proses kerjanya
- Kemudahan pemeliharaan jangka panjang: Bahasa dan ekosistem Clojure sudah matang dan stabil. Kita dapat membangun sistem berkualitas tinggi sambil menekan biaya pemeliharaan
- Budaya yang berpusat pada ide: Komunitas Clojure mengeksplorasi ide dari masa lalu dan masa kini, dari akademia maupun industri, untuk mencari cara pengembangan perangkat lunak yang lebih baik. Ini memberi pengembang tantangan baru dan peluang belajar
(hello 'clojure)
- Clojure adalah salah satu bahasa keluarga Lisp yang dibuat pada 1950-an
- Lisp bermula sebagai model teoretis, tetapi juga menawarkan keanggunan konseptual yang tinggi dalam pemrograman nyata
- Karena sintaks kodenya sekaligus selaras dengan struktur data, Lisp memiliki berbagai keunggulan dibanding bahasa dengan tata bahasa yang rumit
- Pernah digunakan sebagai bahasa utama pada masa ledakan AI sebelumnya
- Bahasa keluarga Lisp sempat berkala naik daun lalu meredup, tetapi dalam 10 tahun terakhir Clojure kembali mendapat perhatian
- Clojure berjalan di atas JVM milik Java dan mencerminkan konsep-konsep pemrograman modern
- Dukungan kuat untuk struktur data immutable
- Dirancang dengan mempertimbangkan konkurensi
- Meski komunitasnya kecil dan tumbuh tanpa dukungan perusahaan besar, Clojure memiliki karakteristik bahasa yang kuat
- Clojure dapat dijalankan di berbagai lingkungan
- ClojureScript: dikompilasi menjadi JavaScript untuk dijalankan
- ClojureCLR: berjalan di lingkungan .NET
- Babashka: interpreter skrip cepat yang memanfaatkan GraalVM
- Jank: mendukung kompilasi native
- Dengan mempelajari Clojure, kita bisa memanfaatkan pengetahuan yang sama di berbagai lingkungan
Gaya pengembangan interaktif
- Pemrograman adalah proses berulang antara menulis kode dan memverifikasinya
- Tanpa umpan balik, sulit yakin apakah kode berjalan dengan benar
- Bentuk umpan balik yang umum:
- Menjalankan skrip berulang kali
- Interaksi UI dan output log
- Pemanfaatan unit test
- Penggunaan compiler dan alat analisis statis
- Kecepatan umpan balik sangat memengaruhi produktivitas pengembang
- Semakin lambat umpan balik, semakin banyak waktu habis untuk debugging dan semakin sedikit waktu untuk menulis kode
- Selain cara umpan balik konvensional, Clojure juga menyediakan pendekatan interactive development
- Pengembangan berbasis REPL (Read-Eval-Print Loop) adalah intinya
- Sebelum menulis kode, pengembang menjalankan runtime Clojure lalu menghubungkannya ke editor
- Potongan kode dapat dijalankan satu per satu dan langsung mendapat umpan balik
- Berkat struktur sintaks yang konsisten ala Lisp, kita bebas mengeksekusi potongan kecil hingga blok kode besar
- Berbeda dari REPL biasa, Clojure dapat mengeksekusi potongan kode saat terhubung ke sistem yang sedang berjalan
- Pendekatan ini memberi loop umpan balik yang jauh lebih kuat daripada alur tradisional “tulis kode → jalankan → debug”
- Program bisa dimodifikasi dan di-debug secara real time
- Bukan sekadar REPL sederhana, tetapi alat interaksi kuat yang bisa dipakai bahkan di lingkungan operasional
Budaya yang mengutamakan stabilitas
- Memilih Clojure bukan sekadar memperoleh teknologi yang kuat, tetapi juga menjadi bagian dari komunitas dengan filosofi dan prinsip yang unik
- Jika hanya mengadopsi teknologinya tanpa berkomunikasi dengan komunitas, sulit merasakan nilai sejati Clojure
- Komunitas Clojure menempatkan stabilitas dan kompatibilitas mundur sebagai nilai penting
- Bahasa intinya terus diperbaiki dan dikembangkan hampir tanpa perubahan yang merusak
- Ekosistem open source Clojure juga mengikuti filosofi yang sama, dengan meminimalkan perubahan yang tidak perlu (churn)
- Ini kontras dengan sebagian besar ekosistem bahasa pemrograman modern lainnya
- Pemborosan sumber daya akibat perubahan yang tidak perlu bernilai miliaran dolar secara global
- Di Clojure, melakukan upgrade ke versi terbaru bahasa dan library terasa sangat alami
- Kita bisa menikmati perbaikan bug, pembaruan keamanan, dan peningkatan performa tanpa perlu menulis ulang codebase
- Kode lama yang bisa rusak saat versi baru keluar di bahasa lain, di Clojure biasanya tetap bertahan apa adanya
- Sebagian pengembang mungkin bertanya, “bagaimana bisa berkembang tanpa perubahan?”
- Namun stabilitas berbeda dengan stagnasi
- Clojure berkembang dengan cara menambah dan meningkatkan fitur baru tanpa merusak yang lama
- Pengembang dapat terus memakai alat yang lebih baik tanpa perlu melakukan revisi kode yang tidak perlu
Sistem informasi dan representasi pengetahuan
- Dalam pengembangan aplikasi web dan bisnis, mengumpulkan, mengakses, dan memproses informasi adalah inti
- Namun bahasa pemrograman arus utama sering menunjukkan desain yang tidak efisien dalam hal representasi dan manipulasi informasi
- Mereka memaksa penggunaan struktur data level rendah, yang menimbulkan kompleksitas yang tidak perlu
- Sistem tipe statis sering terlalu kaku, sehingga manipulasi data yang fleksibel menjadi sulit
- Clojure secara bawaan menyediakan struktur data fungsional dan kemampuan manipulasi data yang kuat
- Sebagai bahasa bertipe dinamis, Clojure mengikuti "Open World Assumption"
- Pendekatan ini memaksimalkan skalabilitas dan fleksibilitas data
- Juga sangat dipengaruhi oleh RDF (framework pemodelan data untuk Semantic Web)
- Contoh yang menonjol adalah sinerginya dengan database graf seperti Datomic
- Dengan memanfaatkan keyword yang menyertakan namespace, kita bisa memberi makna yang independen dari konteks
- Struktur Map Clojure dengan keyword bernamespace memungkinkan ekspresi makna yang lebih kaya dibanding JSON biasa
- Perluasan data tambahan menjadi mudah, dan representasi data tetap intuitif sambil menghindari tabrakan nama
Fungsi kecil yang dapat dikombinasikan dan data immutable
- Di Clojure, pendekatan umum adalah memrogram dengan berfokus pada pure function dan data immutable
- Memang kita bisa menulis kode imperatif ala Java, Ruby, atau C, tetapi kode Clojure yang idiomatis sangat berbeda
- Pure function: mengembalikan hasil hanya berdasarkan nilai input dan tidak mengubah state eksternal
- Data immutable: memiliki makna berbasis nilai (value), bukan referensi (reference) atau identitas objek (identity)
- Karena tidak dipengaruhi state eksternal, perilaku kode menjadi lebih mudah diprediksi
- Tidak ada modifikasi variabel global atau efek samping yang tak terduga
- Karena data tidak berisiko berubah, pemrosesan paralel dan penyelesaian masalah konkurensi menjadi lebih mudah
Penanganan konkurensi
- Komputasi modern berjalan di atas prosesor multicore, sehingga konkurensi menjadi elemen yang penting
- Saat Hukum Moore mendekati batasnya, memanfaatkan paralelisme menjadi kunci peningkatan performa
- Namun saat menangani mutable state, kita harus berhadapan dengan masalah sinkronisasi dan kontrol timing yang kompleks
- Clojure menekankan immutability untuk menyelesaikan masalah konkurensi dari akarnya
- Memanipulasi memori yang dapat berubah menimbulkan ketergantungan pada urutan dan timing
- Transformasi data murni (data-in, data-out) selalu aman dijalankan secara paralel
- Clojure memanfaatkan fitur konkurensi bawaan JVM (
java.util.concurrent), sambil menyediakan alat abstraksi tingkat lebih tinggi
- Atoms: mendukung operasi atomik dengan CAS (Compare-and-Set) dan retry otomatis
- Refs: menyediakan Software Transactional Memory (STM)
- Agents: menerapkan pembaruan secara asinkron
- Futures: menyediakan antarmuka fork-and-join berbasis thread pool
- Menyediakan library core.async
- Mendukung pola CSP (Communicating Sequential Processes) yang mirip goroutine di Go
- Dapat dibandingkan dengan model Actor di Erlang/Elixir atau Akka di Scala
- Tanpa memakai abstraksi tingkat tinggi Clojure sekalipun, kita tetap bisa memakai teknik kontrol konkurensi level lebih rendah
- Mendukung synchronized queue, atomic reference, lock, semaphore, berbagai thread pool, hingga manajemen thread manual
- Jika dibutuhkan, kontrol konkurensi yang rinci juga memungkinkan, tetapi dalam banyak kasus memakai alat yang lebih terabstraksi jauh lebih aman dan efisien
Penalaran lokal (Local Reasoning)
- Ada batas pada kompleksitas kode yang bisa kita pikirkan sekaligus
- Jika state program dan perubahannya terjadi di banyak tempat, memahami dan memelihara kode akan menjadi sulit
- Alasan Clojure memudahkan penalaran lokal
- Kode yang berpusat pada pure function
- Perilaku fungsi dapat dipahami sepenuhnya hanya dari inputnya
- Tidak perlu mempertimbangkan state di luar fungsi
- Perbedaan dengan bahasa berorientasi objek
- Clojure meminimalkan polymorphism sehingga lebih mudah melacak di mana kode dijalankan
- Dalam pemrograman berorientasi objek (OOP), “segala sesuatu terjadi di tempat lain”,
sedangkan di Clojure kita cukup menelusuri fungsi yang didefinisikan di namespace
- Berkat struktur sintaks yang konsisten di Clojure, refactoring kode menjadi mudah
- Karena memakai data immutable dan pure function, perubahan kode cenderung minim efek samping yang tak terduga
- Dengan memisahkan sedikit kode imperatif seperlunya, kode imperatif dan kode fungsional dapat disusun secara harmonis
Pengujian yang mudah
- Pada kode Clojure yang berbasis pure function, pengujian bisa dilakukan hanya dengan memberikan input dan memeriksa output
- Tidak perlu inisialisasi state yang rumit, pengaturan objek mock, atau kontrol timing untuk pengujian
- Karena itu reliabilitas test menjadi tinggi dan "flakiness" (kegagalan test yang tidak konsisten) berkurang
- Mendukung teknik pengujian lanjutan Property Based Testing (Generative Testing)
- Menghasilkan input acak untuk mencari kasus yang melanggar sifat atau invarian tertentu
- Mendukung teknik shrinking untuk menemukan contoh kegagalan yang paling minimal
- Konsep ini berasal dari Haskell dan diimplementasikan di berbagai bahasa melalui framework pengujian berbasis QuickCheck
- Di Clojure, pendekatan ini menjadi lebih efektif berkat sinergi antara struktur data immutable dan gaya pengembangan berbasis REPL
Keuntungan merekrut pengembang Clojure
- Secara umum, jumlah pengembang Clojure memang lebih sedikit dibanding bahasa populer seperti JavaScript atau Python
- Namun karena pengembang Clojure sedikit, perusahaan yang memakai Clojure juga tidak banyak
- Karena itu keseimbangan suplai dan permintaan secara keseluruhan tetap terjaga
- Dalam praktiknya, perusahaan yang mencari pengembang Clojure dan para pengembang tersebut sering kali dapat saling bertemu dengan cukup baik
- Pengembang Clojure sering memiliki kemampuan pemecahan masalah yang tinggi
- Alih-alih sekadar mempelajari teknologi yang sedang populer, banyak dari mereka tertarik mengeksplorasi cara berpikir dan ide baru
- Perusahaan yang menggunakan Clojure menilai bahwa meski jumlah pelamar lebih sedikit, kualitasnya sering tinggi
- Contoh: Nubank di Brasil berhasil melatih ratusan pengembang langsung dalam Clojure
- Mencari pengembang Clojure memang tidak mudah, tetapi jika menemukan kandidat yang tepat, peluang mendapatkan pengembang hebat menjadi tinggi
- Daripada hanya mencari orang yang sudah punya pengalaman bahasa tersebut, melatih pengembang dengan kemampuan belajar tinggi juga bisa menjadi pilihan baik
- Komunitas Clojure sendiri cenderung menarik pengembang yang suka memikirkan masalah secara mendalam dan menyelesaikannya
Trade-off dan pengaturan tingkat abstraksi
- Clojure adalah bahasa high-level yang mengarah pada penulisan kode yang ringkas dan ekspresif
- Berkat struktur data fungsional (immutable) dan API manipulasi data yang kuat, kompleksitas yang tidak perlu dapat dikurangi
- Struktur data Clojure secara internal menggunakan struktur pohon (Hash Array Mapped Trie) untuk menjamin immutability
- Saat update terjadi path copying, sehingga beban GC (garbage collection) bisa meningkat
- Dalam proses interop dengan Java, runtime reflection serta boxing/unboxing juga bisa terjadi
- Pada aplikasi umum, biaya ini hampir bisa diabaikan, sementara peningkatan produktivitas pengembang sangat besar
- Untuk kasus yang membutuhkan performa tinggi seperti mesin grafis real-time, pemrosesan sinyal, atau komputasi numerik, optimisasi level rendah tetap memungkinkan
- Clojure menyediakan type hint untuk menghilangkan reflection dan mengoptimalkan operasi tipe primitif
- Pemakaian array tipe primitif yang berurutan memungkinkan pemanfaatan cache CPU
- Library akselerasi GPU juga bisa dimanfaatkan
- Sebagian besar bahasa high-level harus memakai ekstensi native seperti C/Rust saat performa menjadi kritis,
tetapi Clojure dapat memanfaatkan optimisasi JVM (kompilasi JIT) untuk menyelesaikan sebagian besar masalah performa
- Dengan profiling dan sedikit optimisasi, performa event loop dan komponen lain dapat dimaksimalkan
Metaprogramming dan API berbasis data
- Sebagai bahasa keluarga Lisp, Clojure dapat memperlakukan kode sebagai data
- Mirip JSON, tetapi dapat merepresentasikan program dalam struktur yang lebih mudah dibaca
- Menggunakan format data bernama EDN (Extensible Data Notation) untuk menyediakan representasi data yang mirip JSON
- Clojure menyediakan kemampuan mengubah kode itu sendiri dengan macro
- Namun komunitas Clojure memiliki budaya membatasi penggunaan macro secara hati-hati
- Macro bisa menyulitkan debugging dan kurang cocok dengan alat analisis statis
- Sebagai gantinya, pendekatan desain API data-driven lebih disukai
- Contoh: routing HTTP, pembuatan HTML/CSS, validasi data, dan lain-lain
- Alih-alih langsung memanggil fungsi tertentu, perilaku ditentukan melalui struktur data (map, vector)
- API berbasis data dapat dimanipulasi secara dinamis, dan konfigurasi pengguna mudah disimpan serta diubah
- Berkat API berbasis data, sistem dapat dikonfigurasi ulang secara dinamis saat runtime
- Ini memudahkan implementasi sistem simulasi yang sangat fleksibel, pengelolaan konfigurasi dinamis, dan metaprogramming
Interop Java dan pemanfaatan ekosistem
- Pengembangan aplikasi modern adalah proses menggabungkan banyak library open source dan API
- Karena Clojure berjalan di JVM, jutaan paket Java di Maven Central dapat dimanfaatkan
- Library Java dapat dipanggil dengan mudah tanpa reflection
- Dibanding Java, Clojure memiliki kode yang jauh lebih ringkas dan memudahkan pemrograman eksperimental berbasis REPL
- API dapat dieksplorasi dan digabungkan jauh lebih cepat daripada di Java
- Dengan ClojureScript, pendekatan yang sama juga bisa dipakai untuk JavaScript dan ekosistem NPM
Budaya yang berpusat pada ide
- Proyek yang sukses bisa dibuat dengan bahasa apa pun, dan sebaliknya bahasa apa pun bisa gagal jika dipakai dengan cara yang salah
- Alat yang baik tidak otomatis membuat pengembang menjadi baik
- Clojure memiliki kurva masuk yang cukup tinggi, dan proses belajarnya memerlukan trial and error, tetapi justru membuka ruang untuk berpikir lebih dalam
- Beberapa proyek Clojure masih membawa gaya penulisan kode ala Java atau Python sehingga tidak memanfaatkan Clojure dengan baik
- Namun tim yang menerima filosofi dan ide Clojure akan memiliki kemampuan desain perangkat lunak yang lebih baik
- Komunitas Clojure terus mempertanyakan cara pengembangan yang ada dan mengeksplorasi pendekatan yang lebih baik
- Ceramah Rich Hickey (pencipta Clojure) bukan sekadar pengenalan teknologi, tetapi eksplorasi prinsip desain perangkat lunak yang mendasar
- Di konferensi Clojure, yang menjadi pusat bukan pengenalan library, melainkan ide, pembahasan makalah, dan berbagi pengalaman
Kesimpulan
- Clojure bukan sekadar bahasa pemrograman, tetapi komunitas orang-orang yang memikirkan cara pengembangan perangkat lunak yang lebih baik
- Di komunitas ini, memperluas batas diri dan mengeksplorasi kemungkinan baru adalah nilai inti
- Pengembang yang tumbuh dalam budaya seperti ini bukan hanya mahir memakai Clojure, tetapi juga menjadi software engineer dengan kemampuan pemecahan masalah yang lebih baik
3 komentar
Secara pribadi saya menggunakan Clojure, dan saya sangat banyak setuju dengan isi artikel tersebut.
Untuk pekerjaan, saya selama ini terutama menggunakan Python dan Java(Type)Script, tetapi kalau pengelolaannya sedikit saja terabaikan, bahasa itu sendiri dan perubahan pada library-librarynya sering kali membuat kode cepat menjadi legacy code. Yang sangat memuaskan dari Clojure adalah kemudahan untuk langsung melakukan modifikasi dan pengembangan bahkan ketika melihat kembali kode yang pernah ditulis setahun kemudian.
Sejak itu, untuk penggunaan pribadi, kecuali jika ada keterbatasan dari library tertentu, saya jadi sering mengandalkan Clojure.
Jank Jank~!
Komentar Hacker News
Jika ditanya jenis pemrograman apa yang paling dinikmati, jawabannya adalah membangun pipeline pemrosesan data di shell, dan menulis Clojure serta ClojureScript selama 5 tahun terakhir
Sudah menggunakan Clojure selama 12 tahun, dan sebelumnya menggunakan Java selama lebih dari 12 tahun
Sangat suka menulis Clojure, dan menyadari bahwa tidak perlu menjelaskan rasa suka yang mendalam terhadap Clojure dengan membandingkannya dengan bahasa lain
Salah satu co-founder menargetkan membuat produk semaksimal mungkin dengan perusahaan seminimal mungkin
Menjalankan bisnis SaaS selama 10 tahun dengan Clojure, dan itu mungkin tidak akan bisa dilakukan tanpa Clojure
Merekomendasikan <a href="https://www.flow-storm.org/">Flow Storm</a> kepada orang-orang yang memakai Clojure
Belajar banyak dari Rich Hickey, dan pernah memiliki antusiasme terhadap Clojure dan FP
Ada catatan bahwa dokumentasi di ClojureDocs sudah usang, dan ada keinginan untuk menambahkan fitur voting pada jawaban
Bagian tentang stabilitas Clojure terasa mengejutkan, karena setiap kali mencoba tiap tahun, rasanya semuanya berubah
Mulai dari Common Lisp lalu berpindah ke Go dan Rust, tetapi belakangan kembali melihat Clojure
Jika ditanya jenis pemrograman apa yang paling dinikmati, jawabannya adalah membangun pipeline pemrosesan data di shell, dan menulis Clojure serta ClojureScript selama 5 tahun terakhir
Sudah menggunakan Clojure selama 12 tahun, dan sebelumnya menggunakan Java selama lebih dari 12 tahun
Sangat suka menulis Clojure, dan menyadari bahwa tidak perlu menjelaskan rasa suka yang mendalam terhadap Clojure dengan membandingkannya dengan bahasa lain
Salah satu co-founder menargetkan membuat produk semaksimal mungkin dengan perusahaan seminimal mungkin
Menjalankan bisnis SaaS selama 10 tahun dengan Clojure, dan itu mungkin tidak akan bisa dilakukan tanpa Clojure
Merekomendasikan <a href="https://www.flow-storm.org/">Flow Storm</a> kepada orang-orang yang memakai Clojure
Belajar banyak dari Rich Hickey, dan pernah memiliki antusiasme terhadap Clojure dan FP
Ada catatan bahwa dokumentasi di ClojureDocs sudah usang, dan ada keinginan untuk menambahkan fitur voting pada jawaban
Bagian tentang stabilitas Clojure terasa mengejutkan, karena setiap kali mencoba tiap tahun, rasanya semuanya berubah
Mulai dari Common Lisp lalu berpindah ke Go dan Rust, tetapi belakangan kembali melihat Clojure