Daftar Isi
Kode yang "jalan" dan kode yang "mudah dibaca tim" adalah dua hal berbeda. Kode yang cuma jalan akan terus menimbulkan pertanyaan "ini ngapain ya?" setiap kali rekan tim (atau Anda sendiri, enam bulan kemudian) harus membukanya lagi. Berikut 7 kebiasaan kecil yang paling berpengaruh terhadap keterbacaan kode PHP, lengkap dengan contoh sebelum dan sesudah.
1. Nama Variabel dan Fungsi yang Menjelaskan Dirinya Sendiri
// ❌ Sulit ditebak tanpa membaca isinya
function calc($a, $b, $t) {
return $t === 'sum' ? $a + $b : $a - $b;
}
// ✅ Langsung jelas dari namanya saja
function calculateTotal(float $price, float $discount, string $operation): float
{
return $operation === 'add' ? $price + $discount : $price - $discount;
}
Aturan sederhana: kalau Anda butuh komentar untuk menjelaskan apa isi sebuah variabel, itu tanda nama variabelnya perlu diperbaiki, bukan ditambah komentar.
2. Satu Fungsi, Satu Tanggung Jawab
// ❌ Fungsi ini melakukan validasi, simpan ke DB, DAN kirim email sekaligus
function registerUser($data)
{
if (empty($data['email']) || !str_contains($data['email'], '@')) {
throw new Exception('Email tidak valid');
}
$user = User::create($data);
Mail::to($user->email)->send(new WelcomeEmail($user));
return $user;
}
// ✅ Dipecah, masing-masing fungsi punya satu tanggung jawab
function validateUserData(array $data): void
{
if (empty($data['email']) || !str_contains($data['email'], '@')) {
throw new InvalidArgumentException('Email tidak valid');
}
}
function registerUser(array $data): User
{
validateUserData($data);
$user = User::create($data);
Mail::to($user->email)->send(new WelcomeEmail($user));
return $user;
}
Manfaatnya bukan cuma soal rapi — fungsi validateUserData() sekarang bisa dipakai ulang di tempat lain, dan bisa dites secara terpisah tanpa harus benar-benar mengirim email setiap kali testing.
3. Hindari Nesting Dalam yang Membuat Kode Seperti Piramida
// ❌ Semakin dalam nesting-nya, semakin sulit diikuti alurnya
function processOrder($order)
{
if ($order) {
if ($order->status === 'pending') {
if ($order->payment) {
if ($order->payment->status === 'success') {
return 'Pesanan diproses';
} else {
return 'Pembayaran gagal';
}
} else {
return 'Belum ada pembayaran';
}
} else {
return 'Status pesanan tidak valid';
}
} else {
return 'Pesanan tidak ditemukan';
}
}
// ✅ Guard clause: keluar lebih awal untuk kondisi yang tidak valid
function processOrder(?Order $order): string
{
if (!$order) {
return 'Pesanan tidak ditemukan';
}
if ($order->status !== 'pending') {
return 'Status pesanan tidak valid';
}
if (!$order->payment) {
return 'Belum ada pembayaran';
}
if ($order->payment->status !== 'success') {
return 'Pembayaran gagal';
}
return 'Pesanan diproses';
}
Versi kedua dibaca dari atas ke bawah tanpa perlu "menyimpan" banyak konteks if di kepala Anda sekaligus — setiap baris menangani satu kondisi gagal, lalu selesai dengan alur utama di paling akhir.
4. Ganti Angka/String "Ajaib" dengan Konstanta
// ❌ Angka 3 dan string 'admin' ini artinya apa? Harus tebak dari konteks
if ($user->role === 'admin' && $attempts < 3) {
// ...
}
// ✅ Konstanta memberi nama pada nilai yang artinya tidak jelas dengan sendirinya
class User
{
const ROLE_ADMIN = 'admin';
const MAX_LOGIN_ATTEMPTS = 3;
}
if ($user->role === User::ROLE_ADMIN && $attempts < User::MAX_LOGIN_ATTEMPTS) {
// ...
}
Manfaat tambahan: kalau suatu saat batas percobaan login berubah dari 3 menjadi 5, Anda cukup ubah satu tempat, bukan mencari-cari semua angka "3" yang tersebar di codebase.
5. Konsisten dalam Konvensi Penamaan
// ❌ Campur aduk: snake_case, camelCase, dan singkatan tidak konsisten
$user_name = $request->input('name');
$userEmail = $request->input('email');
$usr_addr = $request->input('address');
// ✅ Konsisten memakai satu gaya (PHP/Laravel umumnya pakai camelCase untuk variabel)
$userName = $request->input('name');
$userEmail = $request->input('email');
$userAddress = $request->input('address');
Ikuti standar PSR-12 untuk PHP secara umum, dan konvensi Laravel (camelCase untuk variabel & method, StudlyCase untuk nama class) kalau proyek Anda berbasis Laravel.
6. Komentar Menjelaskan "Kenapa", Bukan "Apa"
// ❌ Komentar ini cuma mengulang apa yang sudah jelas dari kodenya
// Loop untuk setiap user
foreach ($users as $user) {
// set status jadi aktif
$user->status = 'active';
}
// ✅ Komentar menjelaskan alasan yang tidak terlihat dari kode itu sendiri
// Reset status ke 'active' setelah masa suspend 30 hari berakhir,
// sesuai kebijakan yang disepakati tim support (lihat tiket #4521)
foreach ($users as $user) {
$user->status = 'active';
}
Kode yang baik sudah menjelaskan apa yang dilakukannya lewat nama variabel dan fungsi yang jelas. Komentar seharusnya mengisi bagian yang tidak bisa dijelaskan kode itu sendiri: alasan bisnis, keputusan desain, atau workaround untuk bug tertentu.
7. Return Type dan Type Hint yang Eksplisit
// ❌ Tidak ada informasi tipe data — harus baca isi fungsi untuk tahu
function getActiveUsers($minAge)
{
return User::where('age', '>=', $minAge)->where('active', true)->get();
}
// ✅ Type hint membuat kontrak fungsi jelas tanpa perlu baca isinya
function getActiveUsers(int $minAge): Collection
{
return User::where('age', '>=', $minAge)->where('active', true)->get();
}
Selain membuat kode lebih jelas, type hint membuat IDE bisa memberi autocomplete yang akurat dan menangkap kesalahan tipe data lebih awal, sebelum sempat dijalankan.
Bonus: Manfaatkan Tools Otomatis
Tidak semua kebiasaan ini harus diingat manual setiap saat — beberapa tools bisa membantu menegakkannya secara otomatis:
- Laravel Pint — merapikan format kode otomatis sesuai standar PSR-12, tinggal jalankan
./vendor/bin/pint. - PHPStan atau Larastan — menangkap potensi bug dan inkonsistensi tipe data sebelum kode di-commit.
- Git pre-commit hook — menjalankan Pint dan PHPStan otomatis setiap kali Anda commit, supaya kode yang tidak rapi tidak pernah sampai masuk repository.
Kesimpulan
Clean code bukan soal kesempurnaan estetika — ini soal menghemat waktu tim Anda di masa depan. Kode yang mudah dibaca berarti bug lebih cepat ditemukan, fitur baru lebih cepat ditambahkan, dan onboarding developer baru jadi jauh lebih ringan. Mulai dari kebiasaan paling mudah diterapkan hari ini — misalnya memperbaiki satu nama variabel yang membingungkan di file yang sedang Anda kerjakan sekarang.