Sebelum ngoding, ada baiknya kalian perhatikan bagaimana cara mengelola baris kode kalian dengan baik.

Seperti pernyataan Uncle Bob berikut ini:

You are reading this “article” for two reasons. First, you are a programmer. Second, you want to be a better programmer. — Robert C. Martin

Untuk lebih memahami apa yang Uncle Bob katakan, bayangkan kita sedang berada di dalam sebuah perpustakaan, dan kita sedang mencari buku. Jika perpustakaan menyortir dan mengkategorikan buku — buku mereka dengan baik, kita akan menemukan buku yang kita cari dengan lebih cepat.

Menulis kode sama halnya seperti menulis buku, jika kalian ingin membuat sebuah aplikasi yang bagus, kalian harus tahu bagaimana caranya menulis kode yang bersih dan rapi. Jika ada tim atau seseorang yang mendapat “limpahan” kodingan kalian, mereka cukup melihat nama variabel atau packages atau nama classes-nya saja dan mereka langsung paham. Sehingga mereka tidak perlu menulis ulang kodingan kalian dari awal.

Apa itu “Clean Code”?

Seperti yang kalian lihat, belum cukup bagus jika kalian menyelesaikan kodingan “fitur” secara cepat jika orang lain tidak paham/mengerti apa yang kalian tuliskan di kodingan tersebut. Karena hal itu akan membuat issue atau tech-debt di kemudian hari. Kodingan kalian mempunyai definisi “Clean atau Bersih” jika kodingan kalian bisa dimengerti langsung oleh setiap orang di dalam tim.

Kenapa “Saya” harus peduli dengan hal itu?

Alasan kenapa kalian harus peduli adalah kodingan kalian bisa mendeskripsikan bagaimana cara kalian berpikir. Itulah kenapa kalian harus mulai membuat kodingan kalian yang lebih bersih, simple dan mudah dibaca.

Karakteristik kodingan yang bersih

Seperti kutipan dari Uncle Bob berikut ini:

One difference between a smart programmer and a professional programmer is that the professional understands that clarity is king. Professionals use their powers for good and write code that others can understand. — Robert C. Martin

— Baris kode yang elegan

Baris kode kalian seharusnya membuatmu tersenyum seperti halnya seorang musisi yang membuat komposisi lagu, kemudian mendengar sendiri lagunya.

— Baris kode yang telah diurus

Maksudnya adalah, kalian sudah meluangkan waktu untuk membuat kodingan kalian agar tetap simple dan teratur. Berarti, kalian sudah memberikan perhatian yang tepat pada detail kodingan kalian dan orang lain tidak perlu lagi me-“refactor” kodingan kalian.

— Baris kode kalian harus punya tujuan

Setiap fungsi, setiap class, setiap module yang kalian buat, harus merepresentasikan tujuan yang jelas dan tidak tercampur oleh hal/tujuan lain.

— Baris kode kalian tidak berulang

— Ada unit test

— Meminimalisir semua entitas, seperti fungsi, classes, methods, dan yang sejenis.

Maksudnya adalah saat kalian mulai menulis baris kode, kalian harus memperhatikan apakah entitas, fungsi — fungsi, class atau method sudah pernah dibuat atau belum. Sehingga meminimalisir penulisan kode yang berulang. Bagi yang belum mengerti apa itu entitas, fungsi, method dan class.

Entitas: Entitas adalah suatu object yang merepresentasikan data.

Fungsi: Fungsi adalah sebutan untuk suatu fungsi yang mengembalikan nilai.

Method: Method adalah kumpulan beberapa Fungsi yang berada didalam Class.

Class: Class adalah sebuah blueprint atau gambaran umum dari sebuah Object.

Membuat nama yang berarti

Memilih nama yang bagus memang membutuhkan waktu yang tidak sedikit, tapi bisa menolong kita di kemudian hari. Nama dari sebuah variabel, fungsi, atau class, seharusnya bisa menjawab pertanyaan tentang permasalahan kalian. Hal tersebut seharusnya bisa memberitahu kita kenapa variabel, fungsi, atau class itu dibuat, apa dan bagaimana cara kerjanya. Kita ambil contoh:

— Penamaan Class

Classes atau Objects seharusnya berupa kata benda atau frase kata benda. Seperti, Customer, WikiPage, Account, dan AddressParser. Hindari menggunakan kata — kata Manager, Processor, Data, atau Info dalam penamaan sebuah class. Nama class seharusnya bukan sebuah kata kerja.

— Penamaan Metode (Methods)

Metode seharusnya memiliki kata kerja atau frase kata kerja, seperti postPayment, deleteAccount, atau saveAccount. Aksesor (Accessors), merubah nilai (mutators), dan Predikat (Predicates) harus dinamakan berdasarkan nilai atau prefix seperti get, set dan is. Sesuai dengan JavaBean standard.

— Gunakan problem domain

Saat dimana tidak ada lagi nama yang “programmer banget” tentang apa yang sedang kalian lakukan, gunakanlah nama sesuai dengan domain masalah yang ingin kalian pecahkan. Setidaknya, programmer lain yang akan me-maintain kodingan kalian bisa bertanya kepada product owner atau domain expert-nya tentang hal ini.

Menulis kode menggunakan prinsip S.O.L.I.D

Prinsip ini juga dibawakan oleh Robert C. Martin (Uncle Bob), SOLID adalah istilah yang menjelaskan kumpulan prinsip desain untuk kode yang baik.

Single Responsibility Principle (SRP)

Artinya setiap class harus memiliki satu tujuan. Sebuah class tidak boleh memiliki lebih dari satu alasan untuk diubah. Hanya karena kalian ingin menambahkan semuanya yang kalian inginkan, bukan artinya kalian harus menambahkannya. Pilah class yang besar menjadi kecil — kecil. Dan hindari God Classes. Kita ambil contoh:

Kodingan diatas membuat sebuah class RecyclerView.Adapter tidak memiliki satu tujuan yang jelas. Karena class tersebut memiliki logika bisnis (if…else…) di dalamdidalam fungsi onBindViewHolder. Class ini seharusnya hanya bertujuan untuk mengatur data ke sebuah implementasi view.

Open-Closed Principle (OCP)

Entitas perangkat lunak seharusnya terbuka untuk extension tetapi tertutup untuk modification. Artinya, jika kalian membuat sebuah Class A, dan ada seseorang di tim kalian yang ingin membuat perubahan terhadap fungsi tertentu di dalam Class A, orang tersebut bisa melakukannya hanya dengan membuat sebuah class baru dengan cara melakukan extension ke Class A. tanpa harus melakukan perubahan di dalam Class A itu sendiri. Kita ambil contoh:

Kalian ingin membuat sebuah kustom adapter untuk sebuah RecyclerView. Kalian cukup melakukannya dengan cara buat class baru dan extend dari RecyclerView.Adapter, kemudian kalian bisa buat behavior khusus sesuai keinginan kalian tanpa harus mengubah behavior dari class RecyclerView.Adapter itu sendiri. Seperti yang terlihat di baris kode berikut:

Liskov Substitution Principle (LSP)

Seperti kata Uncle Bob berikut ini:

Child classes should never break the parent class type definitions.

Artinya, sebuah subclass yang meng-override metode — metode dari parent class tanpa merusak parent class-nya. Kita ambil contoh:

Kalian membuat sebuah interface OnClickListener dengan satu fungsi yaitu onClick(). Dan kalian implementasi interface tersebut ke beberapa class (MyActivity A dan MyActivity B).

  • Pada MyActivity A, implementasi onClick() hanya memunculkan pesan toast saja,
  • Sedangkan, di MyActivity B implementasi onClick() yang membuka halaman Login.

Implementasi onClick di MyActivity B tidak akan merusak implementasi di MyActivity A dan tidak merubah nilai apapun dari interface-nya. Lihat baris kode berikut:

Interface Segregation Principle (ISP)

Maksud dari prinsip ini adalah tidak ada subclass yang dipaksa untuk meng-implementasi fungsi — fungsi yang tidak digunakan. Maksudnya adalah, jika kalian ingin membuat Class B dan melakukan extension dari Class A, kalian tidak seharusnya meng-override semua methods yang ada di dalam Class A ke dalam Class B. Kita ambil contoh:

Di dalam activity kalian, kalian ingin implementasi sebuah class SearchView.OnQueryTextListener() dan hanya membutuhkan satu method onQueryTextSubmit() saja.

Bagaimana caranya agar kita hanya implementasi satu method saja tanpa harus implementasi method yang tidak dibutuhkan?

Jawabannya adalah dengan membuat satu interface baru dan buat sebuah implementasi default dari interface tersebut.

Dan seperti ini cara implementasinya sekarang:

Dependency Inversion Principle (DIP)

Seperti kata Uncle Bob berikut:

Depend on Abstractions. Do not depend on concretions.

Definisi dari Uncle Bob tentang Dependency Inversion Principle terdiri dari dua hal:

  • Modul high-level tidak seharusnya bergantung dengan module low-level. Tetapi mereka bisa bergantung pada abstraksi.
  • Abstraksi tidak bergantung pada detail, begitu juga sebaliknya

Modul High-level yang memberikan logika yang complex, seharusnya bisa dengan mudah digunakan kembali dan tidak terpengaruh oleh perubahan di modul low-level yang menyediakan fitur utilitas. Untuk mencapai hal tersebut, kalian harus membuat abstraksi yang memisahkan masing — masing modul high-level dan modul low-level.

Contoh yang paling mudah adalah MVP Pattern. Kalian punya sebuah interface yang bisa membantu komunikasi antara UI Classes (Activity/Fragment) dan Presenter Classes. UI Classes tidak perlu tahu implementasi metode — metode di dalam Presenter. Begitu juga sebaliknya, jika kalian melakukan perubahan di dalam Presenter Classes, UI Classes tidak akan peduli apa perubahan yang kalian lakukan.

Lihat baris kode berikut:

Sekarang, kita lihat implementasinya di UI Classes:

Jadi, yang kita butuhkan adalah membuat sebuah interface yang menjadi abstraksi dari implementasi antara Presenter dan UI (View).

Kesimpulan

Para programmer tahu kalau kadang — kadang mereka menulis baris kode yang hanya mereka sendiri yang tahu maksud dan tujuannya. Mulai sekarang, kalian harus mulai berpikir tentang bagaimana cara menulis kode dengan perspektif tentang membuat kode yang mudah dimengerti dan mudah diubah kedepannya.

Saya mengerti jika kalian telah membuat aplikasi atau baris kode dengan penamaan yang asal, menumpuk semuanya di dalam satu class (God Classes), atau Spaghetti Code. Percayalah, saya juga pernah melakukan hal yang sama. Itulah mengapa saya ingin membagikan pengalaman saya tentang Clean Code dari Uncle Bob ini kepada kalian. Dan, saya harap kalian bisa mengerti tentang penjelasan saya.

Happy Coding Everyone :)

Baca juga jurnal teknologi lain dari kami di medium eFishery atau di eFishery Engineering Blog

Artikel ini diterbitkan pertama kali di:

https://medium.com/mindorks/understanding-clean-code-in-android-ebe42ad89a99