Jika Anda ingin refactor kecil di proyek CodeIgniter 4 berjalan konsisten tanpa menunggu review manual, pre-commit Rector adalah pendekatan yang masuk akal. Ide utamanya sederhana: sebelum kode masuk ke repository, hook Git menjalankan Rector pada file yang berubah untuk menerapkan refactor aman, misalnya modernisasi syntax PHP dan cleanup sederhana.
Pendekatan ini bukan pengganti formatter atau static analysis. Rector cocok untuk mengubah kode, PHP CS Fixer untuk merapikan style, dan PHPStan untuk menemukan potensi bug. Jika dipakai bersama dengan scope yang dibatasi, workflow ini membantu menjaga codebase tetap rapi tanpa membuat proses commit terasa berat.
Kapan Rector berguna dibanding PHP CS Fixer dan PHPStan
Rector: mengubah struktur kode secara otomatis
Rector berguna saat Anda ingin otomatisasi refactor yang sifatnya mekanis dan berulang. Contohnya:
- Mengubah syntax lama ke syntax PHP yang lebih modern dan aman dibaca.
- Merapikan pola kode sederhana yang bisa ditransformasi dengan aturan yang jelas.
- Mengurangi pekerjaan review untuk perubahan yang seharusnya bisa dilakukan tool.
Rector bekerja pada level AST (abstract syntax tree), jadi ia memahami struktur kode, bukan sekadar mencari dan mengganti teks.
PHP CS Fixer: formatting dan style
PHP CS Fixer dipakai untuk konsistensi format, seperti penataan spasi, import, trailing comma, atau gaya penulisan array. Ia penting, tetapi bukan alat refactor struktural. Jika tujuan Anda adalah perubahan style tanpa mengubah perilaku program, gunakan PHP CS Fixer.
PHPStan: analisis statis untuk mendeteksi masalah
PHPStan tidak memodifikasi kode. Ia menganalisis tipe, alur data, pemanggilan method, nullability, dan berbagai potensi bug lain. Tool ini sangat cocok dijalankan di CI atau lokal sebelum push, tetapi tidak menyelesaikan kebutuhan refactor otomatis.
Pola kerja yang sehat
Untuk proyek CodeIgniter 4, pembagian tanggung jawab yang umum dan aman adalah:
- Rector: refactor aman dan modernisasi syntax.
- PHP CS Fixer: format dan style.
- PHPStan: validasi kualitas dan potensi bug.
Jika pre-commit terasa lambat, prioritaskan Rector hanya untuk file yang di-stage. Jalankan pemeriksaan penuh di CI agar kualitas tetap terjaga.
Setup dependency dev untuk CodeIgniter 4
Pasang dependency sebagai dev dependency agar tidak ikut ke environment produksi. Minimal Anda membutuhkan Rector. Untuk hook Git, pilih salah satu: Husky atau CaptainHook.
Dependency dasar dengan Composer
composer require --dev rector/rectorJika Anda juga memakai formatter dan static analysis dalam workflow yang sama, dependency terpisah bisa ditambahkan sesuai kebutuhan. Namun untuk fokus artikel ini, kita batasi ke Rector dan integrasi hook.
Pilihan integrasi hook
Ada dua pendekatan umum:
- Husky: populer di tim yang sudah memakai Node.js tooling, misalnya untuk frontend, lint-staged, atau commit workflow lain.
- CaptainHook: lebih natural untuk ekosistem PHP karena hook dikelola dari dependency proyek PHP.
Jika proyek CodeIgniter 4 Anda murni PHP dan tidak memakai Node.js, CaptainHook biasanya lebih ringan secara operasional. Jika repository sudah punya toolchain JavaScript, Husky sering lebih mudah diterima karena satu pola untuk semua hook.
Konfigurasi dasar Rector untuk refactor aman
Target pre-commit sebaiknya konservatif. Jangan langsung mengaktifkan aturan besar yang mengubah arsitektur atau kontrak API. Fokus pada modernisasi syntax PHP dan cleanup sederhana yang relatif aman untuk dijalankan sering.
Contoh file konfigurasi rector.php
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([
__DIR__ . '/app',
__DIR__ . '/tests',
]);
$rectorConfig->skip([
__DIR__ . '/vendor',
__DIR__ . '/writable',
__DIR__ . '/public',
]);
$rectorConfig->sets([
SetList::CODE_QUALITY,
SetList::DEAD_CODE,
]);
$rectorConfig->phpVersion(\Rector\ValueObject\PhpVersion::PHP_80);
};Catatan penting:
- Batasi path ke
appdantests. Ini biasanya cukup untuk target CodeIgniter 4. - Skip directory yang tidak relevan agar hook tetap cepat.
- Pilih set secara konservatif. Jangan langsung menyalakan semua aturan upgrade atau framework-specific rule tanpa review.
- PHP version harus disesuaikan dengan versi PHP minimal yang benar-benar dipakai proyek Anda.
Mengapa konfigurasi konservatif lebih aman
Rector bisa sangat kuat, tetapi kekuatan itu juga berarti ada risiko perubahan yang terlalu agresif. Pada tahap awal adopsi, tujuan utama bukan mengejar transformasi sebanyak mungkin, melainkan memastikan hasil refactor:
- mudah diprediksi,
- mudah direview di diff,
- tidak memperlambat commit harian,
- tidak mengejutkan anggota tim.
Contoh target refactor pada controller, service, dan test
Di bawah ini bukan daftar semua rule Rector, melainkan contoh area yang cocok menjadi target pre-commit karena manfaatnya jelas dan risikonya relatif rendah.
Controller: cleanup dan modernisasi syntax sederhana
<?php
namespace App\Controllers;
use App\Services\UserService;
use CodeIgniter\Controller;
class UserController extends Controller
{
public function show(int $id)
{
$service = new UserService();
if ($id === 0) {
return redirect()->to('/users');
}
$user = $service->findById($id);
if ($user === null) {
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound();
}
return view('users/show', ['user' => $user]);
}
}Pada kode semacam ini, Rector cocok untuk cleanup aman seperti menyederhanakan pola tertentu, menghapus kode mati sederhana, atau membantu modernisasi syntax. Namun ia tidak boleh dipaksa mengambil keputusan desain seperti mengganti cara dependency di-instantiate jika proyek Anda belum punya pola DI yang konsisten.
Service: refactor kecil yang berulang
<?php
namespace App\Services;
class InvoiceService
{
public function normalizeStatus(?string $status): string
{
return $status ?? 'draft';
}
}Pada kelas service, Rector sering berguna untuk transformasi syntax yang berulang di banyak file. Misalnya penyederhanaan ekspresi yang ekuivalen secara perilaku. Ini mengurangi noise saat developer melakukan perubahan domain yang sebenarnya kecil.
Test: menjaga test suite tetap konsisten
<?php
namespace Tests\Unit\Services;
use App\Services\InvoiceService;
use CodeIgniter\Test\CIUnitTestCase;
class InvoiceServiceTest extends CIUnitTestCase
{
public function testNormalizeStatusReturnsDraftWhenNull(): void
{
$service = new InvoiceService();
$this->assertSame('draft', $service->normalizeStatus(null));
}
}Folder tests adalah target yang baik untuk Rector karena perubahan syntax di test umumnya lebih aman. Selain itu, test yang rapi mempercepat review dan mempermudah migrasi bertahap.
Menjalankan Rector hanya pada file yang di-stage
Kunci agar pre-commit tidak mengganggu flow harian adalah scope yang sempit. Jangan jalankan Rector ke seluruh proyek pada setiap commit. Jalankan hanya pada file PHP yang sedang di-stage.
Pendekatan umum
- Ambil daftar file yang di-stage dari Git.
- Filter hanya file berekstensi
.php. - Batasi ke path yang relevan, misalnya
app/dantests/. - Jalankan Rector pada daftar file tersebut.
- Tambahkan kembali file yang diubah oleh Rector ke staging area.
Contoh script shell sederhana
#!/bin/sh
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '^(app|tests)/.*\.php$')
if [ -z "$FILES" ]; then
exit 0
fi
vendor/bin/rector process $FILES --no-progress-bar
STATUS=$?
if [ $STATUS -ne 0 ]; then
echo "Rector gagal. Periksa output di atas."
exit $STATUS
fi
printf '%s\n' "$FILES" | xargs git add
Script ini menunjukkan pola kerja yang penting: file yang diubah otomatis oleh Rector harus di-stage ulang, jika tidak commit bisa berisi versi lama.
Integrasi Git hook dengan Husky
Jika repository Anda sudah memakai Node.js tooling, Husky bisa menjadi pilihan yang praktis.
Contoh alur integrasi
- Pasang Husky di repository.
- Buat hook
pre-commit. - Panggil script shell yang menjalankan Rector pada file staged.
npx husky initLalu isi file hook pre-commit dengan pemanggilan script proyek, misalnya:
./tools/pre-commit-rector.shKeuntungan Husky:
- Cocok jika tim sudah akrab dengan hook berbasis Node.js.
- Mudah digabung dengan linting frontend atau commit workflow lain.
Kekurangannya:
- Menambah dependency dan runtime tambahan untuk proyek PHP murni.
- Butuh konsistensi environment lokal jika sebagian developer tidak memasang tool Node.js.
Integrasi Git hook dengan CaptainHook
Untuk tim PHP-first, CaptainHook sering terasa lebih natural karena dikelola dari ekosistem PHP.
Contoh pendekatan konfigurasi
Pasang package CaptainHook sebagai dev dependency, lalu definisikan action pre-commit untuk memanggil script yang sama. Struktur pastinya dapat mengikuti dokumentasi resmi package yang Anda gunakan, tetapi prinsipnya tetap:
- Hook tidak perlu mengetahui detail Rector.
- Logika filter file staged disimpan di script proyek agar mudah dirawat.
- Tool hook hanya menjadi pemicu.
Keuntungan CaptainHook:
- Lebih konsisten untuk proyek berbasis Composer.
- Tidak bergantung pada Node.js jika memang tidak dibutuhkan.
Kekurangannya:
- Kurang familiar di tim yang sudah menstandardkan Husky di semua repository.
Membatasi scope agar hook tetap cepat
Masalah paling umum pada pre-commit Rector bukan akurasi, melainkan performa dan gangguan pada ritme kerja developer. Beberapa strategi berikut biasanya cukup efektif:
1. Proses hanya file staged
Ini aturan paling penting. Menjalankan Rector ke seluruh codebase pada setiap commit hampir selalu terasa terlalu berat.
2. Batasi path
Fokus pada app dan tests. Hindari memproses direktori build, cache, public asset, atau generated code.
3. Mulai dari rule yang aman
Semakin agresif ruleset, semakin besar kemungkinan waktu proses bertambah dan diff menjadi sulit direview.
4. Pisahkan mode lokal dan mode CI
Lokal untuk file staged saja. CI untuk full run pada seluruh project.
5. Hindari terlalu banyak tool berat di pre-commit
Jika pre-commit sudah menjalankan Rector, formatter, test, dan static analysis penuh sekaligus, developer cenderung mencari cara untuk melewati hook. Itu tanda workflow perlu disederhanakan.
Strategi menjalankan cek penuh di CI
Pre-commit sebaiknya dianggap sebagai filter cepat, bukan satu-satunya lapisan kualitas. Di CI, jalankan pemeriksaan yang lebih lengkap:
- Rector pada seluruh path target untuk memastikan tidak ada file yang terlewat.
- PHPStan untuk analisis statis.
- Formatter atau style checker untuk konsistensi style.
- Test suite sesuai tingkat kepercayaan yang dibutuhkan.
Mode CI yang umum
Untuk CI, banyak tim memilih mode dry-run atau mode yang membuat pipeline gagal jika ada perubahan yang seharusnya diterapkan. Dengan begitu, CI bertindak sebagai pagar terakhir tanpa diam-diam mengubah kode di branch build.
Prinsip yang aman: lokal boleh memperbaiki otomatis, CI sebaiknya memverifikasi dan gagal jika ada deviasi.
Risiko false positive, keterbatasan, dan cara menguranginya
False positive tetap mungkin terjadi
Walaupun Rector memahami struktur kode, tidak semua transformasi aman untuk semua codebase. Risiko muncul terutama jika proyek memiliki pola dinamis, magic method, convention internal, atau integrasi framework yang bergantung pada perilaku implisit.
Keterbatasan yang perlu diingat
- Rector tidak memahami seluruh niat bisnis di balik kode.
- Transformasi yang tampak valid secara syntax belum tentu sesuai kontrak internal proyek.
- Kode dengan refleksi, proxy, atau pola meta-programming lebih rentan terhadap perubahan yang tidak diinginkan.
Cara mengurangi risiko
- Mulai dari ruleset konservatif.
- Jalankan pada area yang ter-cover test.
- Review diff hasil refactor, jangan langsung commit tanpa melihat perubahan.
- Tambahkan
skipuntuk file atau folder yang sering bermasalah. - Gunakan CI untuk memverifikasi bahwa perubahan otomatis tidak merusak perilaku aplikasi.
Cara review diff hasil refactor otomatis
Salah satu kesalahan umum adalah menganggap hasil Rector selalu benar lalu langsung commit. Praktik yang lebih aman:
- Jalankan Rector di pre-commit.
- Lihat diff sebelum commit final.
- Pastikan perubahan hanya bersifat mekanis dan tidak mengubah maksud kode.
- Jika ada refactor yang terasa terlalu agresif, tambahkan pengecualian di konfigurasi.
Apa yang perlu dicek saat review diff
- Apakah perubahan hanya syntax dan cleanup sederhana?
- Apakah ada perubahan pada perilaku null handling, perbandingan, atau casting?
- Apakah file test ikut menyesuaikan secara masuk akal?
- Apakah perubahan membuat code review domain menjadi lebih sulit karena tercampur noise?
Jika jawabannya ya pada poin terakhir, pertimbangkan untuk memisahkan commit refactor otomatis dari commit perubahan fitur.
Checklist adopsi tim agar tidak mengganggu flow commit harian
Agar pre-commit Rector diterima tim, fokuslah pada adopsi bertahap.
Checklist praktis
- Sepakati tujuan: hook dipakai untuk refactor kecil dan aman, bukan migrasi besar.
- Batasi rule awal: mulai dari modernisasi syntax dan cleanup sederhana.
- Proses hanya file staged: jangan seluruh codebase.
- Dokumentasikan cara bypass darurat: misalnya saat debugging hook bermasalah, dengan catatan penggunaan harus jarang dan jelas.
- Pisahkan validasi penuh ke CI: jangan semua beban diletakkan di lokal.
- Review diff tetap wajib: hasil otomatis bukan berarti bebas audit.
- Tambahkan skip list: untuk area sensitif, generated code, atau folder legacy tertentu.
- Mulai dari satu repository: ukur dampak ke kecepatan commit sebelum diterapkan lebih luas.
Rekomendasi workflow yang realistis untuk CodeIgniter 4
Jika Anda ingin mulai tanpa banyak risiko, workflow berikut cukup seimbang:
- Pasang Rector sebagai dev dependency.
- Buat
rector.phpdengan pathappdantests, plus set yang konservatif. - Buat script pre-commit yang hanya memproses file PHP staged.
- Integrasikan script ke Husky atau CaptainHook sesuai toolchain tim.
- Di CI, jalankan Rector untuk seluruh target dalam mode verifikasi, lalu jalankan PHPStan dan test.
- Evaluasi diff selama beberapa sprint sebelum menambah ruleset.
Dengan pola ini, CodeIgniter 4 pre-commit Rector memberi manfaat nyata: refactor kecil terjadi lebih konsisten, review menjadi lebih fokus pada logika bisnis, dan codebase bergerak ke arah yang lebih rapi tanpa mengubah flow commit harian secara drastis.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!