PPL 2020 — Document Builder: Menulis Kode yang Rapi

Firman Hadi
pepeel
Published in
5 min readMar 9, 2020

Akui saja, kita semua pernah menulis kode yang ‘berantakan’. Kembalilah ke masa-masa Anda belajar programming, dan Anda pasti akan menemukan kode yang sulit Anda mengerti sekarang. Tidak perlu malu karena itu adalah salah satu dari proses pembelajaran.

Clean Code

Clean code, atau kode yang ‘bersih’ sebenarnya adalah suatu konsep yang subjektif. Siapa yang bisa menilai suatu kode itu rapi, enak dibaca atau tidak? Apakah kode yang bagus itu menggunakan tab untuk indentasi? atau space? Pada dasarnya, sebuah clean code bisa dikatakan sebagai kode yang mudah dipahami dan mudah diubah. Untuk mencapai ‘mudah dipahami’ dan ‘mudah diubah’, tentu kita harus melakukan berbagai macam strategi dalam menulis kode tersebut.

Terdapat beberapa prinsip yang cukup universal yang bisa diterapkan untuk mencapai clean code, diantaranya:

  • KISS: Keep It Simple Stupid. Artinya adalah kode yang harus kita buat harus sesimpel mungkin agar mudah dipahami oleh orang lain.
  • DRY: Don’t Repeat Yourself. Artinya adalah hindari melakukan hal yang sama berkali-kali. Hal tersebut bisa menyulitkan kita apabila ‘hal yang sama’ tersebut ingin kita ubah. Pelanggaran prinsip ini biasa disebut dengan WET: We Enjoy Typing, Write Everything Twice, Waste Everyone’s Time.
  • YAGNI: You Aren’t Gonna Need It. Artinya adalah kita tidak perlu membuat fungsionalitas yang kita pikir akan dibutuhkan di masa depan, karena lebih baik fungsionalitas tersebut diimplementasikan di saat kita membutuhkannya saja. Belum tentu fungsionalitas tersebut akan digunakan juga.
  • Composition over inheritance: Artinya adalah lebih memprioritaskan composition daripada inheritance pada OOP. Dengan hal tersebut, kita lebih fokus kepada behavior sebuah class (composition) dibandingkan definisi dari class tersebut (inheritance).
  • Favor readability: Artinya adalah prioritaskan readability sebuah kode, karena kode kita tidak hanya dibaca oleh mesin, tapi juga manusia.
  • Practice consistency: Artinya apabila Anda menulis kode dengan cara tertentu, tetaplah konsisten dengan cara tersebut.

Studi Kasus: Script .gitlab-ci.yml di Document Builder

Misalkan Anda diminta untuk membuat script untuk Gitlab CI yang bisa melakukan deployment untuk dua buah environment yaitu production (lewat branch master), dan staging (melalui branch staging). Alur deployment yang dilakukan sama, yaitu:

  1. Analisis kode (test, lint, static code analysis lewat SonarQube).
  2. Build docker image aplikasi (sesuai environment).
  3. Akses SSH ke server target, dan lakukan database migration pada environment target.
  4. Akses SSH ke server target, dan jalankan image aplikasi yang baru.

Untuk mengetahui konteks lebih lanjut, perlu diketahui juga bahwa 1 job GitLab CI hanya bisa dispesifikasikan untuk satu environment saja (tidak menerima bisa parameter yang bisa membedakan environment). Pertama, solusi yang bisa dilakukan adalah sebagai berikut:

Wow… Banyak sekali duplikasi di script tersebut. Sebuah contoh yang baik untuk pelanggaran prinsip DRY (yang kemudian menjadi WET). Apakah kita bisa melakukan lebih baik dari ini? Apabila alur deployment dan script di atas diteliti lebih lanjut, maka terdapat observasi seperti berikut:

  1. Tahap analisis kode sudah rapi dan bisa dipakai kedua environment.
  2. Tahap build docker image sama untuk kedua environment, hanya berbeda pada --build-arg ENV=_env_ di baris terakhir script.
  3. Tahap migration dan deploy (3 dan 4) sama-sama menggunakan akses SSH.

Berdasarkan observasi tersebut, tentu kita akan berpikir: Apakah kita bisa melakukan ekstraksi atribut dan menjadikannya seperti inheritance di OOP? Bisa! Kita bisa menggunakan atribut extends untuk menandakan bahwa suatu object melakukan extend terhadap suatu object lain layaknya inheritance di OOP. Untuk lebih jelasnya, Anda bisa membaca penjelasan extends di dokumentasi GitLab CI.

Sebagai contoh, kita akan melakukan refactoring pada tahap build docker image. Hasil refactor-nya adalah sebagai berikut:

Lihat bagaimana sekarang job image-build-staging dan image-build-production merupakan extension dari .image-build yang berisi tahapan untuk melakukan build image. Sekarang, image-build-staging dan image-build-production hanya perlu membuat variabel yang diperlukan oleh .image-build dan tidak perlu peduli tentang implementasi dari .image-build itu sendiri.

Selanjutnya, dari observasi ketiga kita tentu dapat memanfaatkan hal yang sama untuk proses mengakses SSH server:

Bisa dilihat juga sekarang untuk masing-masing migration-env dan deploy-env melakukan extend ke .sshrun. Masing-masing job hanya perlu menambahkan variabel yang diperlukan untuk menjalankan job-nya.

Apa yang Telah Kita Lakukan?

Kita telah berhasil melakukan refactoring pada script GitLab CI milik Document Builder. Sekarang, apabila ada perubahan dalam melakukan build image maupun mengakses SSH, maka kita cukup mengubah 1 bagian saja. Selain DRY, prinsip-prinsip yang telah kita terapkan dengan melakukan refactoring seperti di atas adalah sebagai berikut:

  • Composition over inheritance: Ini mungkin tidak terlalu terlihat karena kita menggunakan extend yang bisa dibilang inheritance. Tetapi, sebenarnya kita bisa dikatakan tidak melakukan inheritance karena setiap job yang melakukan extend tidak melakukan override, melainkan mirip dengan memanggil sebuah method (yaitu parent object) dengan parameter tertentu (variabel yang didefinisikan).
  • Favor readability: Tentu saja, karena sekarang tidak ada duplicate code, dan setiap code yang melakukan extend tidak melakukan hal yang banyak.
  • Practice consistency: Cara kita melakukan extend dan hanya membuat variabel (tidak ada override atribut) bisa dikatakan sebagai praktek yang konsisten.
  • KISS: Karena hasil script sekarang menjadi lebih simpel.

Aku Akan Menerapkan Clean Code Dimanapun!

Eits, tunggu dulu. Apakah clean code selalu harus diterapkan? Tidak semua best practice harus diterapkan, dan harus dipertimbangkan juga drawback-nya. Sebagai contoh, apabila kita ‘terlalu’ menerapkan DRY, maka dalam beberapa kasus sebenarnya kode tersebut akan sulit diubah. Artikel ini membahas tentang pengalaman si penulis dalam menerapkan clean code tanpa komunikasi, dan berakhir dalam kodenya yang ‘clean code’ di-revert. Coding lah dengan sopan :)

Kesimpulan

Kita telah membahas tentang prinsip-prinsip yang cukup universal dalam menerapkan clean code, dan sudah menunjukkannya dalam studi kasus kecil pada script GitLab CI pada Document Builder. Walaupun terlihat baik, terdapat beberapa kasus dimana clean code tidak diperlukan. Ingat, sesuatu yang berlebihan itu tidak baik.

--

--