DRY (Don't Repeat Yourself) — prinsip fundamental pengembangan yang dirumuskan oleh Andy Hunt dan Dave Thomas dalam buku “The Pragmatic Programmer”. Prinsip ini menyatakan: setiap bagian pengetahuan dalam sistem harus memiliki representasi tunggal, tidak ambigu, dan otoritatif. Menurut The Pragmatic Programmer, 20th Anniversary Edition, pelanggaran DRY menyebabkan perubahan satu elemen memerlukan koreksi di puluhan tempat, dan setiap fragmen yang terlewat menjadi sumber bug.
Poin Utama
DRY (Don't Repeat Yourself) — prinsip pengembangan yang memerlukan penyimpanan tunggal setiap elemen pengetahuan dalam proyek. Ini berarti setiap logika, konfigurasi, atau metadata harus ada tepat di satu tempat.
Istilah ini diperkenalkan oleh Andy Hunt dan Dave Thomas pada tahun 1999 dalam buku “The Pragmatic Programmer”. Penulis mendefinisikan DRY sebagai “setiap bagian pengetahuan harus memiliki representasi tunggal yang konsisten dalam sistem”. Kebalikan dari DRY — pendekatan WET (Write Everything Twice), di mana duplikasi dianggap sebagai norma.
Menurut penelitian University of California, Davis (2019), proyek dengan tingkat duplikasi kode yang tinggi menghabiskan waktu 42% lebih banyak untuk memperbaiki bug. Alasannya adalah pengembang harus menemukan dan mengubah semua salinan dari fragmen yang sama — dan dalam pencarian manual, kelalaian tidak dapat dihindari.
Terapkan DRY sebagai kriteria kualitas kode. Jika Anda melihat pola yang sama muncul dalam proyek tiga kali — pisahkan ke dalam abstraksi, tanpa menunggu pengulangan keempat.
Single Responsibility Principle (SRP) dari SOLID menyatakan bahwa sebuah kelas harus memiliki satu alasan untuk berubah. DRY lebih luas: tidak hanya mencakup kelas, tetapi juga data, konfigurasi, dokumentasi, dan bahkan aturan bisnis. SRP tentang batas tanggung jawab, DRY — tentang tidak diperbolehkannya menyalin.
Dalam pengembangan mobile, perbedaan ini sangat terlihat. Jika aturan bisnis yang sama (perhitungan pajak, format tanggal) berulang di bagian Android dan iOS — ini adalah pelanggaran DRY, meskipun SRP secara formal dipatuhi dalam setiap platform. Solusi — memisahkan logika umum ke dalam modul bersama (KMM, C++).
Menurut laporan Google Android Architecture Guidelines (2023), tim yang menggunakan modul bersama untuk logika bisnis mengurangi jumlah bug saat perubahan persyaratan sebesar 37% dibandingkan dengan proyek dengan duplikasi logika antar platform.
Duplikasi — sumber utama utang teknis dalam proyek mobile. Setiap salinan kode menciptakan ketergantungan tersembunyi: untuk mengubah perilaku, semua salinan harus ditemukan dan diperbarui. Melewatkan satu saja berarti bug.
Pertimbangkan situasi klasik: dalam aplikasi Android, pemformatan tanggal dilakukan di tiga Activity yang berbeda. Saat beralih ke format baru (misalnya ISO 8601), pengembang memperbaiki dua file, lupa yang ketiga — dan pengguna melihat tanggal dalam format lama. Peringkat pengguna aplikasi turun, dan menemukan bug membutuhkan waktu dua kali lebih lama.
Penelitian Google Research (2020) menunjukkan: 68% bug kritis dalam aplikasi mobile terkait dengan perubahan kode duplikat yang tidak sinkron. Biaya memperbaiki bug semacam itu di production 4,5 kali lebih tinggi daripada jika kode tersebut seragam sejak awal.
Gunakan penganalisis statis (Detekt, SwiftLint) dengan aturan yang melarang deteksi copy-paste. Konfigurasikan CI sehingga pull-request dengan duplikasi lebih dari N baris tidak lolos review tanpa justifikasi.
Anti-pattern tipikal — menyalin adapter RecyclerView dengan perubahan kecil. Alih-alih satu adapter universal dengan konfigurasi, pengembang membuat kelas terpisah untuk setiap layar. Refactoring dengan pemisahan kelas dasar bersama mempersingkat kode sebesar 30–50%.
// Duplikasi: dua adapter terpisah
class UserAdapter {
fun bind(item: User) { /* ... */ }
}
class ProductAdapter {
fun bind(item: Product) { /* ... */ }
}
// Refactoring DRY: kelas dasar bersama
abstract class BaseAdapter<T> {
abstract fun bind(item: T)
}
class UserAdapter : BaseAdapter<User>() { /* ... */ }
class ProductAdapter : BaseAdapter<Product>() { /* ... */ }
Dalam contoh pertama, setiap adapter mengimplementasikan mekanisme bind dari awal. Saat menambahkan logika baru (analitik, pencatatan), setiap file harus diubah. Kelas dasar menghilangkan duplikasi ini: logika umum hidup di satu tempat, logika spesifik di kelas turunan.
Dalam proyek iOS, konfigurasi URLSession sering diduplikasi — header, batas waktu, penanganan kesalahan. Setiap layanan membuat sesi sendiri dengan pengaturan yang berulang.
// Duplikasi: setiap layanan mengonfigurasi sesi dari awal
class UserService {
let session = URLSession(configuration: {
let cfg = URLSessionConfiguration.default
cfg.timeoutIntervalForRequest = 30
cfg.httpAdditionalHeaders = ["Authorization": "Bearer ..."]
return cfg
}())
}
// DRY: pabrik sesi terpadu
struct NetworkConfig {
static var session: URLSession {
let cfg = URLSessionConfiguration.default
cfg.timeoutIntervalForRequest = 30
cfg.httpAdditionalHeaders = ["Authorization": "Bearer ..."]
return URLSession(configuration: cfg)
}
}
Memisahkan konfigurasi ke dalam NetworkConfig terpadu memastikan bahwa semua layanan menggunakan header dan batas waktu yang sama. Perubahan di satu tempat secara otomatis diterapkan ke semua permintaan — ini mengurangi risiko kesalahan saat mengubah kunci API atau versi protokol.
Pewarisan — cara alami untuk menghilangkan duplikasi: logika umum dipisahkan ke kelas dasar, dan logika spesifik ke kelas turunan. Namun dalam pengembangan mobile, penyalahgunaan pewarisan menciptakan hierarki kaku yang sulit dipelihara. Komposisi (injeksi ketergantungan) — alternatif yang lebih fleksibel.
Analisis Google I/O 2023: Modern Android Architecture menunjukkan bahwa 76% tim Google lebih memilih komposisi daripada pewarisan untuk menghilangkan duplikasi. Alih-alih BaseViewModel dengan sepuluh metode, disarankan untuk memisahkan kelas UseCase terpisah untuk setiap operasi bisnis dan menyuntikkannya di tempat yang diperlukan.
Pilih komposisi dalam semua kasus kecuali relasi “adalah”. Jika kelas A adalah spesialisasi dari kelas B — pewarisan tepat. Jika A hanya menggunakan fungsionalitas B — gunakan komposisi.
Kelas utilitas (Extensions, Helpers) — cara paling sederhana untuk menghindari duplikasi. Kandidat tipikal: pemformatan tanggal, validasi email, konversi unit, bekerja dengan SharedPreferences/UserDefaults.
// DRY: fungsi format tanggal terpadu
fun Date.toDisplayFormat(): String {
val sdf = SimpleDateFormat("dd.MM.yyyy", Locale.getDefault())
return sdf.format(this)
}
// Penggunaan di mana saja dalam aplikasi
textView.text = Date().toDisplayFormat()
Ekstensi Date.toDisplayFormat() dideklarasikan sekali dan tersedia di seluruh proyek. Jika format perlu diubah dari “dd.MM.yyyy” menjadi “yyyy-MM-dd” — koreksi di satu file, bukan di setiap Activity atau Fragment tempat pemformatan muncul. Ini adalah inti dari DRY.
Proyek Android multi-modul sering menduplikasi versi dependensi di setiap build.gradle. Solusinya — version catalog (libs.versions.toml), yang memusatkan semua versi dalam satu file.
Menurut Android Developer Documentation (2024), migrasi ke version catalog mengurangi konflik dependensi sebesar 52% dan mempercepat pembangunan berkat titik koreksi tunggal.
Terapkan version catalog di awal proyek atau pada reorganisasi modul pertama. Jika proyek sudah memiliki duplikasi — alokasikan satu hari untuk migrasi: itu akan terbayar pada pembaruan perpustakaan berikutnya.
Abstraksi prematur — kesalahan paling umum dari pemula. Pengembang melihat dua baris kode yang mirip dan segera memisahkannya ke dalam fungsi bersama. Setelah sebulan, persyaratan berubah dan fungsi bersama menjadi sarat dengan parameter dan flag — menjadi lebih kompleks daripada duplikasi awal. Rule of Three melindungi dari hal ini: jangan abstraksi apa yang muncul satu atau dua kali.
Martin Fowler dalam buku Refactoring (2019) merekomendasikan: “Duplikasi kode tidak selalu buruk. Duplikasi pengetahuan adalah buruk”. Jika dua baris secara kebetulan cocok tetapi mengekspresikan konsep yang berbeda — itu bukan duplikasi, melainkan kebetulan. Rule of Three membantu membedakan kebetulan dari duplikasi sistematis.
Sebelum mengabstraksi, evaluasi semantiknya. Kode yang disalin dengan makna yang sama — pelanggaran DRY. Kode dengan makna berbeda tetapi sintaksis serupa — kebetulan yang tidak memerlukan abstraksi.
Parameterisasi berlebihan terjadi ketika satu fungsi mencoba mencakup semua skenario yang mungkin melalui flag dan parameter boolean. Kode semacam itu melanggar SRP dan menjadi tidak terbaca. Gejala: jika fungsi memiliki lebih dari dua parameter boolean — ini adalah bau kode (code smell) dari abstraksi berlebihan.
Alih-alih satu fungsi dengan flag useCache: Boolean, lebih baik membuat dua fungsi terpisah dengan nama yang jelas: fetchFromNetwork() dan fetchFromCache(). Kejelasan lebih penting daripada abstraksi kering — ini sejalan dengan prinsip KISS.
Refactor parameterisasi berlebihan ketika fungsi mencapai 3+ parameter boolean. Bagi menjadi fungsi terpisah dengan nama yang jelas — setiap panggilan akan menjadi self-documenting.
Pertanyaan Umum
DRY (Don't Repeat Yourself) — prinsip yang mengharuskan setiap unit logis disimpan di satu tempat. Jika kode yang sama muncul di beberapa bagian proyek — ini adalah pelanggaran DRY. Perbaikan: pindahkan logika yang berulang ke fungsi, kelas, atau modul terpisah.
WET (Write Everything Twice) — antitesis dari DRY, di mana duplikasi dianggap dapat diterima. Dalam proyek WET, fragmen kode yang sama dapat ada dalam lima salinan, dan ketika persyaratan berubah, pengembang memperbaiki setiap salinan secara terpisah. WET meningkatkan risiko bug dan memperlambat pengembangan.
DRY berbahaya pada abstraksi prematur: ketika dua bagian kode yang mirip tetapi secara semantik berbeda dipaksakan digabungkan menjadi satu fungsi. Ini menciptakan kode kompleks yang sarat parameter. Rule of Three membantu menghindari kesalahan ini: abstraksi hanya setelah pengulangan ketiga.
Di Android, DRY diterapkan melalui version catalog (libs.versions.toml), kelas dasar bersama untuk adapter, pabrik ViewModel, dan ekstensi Kotlin yang berguna. Disarankan untuk memisahkan logika bisnis ke modul bersama (KMM) dan menggunakan View Binding untuk menghilangkan duplikasi findViewById.
Di iOS, DRY dicapai melalui protokol dengan implementasi default, konfigurasi jaringan bersama (NetworkConfig), pabrik sel UICollectionView, dan paket SPM dengan logika bisnis bersama. Extensions dari tipe standar (Date, String, URL) mengurangi duplikasi pemformatan dan validasi.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga