Tiga belas chapter sejak Memahami Class dan Object membangun kotak peralatan OOP yang lengkap — dan sekarang tibalah pertanyaan yang memisahkan programer berpengalaman dari yang bukan: kapan peralatan itu memang sebaiknya dipakai? Class bukan tujuan; class adalah alat untuk masalah tertentu. Program Python yang sehat justru penuh fungsi biasa, dan memaksakan class ke masalah yang salah menghasilkan kode yang lebih panjang, lebih lambat dibaca, dan lebih sulit diubah. Chapter penutup Section ini merangkum sinyal-sinyal kapan OOP membayar biayanya, kapan struktur lebih sederhana menang, dan bagaimana menemukan titik tengahnya.

Sinyal OOP Layak Dipakai #

Empat situasi berikut adalah sinyal klasik bahwa class akan menyelesaikan masalah, bukan menambahnya:

  • Data hidup bersama aturannya. Rekening dari Chapter Encapsulation adalah contohnya: saldo selalu harus lewat pemeriksaan setor() dan tarik(). Ketika data punya invarian yang harus dijaga di setiap perubahan, satu wadah berisi data plus method penjaga adalah bentuk paling aman.
  • Banyak bentuk dari satu interface. Sistem pinjam perpustakaan memproses Buku, Majalah, dan item lain lewat durasi_pinjam() yang sama — polymorphism dari Chapter Polymorphism menghapus percabangan tipe dari kode pemanggil.
  • State harus hidup lintas pemanggilan. Koneksi database, sesi pengguna, game loop — object menyimpan keadaan antar panggilan tanpa meneruskan belasan parameter ke setiap fungsi.
  • Ekosistem yang kita tempeli berbasis class. Framework populer di Python (Flask, Django, pytest) menyuruh kita menulis class untuk handler, model, dan test fixture. Tidak menguasai OOP berarti tidak bisa bekerja di ekosistem itu.

Ketika Fungsi dan Dictionary Cukup #

Untuk data yang hanya mengalir — dibaca, diubah, diteruskan — struktur polos sering kali pilihan terbaik:

python
buku1 = {"judul": "Laskar Pelangi", "penulis": "Andrea Hirata", "tahun": 2005}
buku2 = {"judul": "Bumi Manusia", "penulis": "Pramoedya A. Toer", "tahun": 1980}

def deskripsi(buku):
    return f"{buku['judul']} ({buku['tahun']})"

print(deskripsi(buku1))
print(deskripsi(buku2))

Output yang Dihasilkan:

text
Laskar Pelangi (2005)
Bumi Manusia (1980)

Tidak ada invarian yang dijaga, tidak ada perilaku berbeda per bentuk — dictionary plus dua fungsi menyelesaikannya dalam sepuluh baris. Kelemahannya juga jujur terlihat: key dictionary bebas salah ketik (typo judul baru ketahuan sebagai KeyError saat program berjalan), dan bentuk datanya tidak tertulis di satu tempat. Ketika kelemahan itu mulai terasa mengganggu, jangan langsung lompat ke class penuh — Python punya jalan tengahnya.

Dataclasses untuk Data Murni #

Bentuk data yang perlu dideklarasikan, tetapi tidak butuh method penjaga, pas dengan @dataclass: decorator yang otomatis menghasilkan __init__, __repr__, dan perbandingan kesetaraan dari deklarasi field:

python
from dataclasses import dataclass

@dataclass
class Buku:
    judul: str
    penulis: str
    tahun: int

buku = Buku("Laskar Pelangi", "Andrea Hirata", 2005)

print(buku)
print(buku.judul)

Output yang Dihasilkan:

text
Buku(judul='Laskar Pelangi', penulis='Andrea Hirata', tahun=2005)
Laskar Pelangi

Enam baris deklarasi menggantikan tulisan tangan constructor dan __repr__ — dan nama field yang salah ketik langsung tertangkap saat object dibuat, bukan saat data dibaca. Anotasi str dan int pada tiap field juga menjadi dokumentasi hidup; pembahasan anotasi tipe menyusul pada Section Type Hints dan Static Analysis. Dataclass adalah anggota penting keluarga alat pemodelan data — lengkapnya di chapter Dataclasses pada Section Advanced Data Modeling.

Bahaya Over-Engineering #

Sisi buruk pemakaian class yang salah tidak berisik: program tetap berjalan, hanya saja membengkak. Contoh ekstremnya mudah dikenali:

python
class Penambah:
    def tambah(self, a, b):
        return a + b

kalkulator = Penambah()

print(kalkulator.tambah(2, 3))

Output yang Dihasilkan:

text
5

Class Penambah tidak menyimpan state, tidak menjaga aturan apa pun, dan hanya membungkus satu baris return a + b. Fungsi tambah(a, b) tiga baris menggantikannya dengan lebih sedikit konsep untuk diingat. Bentuk pembengkakan yang lebih halus lebih sering muncul di dunia nyata: class dengan satu method run(), hierarki BaseHandler setinggi tiga tingkat untuk satu implementasi, atau “Manager” yang hanya meneruskan panggilan ke tempat lain.

Tabel Keputusan #

Gunakan OOP ketikaUtamakan fungsi/dictionary/dataclass ketika
Data punya invarian yang harus dijaga methodData hanya mengalir lewat fungsi
Banyak class berbagi satu interfaceLogika linier, satu arah, sekali jalan
State harus bertahan lintas pemanggilanPerhitungan murni tanpa keadaan
Framework menuntut class (handler, model, test)Skrip kecil, notebook, kode sekali pakai
Bentuk data perlu dideklarasikan, tanpa perilaku— (gunakan @dataclass, bukan class manual)

Sebagai penutup Section: dua arah lanjutan yang saling melengkapi sudah menunggu. Section Advanced Data Modeling memperdalam sisi data — chapter Properties untuk attribute terkendali, Dataclasses, hingga Special Methods dan Data Model yang membuat class kita terasa seperti class bawaan. Section Functional Programming memperkenalkan gaya sebaliknya — pure functions, immutability, dan komposisi fungsi — yang di tangan yang tepat justru paling bebas dari state. Programer Python yang matang berdiri nyaman di kedua dunia.