Mengenal ESLint Plugin Functional
Rule 1: Immutability
Functional Programming
Functional Programming (FP) beberapa tahun belakangan ini sering menjadi topik perbincangan dan diskusi di kalangan developer Javascript. FP yang berdasar pada Lambda Calculus sebenarnya bukan merupakan paradigma baru, bahkan bahasa pemrograman berbasis FP pertama (LISP) sudah lahir dan digunakan sejak tahun 1960. FP sendiri bersifat deklaratif dan bertitik tumpu pada penyusunan block code dengan pure function, menekankan immutability serta menghindari shared state dan side effects.
Artikel ini berfokus pada penggunaan eslint-plugin-functional untuk implementasi salah satu aspek dari FP yaitu immutability. Javascript menyediakan beberapa API yang melakukan mutasi baik pada array dan object. Plugin ini mempermudah implementasi FP pada codebase project tanpa harus khawatir melakukan mutasi secara tidak sengaja.
Global vs local variable mutation
Melakukan mutasi data tidak selalu merupakan hal buruk, namun mutasi pada variable global dapat menyebabkan bug yang cukup sulit untuk dilacak dan akan semakin sulit seiring dengan perkembangan codebase project. Berikut contoh kasus untuk memudahkan dalam memahami bug seperti apa yang dimaksud.
Perusahaan A tiap tahun melakukan renumerasi terhadap salary employee. Renumerasi ini merupakan hasil total performance bonus dan salary adjustment tahunan yang didapat employee. Kedua adjusment ini berdasarkan pada base salary employee pada tahun tersebut. Seorang employee bisa saja tidak mendapat salah satu adjustment ataupun keduanya. Perhitungan masing-masing adjustment tadi pun bisa berubah dan tidak saling dependen satu sama lain, sehingga kedua perhitungan ini pun dipisahkan menjadi dua fitur yang berbeda namun masih menggunakan sumber basic salary yang sama.
Saat ini besar salary adjusment adalah 50% dari base salary sedangkan performance bonus sebesar 10% dari base salary. Apabila seorang employee mendapatkan yearly adjustment dan performance bonus maka salary yang didapat pada saat renumerasi diberlakukan adalah sebesar 160% dari base salary sebelumnya.
Bambang merupakan seorang employee perusahaan A dengan basic salary 100 juta dan ia cukup beruntung tahun ini memperoleh kedua adjustment sehingga ekspektasi salary selanjutnya adalah sebesar 160 juta.
Pada perhitungan yearly adjustment terdapat sedikit kesalahan dimana terjadi shallow copy yang tanpa sengaja menghasilkan mutasi terhadap salary dari data asli, padahal developer berasumsi mutasi hanya akan berlaku pada variable newData saja. Hal ini mengakibatkan jumlah total renumerasi (newSalary = 165 juta) lebih besar dari nilai yang seharusnya (160 juta).
Bayangkan apabila di kemudian hari semakin banyak perhitungan lain yang dilakukan terhadap data employee dan masing-masing perhitungan berada pada tempat yang berbeda, maka cukup sulit untuk melakukan tracking terhadap sumber mutasi. Salah satu cara sederhana untuk mengatasi hal tersebut adalah dengan membatasi mutasi hanya pada variable local saja dengan lebih dulu melakukan deep copy menggunakan spread operator ataupun Object.assign sehingga mutasi hanya terjadi pada local variable hasil copy saja.
Pada FP, immutability merupakan salah satu aspek penting untuk diimplementasikan. Bagaimana cara melakukan enforcing immutability pada codebase yang bahasa pemrogramannya sendiri mendukung mutability?
eslint-plugin-functional to the rescue!
ESLint sendiri pada dasarnya merupakan salah satu tools yang populer digunakan untuk melakukan enforcing terhadap gaya penulisan kode. ESLint memiliki banyak plugins untuk berbagai peruntukan yang dapat kita konfigurasi dengan memilih rules mana yang akan digunakan berdasarkan list rules yang disediakan masing-masing plugin. Pada saat artikel ini ditulis eslint-plugin-functional memiliki 16 rules untuk mendukung implementasi FP pada Javascript dan Typescript. Berikut langkah-langkah untuk menggunakan plugin ini dengan asumsi codebase project belum diinisiasi.
Pertama-tama lakukan inisiasi project
yarn init -y# ataunpm init -y
Install eslint dan eslint-plugin-functional
yarn add -D eslint eslint-plugin-functional# ataunpm install -D eslint eslint-plugin-functional
Buat atau edit file .eslintrc.json
{
"plugins":[
"functional"
],
"rules":{
"functional/immutable-data":"warn"
},
"parserOptions":{
"ecmaVersion":11,
"sourceType":"module"
},
"env":{
"es6":true
}
}
Konfigurasi di atas mengaktifkan rule “immutable-data” yang digunakan untuk melarang adanya mutasi data, apabila mutasi data dilakukan maka akan diberikan warning menunjuk pada line dimana mutasi terjadi. Kita bisa mengganti level error dengan mengubah value “warn” menjadi “error”.
Untuk menjalankan eslint, modifikasi attibutes script pada package.json seperti berikut
{
"scripts":{
"start":"eslint . && node index.js"
}
}
atau kita bisa memisahkan eksekusi eslint pada command tersendiri
{
"scripts":{
"lint":"eslint .",
"start":"node index.js"
}
}
Kita bisa mencoba apakah eslint bekerja dengan baik dengan menggunakan salah satu mutable API yang disediakan javascript yaitu method .sort().
Buat atau edit index.js seperti berikut
Apabila kode dijalankan maka eslint akan mengeluarkan warning dikarenakan .sort() melakukan mutate pada originalArr.
Untuk memastikan warn ataupun error hilang ketika mutate originalArr tidak lagi dilakukan maka coba ubah code menjadi sebagai berikut.
Untuk mencoba plugin ini tanpa install gunakan replit berikut
Sekian pengenalan ESLint Plugin Functional (immutable-data), feedback dan saran sangat dinantikan, semoga bermanfaat!