BobDalgleish telah mencatat bahwa pola (anti-) ini disebut " data gelandangan ".
Dalam pengalaman saya, penyebab paling umum dari data gelandangan berlebihan adalah memiliki banyak variabel status tertaut yang harus benar-benar dienkapsulasi dalam objek atau struktur data. Kadang-kadang, bahkan mungkin perlu untuk bersarang banyak objek untuk mengatur data dengan benar.
Untuk contoh sederhana, pertimbangkan gim yang memiliki karakter pemain yang dapat disesuaikan, dengan properti seperti playerName
, playerEyeColor
dan sebagainya. Tentu saja, pemain juga memiliki posisi fisik di peta permainan, dan berbagai properti lainnya seperti, katakanlah, tingkat kesehatan saat ini dan maksimum, dan sebagainya.
Dalam iterasi pertama dari permainan seperti itu, mungkin ini merupakan pilihan yang masuk akal untuk membuat semua properti ini menjadi variabel global - lagipula, hanya ada satu pemain, dan hampir semua hal dalam permainan itu entah bagaimana melibatkan pemain. Jadi keadaan global Anda mungkin mengandung variabel seperti:
playerName = "Bob"
playerEyeColor = GREEN
playerXPosition = -8
playerYPosition = 136
playerHealth = 100
playerMaxHealth = 100
Tetapi pada titik tertentu, Anda mungkin perlu mengubah desain ini, mungkin karena Anda ingin menambahkan mode multipemain ke dalam gim. Sebagai upaya pertama, Anda bisa mencoba membuat semua variabel tersebut lokal, dan meneruskannya ke fungsi yang membutuhkannya. Namun, Anda kemudian mungkin menemukan bahwa tindakan tertentu dalam game Anda mungkin melibatkan rantai panggilan fungsi seperti, katakan:
mainGameLoop()
-> processInputEvent()
-> doPlayerAction()
-> movePlayer()
-> checkCollision()
-> interactWithNPC()
-> interactWithShopkeeper()
... dan interactWithShopkeeper()
fungsinya meminta penjaga toko memanggil pemain dengan nama, jadi Anda sekarang tiba-tiba harus lulus playerName
sebagai data gelandangan melalui semua fungsi itu. Dan, tentu saja, jika penjaga toko berpikir bahwa pemain bermata biru naif, dan akan membebankan harga yang lebih tinggi untuk mereka, maka Anda harus melewati playerEyeColor
seluruh rantai fungsi, dan sebagainya.
The tepat solusi, dalam hal ini, tentu saja untuk menentukan objek pemain yang merangkum nama, warna mata, posisi, kesehatan dan properti lainnya dari karakter pemain. Dengan begitu, Anda hanya perlu meneruskan objek tunggal itu ke semua fungsi yang melibatkan pemain.
Juga, beberapa fungsi di atas dapat secara alami dibuat menjadi metode objek pemain itu, yang secara otomatis akan memberi mereka akses ke properti pemain. Di satu sisi, ini hanyalah gula sintaksis, karena memanggil metode pada objek secara efektif melewatkan instance objek sebagai parameter tersembunyi ke metode tersebut, tetapi itu membuat kode terlihat lebih jelas dan lebih alami jika digunakan dengan benar.
Tentu saja, permainan tipikal akan memiliki lebih banyak kondisi "global" daripada hanya pemain; misalnya, Anda hampir pasti memiliki semacam peta tempat permainan berlangsung, dan daftar karakter non-pemain bergerak di peta, dan mungkin item diletakkan di situ, dan sebagainya. Anda bisa melewatkan semua itu di sekitar sebagai objek gelandangan juga, tapi itu lagi akan mengacaukan argumen metode Anda.
Alih-alih, solusinya adalah membuat objek menyimpan referensi ke objek lain yang memiliki hubungan permanen atau sementara dengannya. Jadi, misalnya, objek pemain (dan mungkin objek NPC juga) mungkin harus menyimpan referensi ke objek "dunia game", yang akan memiliki referensi ke level / peta saat ini, sehingga metode seperti player.moveTo(x, y)
tidak perlu secara eksplisit diberi peta sebagai parameter.
Demikian pula, jika karakter pemain kami memiliki, misalnya, anjing peliharaan yang mengikuti mereka, kami secara alami akan mengelompokkan semua variabel keadaan yang menggambarkan anjing menjadi satu objek, dan memberikan objek pemain referensi ke anjing (sehingga pemain dapat , katakan, panggil anjing dengan nama) dan sebaliknya (agar anjing tahu di mana pemain berada). Dan, tentu saja, kami mungkin ingin membuat pemain dan objek anjing menjadi dua subclass dari objek "aktor" yang lebih umum, sehingga kami dapat menggunakan kembali kode yang sama untuk, katakanlah, memindahkan keduanya di sekitar peta.
Ps. Meskipun saya telah menggunakan game sebagai contoh, ada beberapa jenis program lain di mana masalah seperti itu muncul juga. Namun, dalam pengalaman saya, masalah mendasar cenderung selalu sama: Anda memiliki banyak variabel terpisah (baik lokal maupun global) yang benar-benar ingin dikelompokkan bersama menjadi satu atau lebih objek yang saling terkait. Apakah "data gelandangan" yang mengganggu fungsi Anda terdiri dari pengaturan opsi "global" atau kueri basis data yang di-cache atau vektor negara dalam simulasi numerik, solusinya selalu untuk mengidentifikasi konteks alami dari data tersebut, dan menjadikannya sebagai objek (atau apa pun yang setara terdekat dalam bahasa pilihan Anda).