“Code smell” (bau kode) adalah istilah informal yang digunakan oleh programmer untuk menggambarkan pola desain perangkat lunak yang umum ditemukan pada kode yang buruk. Bau kode paling baik dipahami bukan sebagai bug atau cacat pada dirinya sendiri, tetapi sebagai tanda peringatan kualitas kode yang buruk.
Istilah “bau kode” diciptakan oleh Kent Beck dan dipopulerkan dalam buku penting tahun 1999 yang ia tulis bersama Martin Fowler, Refactoring: Improvement the Design of Existing Code, khususnya dalam babak berjudul “Bad Smells in Code.” Fowler sendiri secara ringkas mengartikulasikan bau kode sebagai “indikasi permukaan yang biasanya terkait dengan masalah yang lebih dalam pada sistem.”1
Tidak seperti bug perangkat lunak sejati, bau kode tidak mencegah kode sumber untuk mengompilasi, menjalankan, dan melakukan fungsi yang diinginkan, juga kehadirannya tidak selalu menunjukkan masalah aktual. Bayangkan memasuki rumah dan mencium sesuatu yang aneh atau berjamur. Bau itu mungkin berasal dari makanan kedaluwarsa di lemari es Anda atau sampah yang perlu dibawa keluar; lebih serius, itu bisa dari jamur atau sesuatu yang membusuk di dalam dinding Anda, tetapi bisa juga dari keju yang kuat yang sangat aman untuk dimakan. Apa pun, baunya membutuhkan pemeriksaan lebih lanjut.
Untuk seorang insinyur perangkat lunak yang berpengalaman, pola tertentu dalam kode tidak “berbau” benar. Seiring waktu, seseorang mungkin secara naluriah mengasosiasikannya dengan komplikasi tertentu, inefisiensi, atau masalah di masa depan. Menamai dan mempopulerkan bau kode tertentu memfasilitasi keakraban dengan pola-pola kontraproduktif ini (atau “anti-pola”) dan prinsip-prinsip desain yang dilanggarnya. Keakraban itu pada akhirnya membuat anti-pola ini lebih mungkin dikenali dan diperbaiki selama peninjauan kode. Seperti yang dikatakan Fowler, “secara definisi, bau adalah sesuatu yang mudah dikenali, atau mudah dicium.”
Jika dibiarkan tanpa penanganan, bau kode merupakan kontributor utama terhadap hutang teknis. Seperti yang ditegaskan sebuah penelitian, 75% cacat yang ditemukan dari peninjauan kode tidak mempengaruhi eksekusi program tetapi “memengaruhi kemampuan perangkat lunak untuk dikembangkan”. 2 Bahkan jika anti-pola atau kebiasaan buruk tertentu tidak menyebabkan bug hari ini, itu secara signifikan meningkatkan risiko bug, crash, atau kerentanan keamanan di basis kode Anda muncul nantinya. Setidaknya, keberadaan bau kode yang sudah diketahui dapat mengurangi keterbacaan dan pemeliharaan kode Anda, membuatnya lebih sulit untuk dipahami, diperbarui, dan ditingkatkan.
Tetap terinformasi tentang tren industri yang paling penting—dan menarik—tentang AI, otomatisasi, data, dan di luarnya dengan buletin Think. Lihat Pernyataan Privasi IBM®.
Meskipun banyak bau kode umum terus dikenal dengan nama-nama yang diciptakan oleh Beck dan Fowler di Refactoring, tidak ada daftar bau kode tunggal kanonik yang diterima secara universal. Tetapi apakah bau kode tertentu harus disebut dengan satu nama atau lain, atau dikategorikan sebagai anti-polanya sendiri daripada subjenis dari yang lain, sebagian besar tidak penting. Yang terpenting adalah apakah nama dan deskripsi dari “bau kode” cukup jelas dan intuitif untuk membantu tim pengembangan perangkat lunak berbagi dan menerapkan prinsip-prinsip desain yang produktif.
Demikian juga, tidak ada taksonomi yang disepakati secara universal untuk berbagai kategori bau kode. Artikel ini terutama mengacu pada taksonomi yang diusulkan oleh Jerzyk dan Madeyski pada tahun 2023.3 Temuan mereka diterbitkan dalam katalog bermanfaat yang dikelola di codesmells.org, yang menyediakan konteks tambahan, contoh kode, dan teknik pemfaktoran ulang yang sesuai untuk masing-masing.
Jerzyk dan Madeyski mencatat bahwa taksonomi bau kode yang paling umum dirujuk mengikuti lima pengelompokan yang diusulkan oleh Mäntylä dan Lassenius pada tahun 2006, yang mengategorikan 22 bau kode yang diperkenalkan oleh Fowler dan Beck (dan satu lagi dari mereka sendiri) ke dalam lima pengelompokan yang berbeda: Bloater, Object-Orientation Abuser, Change Preventer, Dispensable, dan Coupler.4 Setelah upaya mereka sendiri untuk ulasan literatur yang diterbitkan secara formal dan “materi abu-abu” (seperti blog, forum, dan wiki), Jerzyk dan Madeyski membuat katalog 56 bau kode yang berbeda ke dalam 9 pengelompokan (yang termasuk 5 yang disebutkan sebelumnya dalam paragraf ini).
Meskipun bagian ini sebagian besar mengikuti struktur 9 kategori yang mereka usulkan, penting untuk dicatat bahwa pengelompokan tersebut bersifat informal dan subyektif: taksonomi yang paling berguna adalah mana yang menurut Anda paling intuitif. Memahami berbagai jenis komplikasi atau inefisiensi yang mungkin ditimbulkan oleh bau kode dapat memberikan konsepsi bau kode yang lebih bermakna daripada menghafal masing-masing bau secara langsung. Seperti yang diartikulasikan Mäntylä, “dengan daftar panjang bau kode, mudah untuk kehilangan gambaran keseluruhan”.5
Bloater adalah bau kode yang sering mengakibatkan metode, kelas, atau blok kode tumbuh begitu besar sehingga menjadi sulit digunakan. Hal ini mengurangi keterbacaan dan membuat kode lebih sulit untuk dipelihara atau dimodifikasi.
Contoh-contoh bloater meliputi:
Gumpalan data: Kelompok variabel yang sering muncul bersama di mana-mana.
Kelas besar: Kelas yang mencoba melakukan terlalu banyak dan mengandung terlalu banyak variabel, kurang kohesi.
Fungsi panjang (metode panjang): Metode yang mengandung terlalu banyak baris kode.
Daftar parameter panjang: Fungsi yang membutuhkan terlalu banyak argumen untuk beroperasi dengan benar.
Obsesi elemen dasar: Menggunakan tipe data elemen dasar alih-alih objek kecil khusus.
Change preventer (pencegah perubahan), seperti yang tersirat dari namanya, adalah bau kode yang menghambat kemampuan untuk memodifikasi, menambah, atau mengembangkan perangkat lunak lebih lanjut. Contoh khas dari pencegah perubahan adalah struktur kode yang memaksa Anda untuk membuat serangkaian pengeditan di beberapa tempat hanya untuk menerapkan satu modifikasi sederhana.
Bau kode semacam ini melanggar prinsip tanggung jawab tunggal (SRP) Robert C. Martin, yang menegaskan bahwa perubahan pada satu modul kode seharusnya hanya dapat berasal dari satu tempat. Seperti yang disarankan Martin dalam postingan blog tentang SRP, “Kumpulkan hal-hal yang berubah untuk alasan yang sama. Pisahkan hal-hal yang berubah karena alasan yang berbeda.”6
Contoh pencegah perubahan meliputi:
Shotgun surgery (operasi bedah serampangan): Menerapkan satu perubahan membutuhkan modifikasi di banyak modul yang tersebar secara bersamaan (yang pada dasarnya kebalikan dari kelas besar).
Perubahan divergen: Seperti kebalikan dari operasi bedah serampangan, menerapkan satu perubahan membutuhkan banyak modifikasi dalam satu kelas.
Callback hell: Struktur kode di mana banyak metode saling bersarang jauh di dalam satu sama lain melalui banyak tab indentasi dan kurung kurawal, menyembunyikan sebab dan akibat serta membuat kode sulit dibaca dan dipelihara.
Coupler adalah bau kode yang melanggar prinsip desain inti coupling rendah dengan menciptakan dependensi berlebihan antara kelas yang berbeda. Ini mengurangi penggunaan kembali kode dan mempersulit (atau bahkan mencegah) pengujian unit independen.
Contoh coupler meliputi:
Kecemburuan fitur: Suatu metode mengakses data objek lain secara berlebihan.
Trading orang dalam: Satu kelas menggunakan bidang internal atau metode kelas lain.
Rantai pesan: Urutan panjang panggilan metode yang saling terkait antar objek.
Dealer data meneruskan data melalui lebih banyak kelas atau fungsi daripada yang diperlukan. Ini menciptakan dependensi dan kompleksitas yang tidak perlu, sering menghasilkan elemen kode yang hanya menyimpan atau mendistribusikan data tanpa memberikan perilaku yang berarti.
Contoh-contoh dealer data meliputi:
Perantara: Kelas yang tugasnya hanya mendelegasikan tugas kepada kelas lain.
Data tramp: Ketika data “menumpang” melalui rantai metode yang tidak memanfaatkannya.
Data global: Struktur di mana variabel dapat dimodifikasi dari mana saja di basis kode, membuat setiap fungsi dalam basis kode menjadi tersangka ketika sesuatu rusak.
Dispensable (dapat dihapus), secara intuitif, adalah elemen kode yang dapat dihilangkan: penghapusannya akan membuat basis kode lebih bersih dan lebih mudah dibaca tanpa dampak yang berarti pada fungsionalitas keseluruhan.
Contoh-contoh dispensable meliputi:
Komentar: Meskipun komentar umumnya merupakan hal yang baik, itu kadang digunakan sebagai “deodoran” untuk bau kode, menjelaskan daripada memperbaiki. Misalnya, jika komentar menjelaskan apa yang terjadi di bagian kode tertentu, itu digunakan untuk menutupi kode yang tidak intuitif atau cukup mudah dibaca dengan sendirinya. Komentar individu juga bisa menjadi berlebihan atau ketinggalan zaman dari waktu ke waktu. Perilaku komentar yang lebih spesifik muncul di bau kode lain.
Kelas data: Kelas yang hanya berisi bidang dan pengakses, tidak memiliki perilaku yang berarti.
Kode mati: Elemen kode yang tidak lagi dieksekusi karena, seiring waktu, pemfaktoran ulang dan modifikasi lainnya telah membuatnya usang.
Kode duplikat: Struktur kode yang identik atau sangat mirip di beberapa tempat.
Kelas malas (alias elemen malas): Kelas atau fungsi yang terlalu kecil untuk ada.
Generalitas spekulatif: Kode yang tidak diperlukan ditambahkan untuk mendukung fitur hipotetis masa depan.
Penyalahgunaan fungsional adalah bau kode tidak sedap yang mengabaikan prinsip-prinsip pemrograman berorientasi objek dengan memaksakan pola fungsional ke dalam basis kode berorientasi objek.
Contoh penyalahagunaan fungsional meliputi:
Loops: Menggunakan loop tradisional alih-alih operasi pipa modern. Meskipun Fowler menganggap hampir semua loop sudah ketinggalan zaman, Jerzyk mengemukakan bahwa loop imperatif, khususnya, adalah masalah utama.
Data yang dapat diubah: Variabel yang statusnya berubah secara tak terduga, menyebabkan efek samping yang tidak terduga.
Efek samping (alias fungsi tidak murni): Metode yang melakukan lebih dari nama dan tujuan utamanya.
Penyalahgunaan leksikal adalah indikasi bau kode yang berasal dari konvensi penamaan yang tidak tepat, format yang tidak konsisten, atau sintaksis yang membingungkan. Sederhananya, itu adalah contoh di mana kata-kata kode tidak secara intuitif cocok dengan perilaku kode yang sesuai, menghambat keterbacaan.
Contoh penyalahgunaan leksikal meliputi:
Angka ajaib: Angka-angka tanpa nama yang disisipkan dalam kode tanpa penjelasan atau konteks yang memadai.
Komentar keliru: Komentar yang tidak lagi akurat karena kode di sekitarnya telah berubah. Karena komentar tidak benar-benar dieksekusi, mereka sering lolos dari linter dan pemeriksaan otomatis lainnya.
Nama misterius: Fungsi atau variabel yang tidak diberi nama dengan baik, menyembunyikan maksud sebenarnya.
Nama metode yang salah: Fungsi yang namanya menyesatkan, berdasarkan konvensi dan harapan umum. Misalnya, fungsi bernama getSomething yang sebenarnya tidak mengembalikan apa pun.
Obfuscator (pengabur) adalah elemen kode yang ditulis dengan cara berbelit-belit, kompleks atau “pintar” yang tidak perlu dan menyembunyikan maksud mendasar kode di balik abstraksi yang tidak perlu. “Bau kode” ini membuat kode sumber sulit dibaca dan karenanya menyulitkan programmer di masa mendatang untuk memahami dan memodifikasinya sesuai kebutuhan.
Contoh pengabur meliputi:
Pemisahan vertikal: Jarak besar yang tidak perlu antara elemen kode terkait dan relevan, seperti variabel yang dideklarasikan di bagian atas metode yang tidak digunakan sampai 50 baris kemudian.
Tujuan yang Terselubung: Kategori yang lebih luas dari fungsi, variabel, nama, dan angka yang tujuannya tidak intuitif dan tidak dijelaskan secara jelas dalam konteksnya.
Ekspresi Boolean yang rumit: Aliran logis yang berbelit-belit, seperti yang mengandung negatif ganda atau rantai kompleks
Kode cerdas: Kode yang berfungsi, tetapi menggantikan bahasa khusus yang sulit dipahami dalam situasi di mana sudah ada fitur bawaan yang dipahami secara luas dan solusi konvensional lainnya.
Object-oriented abuser ( atau penyalahgunaan orientasi objek) adalah bau kode yang gagal menerapkan prinsip-prinsip desain berorientasi objek sepenuhnya atau dengan benar. Misalnya, pernyataan switch berguna dalam pemrograman prosedural, tetapi harus dihindari dalam pemrograman berorientasi objek.
Contoh pelaku penyalahgunaan berorientasi objek meliputi:
Kelas alternatif dengan antarmuka yang berbeda: Kelas melakukan fungsi serupa menggunakan nama metode yang sama sekali berbeda.
Warisan yang ditolak: Subkelas yang tidak memerlukan atau menggunakan metode yang diwariskan.
Pernyataan Switch (alias Kompleksitas Bersyarat alias Switch Berulang): Pernyataan switch yang sama persis diduplikasi di seluruh basis kode.
Kolom sementara: Variabel yang dibuat di tempat yang sering kali tidak dibutuhkan, biasanya hanya digunakan dalam keadaan tertentu.
Manfaat utama dari memahami bau kode adalah bahwa mengenalinya memungkinkan pemfaktoran ulang yang lebih efektif: praktik memperbarui kode sumber tanpa memodifikasi perilaku atau fungsionalitas eksternal. Secara rutin merapikan kode melalui pemfaktoran ulang sangat penting untuk mengurangi hutang teknis dan memfasilitasi perbaikan dan penambahan basis kode yang cepat dan efektif dari waktu ke waktu.
Pemfaktoran ulang sebagian besar dapat dipahami sebagai proses mengidentifikasi dan mengatasi bau kode. Tujuannya adalah untuk perbaikan masalah sebelum berdampak negatif pada fungsionalitas, di mana prosesnya lebih seperti debugging daripada pemfaktoran ulang.
Platform rekayasa agen modern, seperti IBM Bob, sering memberikan saran pemfaktoran ulang otomatis secara real time. Melalui pelatihan ekstensif tentang bau kode umum dalam konteks basis kode aktual, alih-alih menghafal secara langsung definisi bau kode, kemampuan pemfaktoran ul kode AI platform tersebut memungkinkan pengembang untuk menskalakan output mereka tanpa peningkatan yang sesuai dalam kode buatan AI yang sulit digunakan yang akan sulit dipahami dan dimodifikasi nanti.
Percepat penyediaan perangkat lunak dengan IBM Bob, mitra AI Anda untuk pengembangan yang aman dan sadar tujuan.
Kembangkan, terapkan, dan kelola aplikasi AI lebih cepat dengan alat yang siap untuk perusahaan.
Menata ulang sistem lama dengan modernisasi AI cerdas.