Konon katanya, di luar sana banyak pengembang perangkat lunak (programmer) yang sangat menyukai bahasa pemrograman Java. Bahkan tak jarang ditemui para programmer yang tidak hanya menyukai Java, tetapi tidak mau menyentuh pemrograman lain selain Java. Katanya Java sangat memudahkan pemrograman. Java berorientasi objek. Java punya komunitas yang sangat hebat. Tapi, apakah kamu sudah kenal dengan Scala? Scala adalah sebuah bahasa pemrograman yang dikembangkan untuk menggantikan Java. Sebuah java yang lebih baik. Mari kita lihat kenapa.

Pengenalan Scala

Scala (yang adalah kepanjangan dari “Scalable Language”) merupakan sebuah bahasa pemrograman yang dirancang untuk digunakan dalam berbagai lingkungan, mulai dari script sederhana sampai dengan sebuah sistem yang besar dan rumit. Istilah kerennya, Scala adalah sebuah general purpose programming language.

Scala dikembangkan oleh Martin Odersky, yang adalah pengembang dari compiler dan fitur Generic pada bahasa pemrograman Java. Setelah lama mengembangkan dan menggunakan Java, Martin Odersky menemukan satu kelemahan fatal pada Java: jika ingin menggunakan Java pada lingkungan pemrograman konkuren, sintaks dari Java harus diubah seluruhnya. Model konkurensi yang digunakan Java (thread) dianggap sulit dimengerti dan dikodekan dengan baik.

Scala dikembangkan untuk memperbaiki model konkurensi dari Java, serta meningkatkan berbagai aspek lainnya, seperti model orientasi objek yang kurang murni, yang banyak tidak disukai oleh programmer non-Java. Selain itu, penggabungan paradigma pemrograman berorientasi objek dan fungsional juga dilakukan oleh Scala, untuk meningkatkan kemudahan pemrograman konkuren. Dengan berbagai alasan tersebut, tahun 2001 Scala dilahirkan.

Meyakinkan para programmer untuk berganti bahasa pemrograman jelas bukan hal yang mudah, terutama untuk bahasa pemrograman yang sudah sangat matang seperti Java. Ekosistem Java sangat kaya, dengan berbagai library, framework, dan komunitas yang telah terbangun dengan matang. Mengharapkan para programmer Java membuang seluruh ekosistem tersebut untuk berganti metode pemrograman (yang belum terbukti benar) tentunya bukan hal yang mudah. Untuk mengantisipasi hal tersebut, Scala dirancang untuk berjalan di atas JVM (Java Virtual Machine). Tidak cukup sampai di sana, kode yang ditulis dengan Scala dapat dipanggil dalam Java dan sebaliknya. Hal ini tentu sangat memudahkan para programmer untuk bereksperimen dengan Scala, sembari tetap tidak meninggalkan ekosistem Java.

Scala Berorientasi Objek

Scala dirancang untuk menjadi bahasa pemrograman yang murni berorientasi objek. Dalam Scala, setiap nilai adalah objek. Tidak ada lagi primitif, tidak ada lagi berbagai intrik aneh seperti kode berikut:

1.toSTring()

yang tidak dapat dijalankan, dan bahkan tidak ada lagi operator. Ketika mengetikkan 1 + 2 dalam Scala, yang terjadi pada dasarnya adalah pemanggilan fungsi sebagai berikut:

1.+(2)

di mana 1 dan 2 masing-masing adalah objek Int.

Objek dalam Scala dideskripsikan menggunakan class, dengan trait sebagai ganti dari interface pada Java. Class pada Scala dikembangkan dengan subclassing, sama seperti Java, tetapi Scala juga menggunakan konsep mixin-based composition untuk menyelesaikan permasalahan multiple inheritance.

Catatan: Detil dari konsep orientasi objek dari Scala, serta perbedaannya dengan Java akan dibahas pada tulisan-tulisan berikutnya. Tulisan ini hanya bersifat pengenalan akan Scala, sehingga penulis tidak akan masuk ke dalam ranah teknis terlalu dalam untuk menjaga panjang tulisan.

Scala (juga) adalah Bahasa Fungsional

Selain berorientasi objek, Scala juga adalah bahasa pemrograman fungsional. Pemrograman fungsional memang belum populer dalam lingkungan pengembangan sistem industri, tetapi model pemrograman ini telah terbukti sangat handal dan praktis. Bertahun-tahun, pemrograman fungsional dianak tirikan oleh komunitas programmer, walaupun sangat populer di kalangan akademis. Berbagai alasan dikemukakan, mulai dari kesulitan pemahaman sampai dengan model pemrograman yang tidak praktis. Scala (dan beberapa bahasa fungsional generasi baru seperti F#) telah relatif sukses membawa pemrograman fungsional ke lingkungan mainstream pemrograman.

Konsep pemrograman fungsional sendiri sebenarnya sederhana: “fungsi adalah nilai” dan “fungsi adalah operasi pemetaan antara masukan dan keluaran”. Konsep pertama, yaitu “fungsi adalah nilai” berarti status dari sebuah fungsi dalam bahasa pemrograman fungsional dapat dikatakan sama dengan sebuah integer atau double. Jika kita dapat melakukan hal seperti ini pada sebuah integer dalam bahasa pemrograman non-fungsional (ilustrasi dalam bahasa C):

// Memasukkan sebuah nilai integer ke dalam variabel
int angka = 10;

// menggunakan nilai integer sebagai parameter fungsi
deretFibonacci(angka);

// mengembalikan nilai integer dari sebuah fungsi
int deretFibonacci(int n) {
     // ....
}

maka sebuah fungsi dalam bahasa pemrograman fungsional mendapatkan perlakukan serupa. Ya, kita dapat memasukkan fungsi ke dalam sebuah variabel, menggunakan fungsi sebagai parameter fungsi lainnya, dan menjadkan fungsi sebagai nilai kembalian dari sebuah fungsi.

// memasukkan fungsi ke dalam variabel
var func = (param1: Int, param2: Int) => param1 + param2
func(1, 2) // hasil: 3

// menggunakan fungsi sebagai parameter fungsi
def median(data: List[Int], sortFunction: (List[Int]) => List[Int]) = {
    // ...
}
val datas = List(100, 24, 50)
def quicksort(data: List[Int]): List[Int] = {
    // ...
}
val med = median(datas, quicksort) // mengembalikan nilai median dari datas

Dapat dilihat pada kode Scala di atas bagaimana fungsi median menerima dua buah parameter, data (yang bertipe List dari Int) dan sortFunction (yang bertipe sebuah fungsi yang menerima List[Int] dan menghasilkan List[Int] juga). Fungsi quicksort kemudian diberikan kepada fungsi median sebagai parameter yang melakukan pengurutan nilai. Pengunaan fungsi seperti ini berguna terutama jika programmer ingin menggunakan fungsi urut yang berbeda-beda, sesuai dengan keadaan.

Konsep yang kedua, yaitu “fungsi adalah operasi pemetaan antara masukan dan keluaran” merupakan sebuah konsep yang mengharuskan sebuah fungsi hanya melakukan operasi kepada nilai-nilai yang ada di dalam fungsi itu sendiri. Nilai-nilai yang berada di luar fungsi tidak boleh diproses oleh sebuah fungsi. Singkatnya, sebuah fungsi hanya boleh menerima masukan, kemudian memberikan keluaran. Perhatikan kode C berikut:

int hp = 9999;
void reduceHP(int value) {
    hp -= value;
}
reduceHP(1000);

Operasi pada fungsi di atas (reduceHP) melakukan proses terhadap nilai yang berada di luar dirinya, yaitu hp. Fungsi jenis ini dikenal juga sebagai fungsi yang memiliki side effect. Side effect tidak diperbolehkan dalam pemrograman fungsional. Kode yang lebih baik menurut konsep fungsional adalah sebagai berikut:

int hp = 9999;
int reduceHP(int currentHP, int damage) {
    return currentHP - damage;
}
hp = reduceHP(hp, 1000);

Meskipun kode di atas belum sepenuhnya fungsional, namun cukup untuk dijadikan ilustrasi. Tulisan-tulisan berikutnya akan membahas mengenai pemrograman fungsional dalam Scala secara lebih mendalam.

Kenapa Scala?

Sifat-sifat Scala umunya sudah kita ketahui. Pemrograman berorientasi objek dan fungsional sangat jelas keuntungannya buat kita. Tapi apa sih aspek yang paling menarik dari Scala yang membuat kamu harus menggunakan Scala, dan bukan Java (atau C++ atau C#)?

Kompatibel

Seperti yang sudah dijelaskan di awal, Scala berjalan di atas JVM dan dapat berbagi kode dengan Java. Dengan begitu, kita dapat menambahkan Scala ke dalam kode yang sudah ada. Berpindah ke Scala tidak berarti kita harus membuang pengetahuan kita tentang Java, framework, library, dan segala hal lain yang ada dalam ekosistem Java. Bahkan, terdapat versi Scala yang berjalan pada lingkungan .Net (walaupun implementasi untuk ini belum matang).

Scala literally stands on the shoulders of giants.

Contoh lain dari kompatibilitas Scala ialah pengunaan tipe-tipe data Java dalam Scala. Class Int dalam Scala merupakan pembungkus dari primitif int dalam Java. Begitu juga class Float, dan berbagai class lain yang juga adalah tipe primitif dalam java. Array dalam Scala dipetakan ke array dalam Java. Hal yang sama dilakukan terhadap String, Exception, dan lainnya. You get the idea.

Bahkan lebih hebatnya lagi, menggunakan berbagai teknik yang ada dalam bahasanya, Scala tidak hanya menggunakan ulang berbagai hal yang ada dalam Java, tapi juga memperbaiki dan menambahkan berbagai fitur dalam class Java yang digunakannya. String misalnya, alih-alih menuliskan

Integer.parseInt(str)

untuk mengubah sebuah String menjadi integer, dalam Scala kita dapat langsung menuliskan

str.toInt

padahal String yang digunakan adalah class String yang sama! Hal ini dimungkinkan oleh salah satu fitur Scala, yaitu implicit conversion, yang tidak akan dibahas pada tulisan ini. Tetapi detil dari implicit conversion dapat dibaca pada link yang diberikan.

Scala Sederhana

Program yang ditulis dengan Scala selalu singkat, padat, dan jelas. Tidak perlu dijelaskan panjang lebar, berikut adalah contoh sebuah class sederhana menggunakan Java:

class MyClass {
    private int id;
    private String name;

    public MyClass(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

yang jika dituliskan dalam Scala akan menjadi:

class MyClass(id: Int, name: String)

dan dapat dipastikan, kedua kode tersebut memiliki fungsionalitas yang sama (constructor, dua buah field, dst). Kemudahan penulisan kode seperti ini sangat umum dijumpai dalam berbagai tempat di Scala, dari library utilitas sampai web framework. Karena kesederhanaan dan berbagai kemudahan ini lah Scala menjadikan pemrograman kembali fun. Dapat mengakses seluruh ekosistem Java juga sangat membantu tentunya.

Scala sangat High-level

Kompleksitas merupakan hal yang tidak dapat dihindari dalam pengembangan perangkat lunak. Sebuah sistem memiliki banyak komponen bergerak dan variabel-variabel yang sulit diprediksi. Meskipun banyak para ahli seringkali menyarankan untuk menghindari kompleksitas sepenuhnya, seringkali hal tersebut tidak dapat dilakukan. Kompleksitas tetap ada, dan harus ditaklukkan.

Scala menyediakan banyak fasilitas untuk mengontrol kompleksitas, baik melalui abstraksi maupun model pemrograman. Pembeda utama ialah pemrograman fungsional. Mari kita lihat sebuah contoh kasus.

Kamu diminta untuk menuliskan sebuah fungsi yang menentukan apakah terdapat huruf kapital dalam sebuah String. Berikut adalah kode yang biasanya dituliskan dengan metode pemrograman konvensional (imparative):

public boolean hasUpperCase(String src) {
    boolean result = false;
    for(int i = 0; i < src.length(); i++) {
        if(Character.isUpperCase(src.charAt(i))) {
             result = true;
             break;
        }
    }
    return result;
}

Sementara dalam Scala, fungsi tersebut dapat dituliskan sebagai berikut:

def hasUpperCase(src: String): boolean = src.exists(_.isUpper)

Dapat dilihat bagaimana Scala jauh lebih tinggi tingkat abstraksinya daripada Java. Ketika Java menganggap String sebagai sebuah nilai yang harus diiterasikan karakter demi karakter, Scala menganggap String sebagai entitas yang dapat di-query. Hasilnya? Kesederhanaan dan penurunan kemungkinan kesalahan. Semakin sedikit kode yang ditulis, tentunya semakin kecil kemungkinan sebuah bug ditemukan di dalam kode tersebut.

Catatan: Karakter “_” yang digunakan dalam kode Scala di atas memiliki arti khusus, yaitu karakter wildcard. Lagi-lagi, detil tidak akan dibahas pada tulisan ini.

Kesimpulan

Kita telah melihat sifat-sifat Scala dan kelebihan dari Scala. Tentu saja hanya menggunakan Scala tidak membuat kita menjadi programmer yang lebih baik. Tetapi menggunakan Scala memberikan kita alat untuk menjadi programmer yang lebih baik. Pengunaan sebuah alat dengan baik dan benar tentunya memerlukan latihan dan pengetahuan yang baik mengenai alat tersebut. Blog ini akan mencoba untuk terus menerus berbagi pengetahuan tersebut.

Permasalahan utama yang akan dihadapi ketika mempelajari Scala adalah paradigma pemrograman fungsional. Pemrograman fungsional sangat, sangat berbeda dengan pemrograman konvensional. Tetapi mempelajari pemrograman fungsional akan sangat membantu dalam meningkatkan kualitas kode, baik dari sisi penulisan maupun perancangan. Mempelajari cara berpikir baru jarang sekali akan merugikan kita. Kembali, blog ini akan mencoba memberikan bantuan dalam hal tersebut, sedikit demi sedikit (hal ini jugalah yang menyebabkan banyak konsep diperkenalkan, tetapi tidak dijelaskan secara rinci - agar pembaca tidak tenggelam dalam banyak konsep baru).

Bacaan Lanjutan

  1. A Tour of Scala
  2. Functional Programming for The Rest of Us
comments powered by Disqus

Daftar Isi