
Pendahuluan
Bayangin lagi ngerjain fitur sederhana, tapi pas buka controller malah nemu tumpukan validasi email atau format telepon yang berceceran di mana-mana. Saya sering banget ngalamin kondisi di mana satu logic validasi yang sama harus dicopy-paste ke tiga tempat berbeda, dan pas ada perubahan format, semuanya jadi berantakan. Di sinilah Value Objects menyelamatkan kewarasan saya; dia bukan sekadar penampung data, tapi cara kita membungkus aturan main suatu nilai agar nggak bisa diubah sembarangan.
Tips & Best Practices
- Di banyak project, biasanya saya mulai dari membuat class yang immutable agar nilai di dalamnya tidak berubah setelah diinisiasi, jadi kita nggak perlu pusing ngecek state object di tengah jalan.
- Pas lagi handling domain logic, saya selalu berusaha bikin static factory method seperti
fromNative()supaya proses pembuatan object terasa lebih natural dibanding manggilnew Class()berulang kali. - Kalau project mulai besar, saya selalu pisahin Value Objects ke namespace khusus seperti
App\Domain\ValueObjectsbiar struktur folder nggak tercampur aduk sama model Laravel yang lain.
Contoh Kode
Daripada ngolah string mentah di controller, mending kita bikin class khusus seperti ini:
readonly class EmailAddress { public function __construct(public string $value) { if (!filter_var($value, FILTER_VALIDATE_EMAIL)) throw new InvalidArgumentException('Email ngaco!'); } }Nanti tinggal pakai di model atau service: $user->email = new EmailAddress($request->email);. Kelihatan jauh lebih bersih, kan?
Variasi Implementasi
Ada dua pendekatan yang sering saya pakai. Pertama, pakai PHP 8.2 readonly class yang simpel banget dan performant. Kedua, pakai Laravel Casts, di mana kita nge-bind Value Object langsung ke atribut Eloquent. Kalau butuh validasi yang ketat di database, pakai Casts lebih enak karena transparan di level model. Tapi kalau cuma buat internal logic service, class murni (POPO) sudah lebih dari cukup dan nggak bikin ketergantungan sama framework.
Kesalahan Umum
- Lupa bikin class-nya immutable, jadi malah ke-modify pas di tengah proses.
- Isi logic terlalu berat sampai si Value Object malah berubah jadi mini-service yang kompleks.
- Mencoba masukin semua validasi ke constructor padahal validasinya butuh akses ke database (ingat, Value Object harusnya murni logic lokal).
- Lupa nambahin method
equals()untuk ngebandingin dua object yang kontennya sama tapi instance-nya beda. - Terlalu antusias sampai semua tipe data dibikin jadi Value Object, padahal buat data sepele kayak integer biasa, itu cuma nambahin boilerplate yang nggak perlu.
Ringkasan
Intinya, Value Objects itu soal gimana kita bikin kode yang bisa 'menjaga dirinya sendiri'. Dengan bungkus nilai ke dalam object, kita nggak lagi perlu khawatir soal format data yang nggak valid masuk ke core business kita. Awalnya emang kerasa nambahin pekerjaan di depan, tapi pas project udah skala gede, teknik ini yang bikin saya bisa tidur nyenyak tanpa takut ada bug format data yang aneh-aneh.
Komentar
Posting Komentar