DRY #
Dalam dunia software engineering, salah satu tantangan terbesar adalah mengelola kompleksitas seiring bertambahnya ukuran dan fitur aplikasi. Kode yang awalnya sederhana bisa dengan cepat berubah menjadi sulit dipelihara jika tidak ada prinsip desain yang jelas.
Salah satu prinsip fundamental yang hampir selalu relevan di berbagai bahasa dan paradigma pemrograman adalah DRY – Don’t Repeat Yourself. Prinsip ini terdengar sederhana, tetapi penerapannya sering kali disalahpahami.
Artikel ini akan membahas:
- Apa itu prinsip DRY
- Tujuan dan nilai penting DRY
- Bentuk-bentuk pelanggaran DRY yang sering terjadi
- Hubungan DRY dengan prinsip desain lain
- Contoh konkret penerapan DRY menggunakan Golang
- Best practice dan jebakan umum (anti-pattern)
Apa Itu Prinsip DRY? #
DRY (Don’t Repeat Yourself) adalah prinsip yang menyatakan bahwa:
Setiap knowledge (aturan bisnis, logika, atau detail implementasi) dalam sistem harus memiliki satu representasi yang jelas, tunggal, dan authoritative.
Artinya, tidak ada duplikasi logika, aturan, atau pengetahuan yang sama di lebih dari satu tempat.
Perlu dicatat: DRY bukan sekadar menghindari copy-paste kode, tetapi menghindari duplikasi makna (duplication of knowledge).
Tujuan dan Nilai Penting DRY #
Maintainability #
Jika sebuah aturan bisnis berubah dan hanya ada satu sumber kebenaran, maka perubahan cukup dilakukan di satu tempat.
Mengurangi Bug #
Duplikasi kode sering menyebabkan:
- Satu bagian di-update
- Bagian lain terlupakan
Hasilnya: bug yang sulit dilacak.
Konsistensi Perilaku Sistem #
Dengan DRY, semua bagian sistem mengikuti aturan yang sama, tanpa variasi yang tidak disengaja.
Mempercepat Development Jangka Panjang #
Walaupun abstraksi butuh usaha di awal, DRY menghemat waktu saat sistem berkembang.
DRY vs Copy-Paste Programming #
| Copy-Paste | DRY |
|---|---|
| Cepat di awal | Lebih stabil jangka panjang |
| Sulit dirawat | Mudah diubah |
| Rentan bug | Lebih aman |
Copy-paste sering terasa produktif, tetapi dalam sistem besar, ia adalah utang teknis.
Bentuk Pelanggaran DRY yang Umum #
Duplikasi Logika Bisnis #
Contoh:
- Validasi email ditulis ulang di service A dan service B
- Perhitungan diskon berbeda tipis di banyak tempat
Duplikasi Konstanta atau Magic Number #
if retryCount > 3 { ... }
// di file lain
if attempts > 3 { ... }
Duplikasi Query atau Mapping Data #
Query SQL atau mapping struct yang sama tersebar di banyak layer.
Duplikasi di Level Arsitektur #
- Validasi di controller dan di service dengan logika yang sama
- Logging manual berulang di setiap handler
Contoh Kasus Tanpa DRY (Bad Example) #
Studi Kasus #
Aplikasi memiliki aturan:
User harus berusia minimal 18 tahun.
Contoh Kode (Tanpa DRY) #
func RegisterUser(age int) error {
if age < 18 {
return errors.New("user must be at least 18 years old")
}
return nil
}
func UpdateProfile(age int) error {
if age < 18 {
return errors.New("age is not valid")
}
return nil
}
Masalah #
- Logika sama, error message berbeda
- Jika aturan berubah (misalnya 21 tahun), harus update di banyak tempat
Refactor dengan Prinsip DRY #
Ekstraksi Logika ke Fungsi Tunggal #
func ValidateAge(age int) error {
if age < 18 {
return errors.New("user must be at least 18 years old")
}
return nil
}
func RegisterUser(age int) error {
return ValidateAge(age)
}
func UpdateProfile(age int) error {
return ValidateAge(age)
}
Sekarang aturan usia hanya ada di satu tempat.
DRY di Level Struktur dan Package (Golang) #
Contoh: Validasi Input #
Struktur Package #
/internal
/validation
user.go
package validation
import "errors"
func ValidateEmail(email string) error {
if email == "" {
return errors.New("email is required")
}
return nil
}
Digunakan di berbagai service tanpa duplikasi.
DRY dengan Struct dan Method #
Tanpa DRY #
type Order struct {
Price float64
}
func CalculateTax(price float64) float64 {
return price * 0.1
}
Dengan DRY (Encapsulation) #
type Order struct {
Price float64
}
func (o Order) Tax() float64 {
return o.Price * 0.1
}
Knowledge tentang pajak melekat pada domain-nya.
DRY dan Konfigurasi #
Anti-Pattern #
if env == "production" {
maxRetry = 5
}
Ditulis ulang di banyak tempat.
DRY dengan Config Terpusat #
type AppConfig struct {
MaxRetry int
}
Config dibaca sekali dan digunakan bersama.
DRY vs Over-Engineering #
⚠️ Peringatan Penting
DRY bukan berarti:
- Semua harus diabstraksi
- Semua harus dibuat generic
Rule of Thumb #
Abstract when you see duplication of meaning, not duplication of shape.
Jika dua kode terlihat sama tapi belum tentu mewakili aturan yang sama, jangan dipaksakan DRY.
Hubungan DRY dengan Prinsip Lain #
- SRP (Single Responsibility Principle): DRY mendorong satu tanggung jawab
- Clean Code: DRY meningkatkan readability
- Clean Architecture: DRY membantu menjaga boundary antar layer
Best Practice Menerapkan DRY di Golang #
- Gunakan package kecil dan fokus
- Ekstrak aturan bisnis ke domain/service
- Hindari magic number, gunakan constant
- Gunakan helper dengan bijak
- Jangan terlalu cepat melakukan abstraksi
Kesimpulan #
Prinsip DRY (Don’t Repeat Yourself) adalah fondasi penting dalam membangun software yang:
- Mudah dirawat
- Minim bug
- Siap berkembang
Dalam Golang, DRY bisa diterapkan secara natural melalui:
- Package design
- Function & method
- Struct dan encapsulation
Namun ingat, DRY yang baik adalah seimbang, bukan berlebihan.
Duplication is cheaper than the wrong abstraction.