Sepanjang Section ini kita membangun peralatannya: container yang menyediakan dependency, service dan action penampung logika bisnis, struktur per domain, konfigurasi terpusat, controller ramping. Peralatan saja tidak cukup — aplikasi berumur dua tahun ditentukan oleh kebiasaan harian, bukan pola yang dipilih sekali di awal. Chapter penutup ini merangkum praktik yang menjaga aplikasi Laravel mudah dirawat seiring usia. Kode contohnya sedikit, keputusannya banyak.
Peta Besar: Lapisan yang Saling Mengunci #
Seluruh Section ini sebenarnya satu gambar: setiap lapisan punya satu tugas dan hanya berbicara dengan lapisan tetangganya.
Kekuatan diagram ini bukan kotak-kotaknya, melainkan panah-panah yang tidak ada: controller tidak menulis query rumit, action tidak membaca Request, model tidak mengirim email. Setiap panah liar yang melompati lapisan berarti satu bagian mengetahui terlalu banyak — awal kode yang sulit diubah.
Disiplin Penamaan dan Konvensi Membosankan #
Kode yang mudah dirawat punya kosakata konsisten: satu konsep satu nama. Jika pendaftaran disebut RegisterUser di action, sebutlah RegisterUser juga di job dan command — bukan berganti-ganti menjadi UserSignup atau DaftarPenggunaBaru. Nama method adalah kata kerja, nama class domain adalah kata benda — folder app/Actions/ yang terbaca seperti daftar kemampuan aplikasi adalah tanda kosakata sehat. Penamaan adalah dokumentasi termurah: gratis dan selalu ikut kode.
Sisi lainnya adalah kesetiaan pada konvensi bawaan framework. Struktur folder default, Eloquent yang dipanggil langsung, middleware yang terdaftar di bootstrap/app.php — keputusan “membosankan” ini punya satu keunggulan: semua pengembang Laravel sudah memahaminya. Penyimpangan tetap sah, seperti structure per domain atau repository di chapter sebelumnya, tetapi harus dibayar dengan masalah konkret yang diselesaikannya — bukan selera sesaat.
Test sebagai Pengait #
Feature test berfungsi seperti pengait (ratchet) di bengkel: boleh berputar maju, dilarang berputar mundur. Setiap fitur yang datang bersama test menaikkan lantai keselamatan sedikit demi sedikit — refactor controller gemuk di chapter sebelumnya aman justru karena lantai itu sudah ada. Aplikasi sandbox kita menutup Section dengan 14 test hijau; tidak banyak, tetapi setiap perubahan struktural berjalan tanpa satu assertion pun diubah.
Dokumentasikan MENGAPA #
Kode menjawab “apa” dan “bagaimana” dengan sangat baik, tetapi diam total tentang “mengapa”. Keputusan arsitektural penting layak satu catatan singkat — pola ringan yang lazim disebut decision record:
ADR-007: Logika bisnis di action class, bukan controller
Status: Diterima
Konteks: store() di ProdukController menumpuk empat tanggung jawab dan
hanya bisa diuji lewat HTTP penuh.
Keputusan: Satu aksi bisnis = satu action class invokable; validasi ke
FormRequest; notifikasi lewat event + listener.
Konsekuensi: Controller hanya mengoordinasikan; action dites tanpa HTTP.
Alternatif service class multi-method ditolak karena aksi jarang berbagi kode.Lima menit menulis: dua tahun kemudian, anggota tim baru yang bertanya “kenapa tidak taruh saja di controller?” tidak perlu menebak — jawabannya terarsip lengkap.
Higiene Dependency #
Package yang menua adalah utang yang diam-diam berbunga. Larinya rutin dan murah:
Output yang Dihasilkan:
$ composer outdated --direct
Legend:
! patch or minor release available - update recommended
~ major release available - update possible
phpunit/phpunit 12.5.39 ~ 13.4.2 The PHP Unit Testing framework.Terbaca jujur: seluruh dependency lain sudah di versi terkini, tinggal satu loncatan major PHPUnit yang menunggu. Patch dan minor bisa diikuti mingguan lewat composer update — irama kecil, risiko kecil. Loncatan major seperti baris ~ layak dijadwalkan khusus: baca panduan upgrade, sesuaikan test, jangan campur dengan perubahan fitur. Menunda selamanya bukan pilihan; dependency yang tertinggal jauh membuat aplikasi tak bisa naik PHP atau Laravel berikutnya.
Pint di CI #
Konsistensi gaya kode sebaiknya bukan tugas reviewer manusia. Pint memeriksanya dalam hitungan detik, dan mode --test gagal dengan exit code non-zero sehingga cocok sebagai gerbang CI:
Output yang Dihasilkan:
$ vendor/bin/pint --test /tmp/ugly.php
──────────────────────────────────────────────────────────────────── Laravel
FAIL ............................................. 1 file, 1 style issue
⨯ /tmp/ugly.php blank_line_after_opening_tag, no_closing_tag, braces_positi…
$ vendor/bin/pint /tmp/ugly.php
──────────────────────────────────────────────────────────────────── Laravel
FIXED ...................................... 1 file, 1 style issue fixedBerkas /tmp/ugly.php sengaja ditulis berantakan — tag penutup ?>, spasi hilang, kurung menempel — dan Pint menolaknya; perintah kedua memperbaikinya otomatis. Aturannya lengkap di dokumentasi Pint
; pola yang sehat: pint --test wajib hijau di pipeline sebelum merge, sama seperti test.
Migrasi Maju, Deploy Kecil #
Dua irama operasional menutup daftar. Pertama, migration berjalan hanya maju: setelah di-push dan dijalankan, jangan pernah diedit — buat migrasi baru untuk perubahan berikutnya, karena mengedit migrasi lama membuat database tiap anggota tim punya sejarah schema berbeda. Kedua, deploy kecil dan sering: satu perubahan per rilis jauh lebih mudah diuji dan di-rollback daripada tumpukan dua minggu. Keduanya dibahas tuntas di chapter Database Migration Production dan Deployment Workflow .
Kesepakatan Tim yang Berpengaruh #
Terakhir, semua ini hanya hidup jika disepakati bersama. Empat kesepakatan dengan dampak terbesar: di mana logika bisnis boleh hidup (action/service, tidak pernah controller); kebijakan test minimal (setiap fitur datang dengan test); siapa yang boleh menaikkan dependency dan kapan; serta bagaimana keputusan arsitektural dicatat. Sisanya biarkan Pint dan konvensi framework yang mengurus.
Aplikasi yang mudah dirawat bukan yang paling banyak polanya, melainkan yang paling konsisten keputusannya. Dengan arsitektur dan disiplin ini di tangan, kita siap masuk ke wilayah yang belum tersentuh Course ini — dimulai dari yang paling sering diminta dunia nyata: membangun API.