Saya pernah nulis kode yang saat itu sense banget. Logikanya jelas, alurnya rapi, variabel-nya deskriptif. Tiga bulan kemudian, buka lagi file yang sama — “ini tadi mau ngapain sih?”
Nganu, kalau kamu pernah merasakan hal yang sama, selamat datang. Kamu tidak sendirian hehe.
Tulisan ini bukan kuliah formal tentang arsitektur software. Ini catatan saya tentang Clean Architecture — dijelaskan dengan cara yang saya sendiri pengen dulu dengar waktu masih kuliah, bukan dengan istilah-istilah yang bikin pusing.
Apa Itu “Spaghetti Code” dan Kenapa Kita Semua Pernah Menulisnya #
Spaghetti code itu bukan istilah teknis yang formal. Tapi semua developer tahu apa artinya: kode yang saling terikat dan sulit dipisahkan, seperti mie spaghetti yang nggak bisa kamu ambil satu helai tanpa menarik yang lain.
Contoh nyata dari proyek GPS tracker yang pernah saya tangani. Dulu, ada satu function yang kurang lebih begini (ini pseudo-code, ya):
function handleUpdatePosition(request):
// Langsung query ke database
vehicle = db.query("SELECT * FROM vehicles WHERE id = ?", request.vehicleId)
if not vehicle:
return error("Vehicle not found")
// Business logic campur di sini
if vehicle.status == "inactive":
vehicle.status = "active"
vehicle.lastActivation = now()
// Update posisi
db.query("UPDATE positions SET lat = ?, lng = ?, time = ? WHERE vehicleId = ?",
request.lat, request.lng, now(), request.vehicleId)
// Kirim notifikasi langsung dari sini
if vehicle.hasAlert:
email.send(vehicle.ownerEmail, "Alert: " + vehicle.name)
sms.send(vehicle.ownerPhone, "Alert from " + vehicle.name)
// Generate laporan langsung
report = generateDailyReport(vehicle)
db.query("INSERT INTO reports ...", report)
return success(vehicle)
Bisa dilihat? Satu function nangkap semua — baca database, olah logika bisnis, kirim email, kirim SMS, generate laporan. Saat itu kelihatannya praktis. Tapi coba bayangkan:
- Kalau mau ganti cara kirim notifikasi — harus edit function ini
- Kalau mau test logika bisnis — harus setup database dan email server
- Kalau mau ganti database — harus ubah semua query yang tersebar di mana-mana
- Kalau ada bug di laporan — harus trace lewat function yang sudah panjang ini
┌─────────────────────────────────────────────────┐
│ Spaghetti Flow │
│ │
│ Request ──► [Database + Logic + Email + Report] │
│ │ │
│ ▼ │
│ Semua menyatu. │
│ Ubah satu, risiko semua goyah. │
└─────────────────────────────────────────────────┘
Intinya: ubah satu hal, risiko hal lain ikut rusak.
Clean Architecture: Intinya Sederhana Kok #
Istilah “Clean Architecture” populer lewat Robert C. Martin (Uncle Bob). Tapi jangan keterangan dulu — kamu tidak perlu baca bukunya untuk mulai memahami idenya.
Intinya cuma satu kalimat: kode yang penting (logika bisnis) tidak boleh tergantung pada detail teknis (database, framework, API).
Kenapa? Karena logika bisnis itu yang tidak berubah — aturan cara menghitung jarak, cara menentukan kendaraan aktif, cara menentukan batas kecepatan. Database, framework, cara kirim email — itu detail yang bisa berubah.
Aturan Ketergantungan (Dependency Rule) #
┌──────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Entity │ │
│ │ Aturan bisnis inti. Paling dalam. │ │
│ │ Tidak tergantung apapun. │ │
│ │ │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ Use Case │ │ │
│ │ │ Apa yang sistem lakukan. │ │ │
│ │ │ Tergantung ke Entity, bukan ke DB. │ │ │
│ │ │ │ │ │
│ │ │ ┌───────────────────────────────┐ │ │ │
│ │ │ │ Infrastructure │ │ │ │
│ │ │ │ Database, API, Email, SMS. │ │ │ │
│ │ │ │ Detail teknis. Paling luar. │ │ │ │
│ │ │ └───────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ Arah panah: luar ──► dalam │
│ Luar tergantung pada dalam. Dalam TIDAK tergantung │
│ pada luar. │
└──────────────────────────────────────────────────────┘
Aturannya sederhana: panah hanya boleh mengarah ke dalam. Entity tidak tahu apa-apa tentang database. Use Case tidak tahu cara kirim email. Infrastructure yang tahu detail teknis.
Ini artinya: kalau kamu mau ganti database dari MySQL ke PostgreSQL, Entity dan Use Case tidak berubah sama sekali. Yang berubah cuma Infrastructure.
Tiga Layer yang Penting #
Untuk mahasiswa, saya rasa tiga layer ini yang paling penting dipahami:
1. Entity — Aturan Bisnis Inti
Ini yang tidak boleh berubah terlepas dari teknologi apa pun yang kamu pakai. Di proyek GPS tracker, contohnya:
class Vehicle:
id, name, status, currentSpeed, speedLimit
function isSpeeding():
return currentSpeed > speedLimit
function activate():
if status == "inactive":
status = "active"
lastActivation = now()
Perhatikan: tidak ada database query, tidak ada HTTP request, tidak ada framework. Ini murni aturan bisnis — apakah kendaraan speeding, bagaimana cara mengaktifkan kendaraan. Bahkan kalau besok ganti bahasa pemrograman, logika ini tetap sama.
2. Use Case — Apa yang Sistem Lakukan
Use case mendefinisikan apa yang sistem lakukan, tanpa peduli bagaimana detailnya.
class UpdatePositionUseCase:
function execute(vehicleId, lat, lng):
// 1. Cari kendaraan
vehicle = vehicleRepository.findById(vehicleId)
if not vehicle:
return error("Vehicle not found")
// 2. Update posisi
vehicle.updatePosition(lat, lng)
// 3. Simpan
vehicleRepository.save(vehicle)
// 4. Kalau speeding, trigger alert
if vehicle.isSpeeding():
alertService.sendSpeedAlert(vehicle)
Perhatikan: use case memanggil vehicleRepository dan alertService, tapi tidak tahu apakah itu pakai MySQL, PostgreSQL, kirim via email atau SMS. Dia cuma tahu “cari kendaraan”, “simpan”, “kirim alert”.
Ini kekuatan utama Clean Architecture: kamu bisa mengganti database tanpa menyentuh use case.
3. Infrastructure — Detail Teknis
Di sinilah detail implementasi berada — database, API, framework, email service, dll.
class MySQLVehicleRepository:
function findById(id):
row = db.query("SELECT * FROM vehicles WHERE id = ?", id)
return Vehicle(id: row.id, name: row.name, ...)
function save(vehicle):
db.query("UPDATE vehicles SET lat = ?, lng = ? WHERE id = ?",
vehicle.lat, vehicle.lng, vehicle.id)
class EmailAlertService:
function sendSpeedAlert(vehicle):
email.send(
to: vehicle.ownerEmail,
subject: "Speed Alert: " + vehicle.name,
body: vehicle.name + " is going " + vehicle.currentSpeed
)
Ini bagian yang boleh berubah. Kalau mau ganti MySQL ke PostgreSQL — ubah di sini. Kalau mau ganti email ke WhatsApp — ubah di sini. Entity dan Use Case tidak tersentuh.
Langkah demi Langkah: Terapkan di GPS Tracker #
Sekarang mari kita bandingkan kode spaghetti di awal dengan versi yang sudah “clean”:
Before: Spaghetti #
Satu function nangkap semua — baca DB, olah logika, kirim notifikasi, generate laporan. Semua menyatu.
After: Clean #
// === Entity: Vehicle ===
// (aturan bisnis murni, tidak tergantung apapun)
class Vehicle:
function updatePosition(lat, lng):
this.lat = lat
this.lng = lng
this.lastUpdate = now()
function isSpeeding():
return this.currentSpeed > this.speedLimit
// === Use Case: UpdatePosition ===
// (apa yang dilakukan, tanpa peduli bagaimana)
class UpdatePositionUseCase:
function execute(vehicleId, lat, lng):
vehicle = repository.findById(vehicleId)
if not vehicle:
return error("Not found")
vehicle.updatePosition(lat, lng)
repository.save(vehicle)
if vehicle.isSpeeding():
alertService.sendSpeedAlert(vehicle)
return success(vehicle)
// === Infrastructure ===
// (detail teknis — boleh berubah kapanpun)
class MySQLVehicleRepository:
function findById(id):
return db.query("SELECT ...")
function save(vehicle):
db.query("UPDATE ...")
class EmailAlertService:
function sendSpeedAlert(vehicle):
email.send(...)
Apa yang Berubah? #
| Aspek | Spaghetti | Clean |
|---|---|---|
| Test logika bisnis | Perlu setup DB + email | Cuma test Vehicle class |
| Ganti database | Ubah semua query di mana-mana | Ubah cuma repository |
| Ganti cara alert | Cari di seluruh codebase | Ubah cuma AlertService |
| Onboarding developer baru | Baca satu function panjang | Baca per layer, mulai dari Entity |
| Efek samping perubahan | Domino effect | Terisolasi per layer |
Perhatikan: setiap layer bisa di-test sendiri. Vehicle bisa di-test tanpa database. UpdatePositionUseCase bisa di-test dengan mock repository. MySQLVehicleRepository bisa di-test secara terpisah.
Kenapa Ini Penting Buat Kamu #
Bukan Cuma Buat Proyek Besar
Mungkin kamu berpikir, “Ini kan buat proyek gede. Skripsi saya cuma aplikasi kecil.” Betul — untuk aplikasi kecil, Clean Architecture bisa overkill. Tapi prinsipnya tetap berlaku:
- Pisahkan yang penting dari detail teknis — ini bukan soal jumlah layer, ini soal mindset
- Tulis kode yang bisa di-test — bahkan di proyek kecil, ini save time saat debugging
- Pikirkan dulu, tulis kemudian — Clean Architecture itu soal memikirkan apa yang penting sebelum mulai ngode
Untuk skripsi, dosen pasti akan tanya “kenapa kamu design sistem seperti ini?” Kalau kamu bisa jawab “karena logika bisnis saya tidak tergantung pada database” — itu jawaban yang jauh lebih kuat daripada “karena tutorial yang saya ikuti seperti itu”.
Kapan Boleh Tidak Pakai Clean Architecture #
Clean Architecture bukan silver bullet. Ada saatnya tidak perlu:
- Prototype — kalau kamu cuma mau proof of concept, tulis saja cepat. Jangan overthink.
- Script kecil — kalau cuma 50 baris untuk scrape data, tidak perlu layer-layeran.
- Belajar dasar dulu — kalau belum nyaman dengan OOP atau design pattern, pelajari itu dulu. Clean Architecture butuh fondasi tersebut.
Intinya: gunakan ketika kompleksitas sudah membutuhkannya, bukan karena kedengarannya keren.
Pelajaran #
1. Spaghetti Code Itu Normal, Tinggal di Itu yang Tidak Normal #
Semua developer pernah nulis spaghetti code — termasuk yang sudah senior. Yang membedakan adalah: sadar kalau kodenya sudah spaghetti, dan tahu cara memperbaikinya.
2. Pisahkan “Apa” dari “Bagaimana” #
Apa yang sistem lakukan (business logic) harus terpisah dari bagaimana sistem melakukannya (database, API, framework). Ini inti Clean Architecture.
3. Test-ability Itu Indikator Arsitektur yang Baik #
Kalau kamu sulit menulis unit test untuk kode kamu — itu sinyal bahwa arsitekturnya perlu dipikirkan ulang. Kode yang baik itu mudah ditest.
4. Jangan Dogmatis #
Clean Architecture itu tool, bukan agama. Kalau konteksnya tidak membutuhkan — tidak perlu dipaksakan. Yang penting paham prinsipnya dan tahu kapan mengaplikasikannya.
Penutup #
Clean Architecture, pada intinya, bukan soal jumlah layer atau pattern yang fancy. Ini soal menulis kode yang bisa dipahami, diubah, dan di-test — oleh diri kamu sendiri maupun orang lain. Bahkan kalau itu 3 bulan kemudian hehe.
Kalau kamu tertarik melihat bagaimana Clean Architecture ini diterapkan di proyek nyata (migrasi dari PHP ke Go, 370+ endpoint), saya punya catatan terpisah untuk sisi implementasinya.
Kalau ada pertanyaan atau mau diskusi lebih lanjut, hubungi saya. Atau lihat layanan yang bisa saya bantu.
Tag: catatan · arsitektur