Ide dasar di balik OOP adalah bahwa data dan perilaku (berdasarkan data itu) tidak dapat dipisahkan dan mereka digabungkan oleh gagasan objek kelas. Objek memiliki data dan metode yang bekerja dengan itu (dan data lainnya). Jelas dengan prinsip-prinsip OOP, objek yang hanya data (seperti C struct) dianggap sebagai anti-pola.
Sejauh ini bagus.
Masalahnya adalah saya telah memperhatikan bahwa kode saya tampaknya akan semakin ke arah pola-anti ini akhir-akhir ini. Tampak bagi saya bahwa semakin saya mencoba untuk mendapatkan informasi yang bersembunyi di antara kelas-kelas dan desain yang digabungkan secara longgar, semakin banyak kelas saya yang menjadi campuran data murni tanpa kelas perilaku dan semua perilaku tanpa kelas data.
Saya biasanya merancang kelas dengan cara yang meminimalkan kesadaran mereka tentang keberadaan kelas lain dan meminimalkan pengetahuan mereka tentang antarmuka kelas lain. Saya terutama menegakkan ini dengan cara top-down, kelas tingkat bawah tidak tahu tentang kelas tingkat yang lebih tinggi. Misalnya:
Misalkan Anda memiliki API permainan kartu umum. Anda memiliki kelas Card
. Sekarang Card
kelas ini perlu menentukan visibilitas ke pemain.
Salah satunya adalah dengan memiliki boolean isVisible(Player p)
di Card
kelas.
Lain adalah memiliki boolean isVisible(Card c)
di Player
kelas.
Saya tidak menyukai pendekatan pertama khususnya karena memberikan pengetahuan tentang Player
kelas tingkat yang lebih tinggi ke kelas tingkat yang lebih rendah Card
.
Sebagai gantinya saya memilih opsi ketiga di mana kita memiliki Viewport
kelas yang, diberikan Player
dan daftar kartu menentukan kartu mana yang terlihat.
Namun pendekatan ini merampas baik Card
dan Player
kelas dari fungsi anggota yang mungkin. Setelah Anda melakukan ini untuk hal-hal lain selain visibilitas kartu, Anda dibiarkan dengan Card
dan Player
kelas - kelas yang berisi data murni karena semua fungsi diimplementasikan di kelas-kelas lain, yang sebagian besar kelas tanpa data, hanya metode, seperti di Viewport
atas.
Ini jelas bertentangan dengan gagasan utama OOP.
Mana cara yang benar? Bagaimana saya harus pergi tentang tugas meminimalkan interdependensi kelas dan meminimalkan asumsi pengetahuan dan penggabungan, tetapi tanpa menutup dengan desain aneh di mana semua kelas tingkat rendah hanya berisi data dan kelas tingkat tinggi berisi semua metode? Adakah yang punya solusi atau perspektif ketiga tentang desain kelas yang menghindari seluruh masalah?
PS Berikut contoh lain:
Misalkan Anda memiliki kelas DocumentId
yang tidak berubah, hanya memiliki satu BigDecimal id
anggota dan pengambil untuk anggota ini. Sekarang Anda perlu memiliki metode di suatu tempat, yang memberikan DocumentId
pengembalian Document
untuk id ini dari database.
Apakah kamu:
- Tambahkan
Document getDocument(SqlSession)
metode keDocumentId
kelas, tiba-tiba memperkenalkan pengetahuan tentang kegigihan Anda ("we're using a database and this query is used to retrieve document by id"
), API yang digunakan untuk mengakses DB dan sejenisnya. Juga kelas ini sekarang membutuhkan file JAR persistensi hanya untuk mengkompilasi. - Tambahkan beberapa kelas lain dengan metode
Document getDocument(DocumentId id)
, meninggalkanDocumentId
kelas sebagai mati, tidak ada perilaku, kelas struct-seperti.