3 Sprint of Clean Codes in ConnectDot
Pada kesempatan ini, saya akan ceritakan bagaimana pengembangan aplikasi ConnectDot masih terus berpegang teguh pada prinsip Clean Code. Saya pun akan go through poin-poin penting pada Clean Code.
General Rules of Clean Code
Follow standard conventions
Aplikasi kami terbagi menjadi dua bagian, yaitu frontend dengan Next.js React Typescript dan backend dengan Django-REST Python. Kami pun mengikuti konvensi standar dalam bahasa program masing-masing dan juga konvensi framework terkait.
Pada frontend kami mengikuti konvensi frontend untuk memisahkan urusan UI rendering dan urusan state management. Sehingga, untuk UI rendering kami gunakan library react dan state management kami gunakan library redux. Untuk menggabungkan keduanya, kami gunakan library react-redux.
Untuk backend, kami turuti konvensi REST API. Semua software engineer seharusnya paham apa itu REST API. Hal ini akan memudahkan pengembang frontend dalam berkomunikasi dengan backend karena pola-pola API pada REST API selalu begitu-begitu saja. Hal ini juga memudahkan apabila ada pengembang backend yang baru, seharusnya orang baru dapat dengan cepat memahami code backend yang kami buat karena sudah mengikuti konvensi REST API.
Keep it simple stupid. Simpler is always better. Reduce complexity as much as possible.
Pada backend, dengan bantuan Django-REST, kami dapat membuat code backend yang sesederhana mungkin. Sebagai contoh, kami berikan cuplikan code backend yang bertugas menangani entity ‘jobs’.
Dalam kurang dari 40 baris kode, kami bisa definisikan API /jobs. Bahkan ini sudah lengkap untuk semua HTTP REST method, yaitu head, get, put, patch, post, dan delete. Selain itu kami juga dapat membatasi siapa saja yang boleh mengakses API dengan satu baris kode: ‘@authorized’.
Boy scout rule. Leave the campground cleaner than you found it.
Aturan ini dapat kami capai dengan code review yang kritis. Kami mengusahakan untuk membaca code yang dibuat oleh teman dalam tim kami line-by-line.
Always find root cause. Always look for the root cause of a problem.
Ini kami terapkan ketika kami menemukan bug pada code yang sudah merged dengan staging.
Untuk semua bug yang yang dilist pada gambar di atas, bisa saja akar permasalahannya berada pada library dependency, atau penggunaan library yang salah. Akan tetapi, ternyata akar permasalahannya adalah logic application state management kami yang kurang lengkap.
Design Rules
Keep configurable data at high levels.
Kami gunakan environment variable agar semuanya dapat diubah dari sisi deployement
Separate multi-threading code.
Multi-threading code kebanyakan ditangani oleh library.
Prevent over-configurability.
Konfigurasi enviroment variable kami tidak rumit, kami pun juga punya template enviroment variable yang singkat.
Use dependency injection.
Dengan dependency injection, unit testing menjadi sangat mudah. Ini kami terapkan di frontend dan backend.
Contoh backend:
Contoh frontend:
Follow Law of Demeter. A class should know only its direct dependencies.
Kami juga tidak mendesain class atau function yang rumit yang dapat mengetahui dependency dari dependencynya. Hal ini juga dapat dilihat pada kode yang saya lampirkan di atas.
Names rules
Choose descriptive and unambiguous names.
Make meaningful distinction.
Use pronounceable names.
Use searchable names.
Replace magic numbers with named constants.
Avoid encodings. Don’t append prefixes or type information.
Tentu kami punya konvensi penamaan untuk frontend dan backend. Kebanyakan dari konvensi penamaan pun diambil dari konvensi general pada bahasa pemrograman itu sendiri dan framework yang kami gunakan. Aturan penamaan kami paksakan konsisten pada code review.
Functions rules
Small.
Do one thing.
Use descriptive names.
Prefer fewer arguments.
Have no side effects.
Don’t use flag arguments. Split method into several independent methods that can be called from the client without the flag.
Semua function yang kami buat kami usahakan bersifat seperti ini. Namun, bagian ‘no side effects’ nya sulit karena memang beberapa funciton bertujuan untuk menghasilkan side effects. Berikut saya lampirkan contoh kode yang mengikuti prinsip di atas.
Comments rules
Always try to explain yourself in code.
Don’t be redundant.
Don’t add obvious noise.
Don’t use closing brace comments.
Don’t comment out code. Just remove.
Use as explanation of intent.
Use as clarification of code.
Use as warning of consequences.
Dari semua code yang sudah saya tampilkan pada postingan blog ini, dapat terlihat bahwa semua code sudah dibuat sejelas mungkin sehingga dapat dikatakan kami “Always try to explain yourself in code.”. Namun, memang ada beberapa bagian yang masih perlu dijelaskan seperti pada bagian API /jobs, pada code paling atas di halaman ini.
Tests
One assert per test.
Readable.
Fast.
Independent.
Repeatable.
Langung saja saya berikan contoh code backend dan frontend.
Kedua contoh tersebut memenuhi semua prinsip testing clean code. Hanya satu assert, mudah dipahami, cepat, independen, dan dapat diulang-ulang dan selalu menghasilkan hal yang sama. Dikatakan cepat karena unit test sangat pendek.
Code smells
Rigidity. The software is difficult to change. A small change causes a cascade of subsequent changes.
Fragility. The software breaks in many places due to a single change.
Immobility. You cannot reuse parts of the code in other projects because of involved risks and high effort.
Needless Complexity.
Needless Repetition.
Opacity. The code is hard to understand.
Kami menggunakan linter untuk frontend dan backend sebagai usaha pertama untuk menghindari code smells. Usaha yang paling besar dari kami untuk menghindari code smells adalah code review. Apabila sebuah merge request pada repository kami mengandung banyak diskusi, biasanya itu terjadi karena ada code-code yang masih bisa diperbaiki baunya.