Saya sedang mengerjakan proyek solo yang lebih besar dan sekarang, dan saya memiliki beberapa kelas di mana saya tidak melihat alasan untuk membuat instance.
Kelas dadu saya sekarang, misalnya, menyimpan semua datanya secara statis dan semua metodenya juga statis. Saya tidak perlu menginisialisasi karena ketika saya ingin melempar dadu dan mendapatkan nilai baru, saya hanya menggunakan Dice.roll()
.
Saya memiliki beberapa kelas serupa yang hanya memiliki satu fungsi utama seperti ini dan saya akan mulai bekerja pada semacam kelas "pengontrol" yang akan bertanggung jawab atas semua acara (seperti ketika seorang pemain bergerak, dan giliran apa saat ini) Yaitu) dan saya telah menemukan bahwa saya dapat mengikuti ide yang sama untuk kelas ini. Saya tidak pernah berencana membuat beberapa objek untuk kelas-kelas khusus ini, jadi apakah itu ide yang buruk untuk membuat mereka sepenuhnya statis?
Saya bertanya-tanya apakah ini dianggap "praktik buruk" ketika datang ke Jawa. Dari apa yang saya lihat, komunitas sepertinya agak terpecah pada topik ini? Bagaimanapun, saya akan senang berdiskusi tentang hal ini dan tautan ke sumber daya juga akan bagus!
Jawaban:
Tidak ada yang salah dengan kelas statis yang benar-benar statis . Artinya, tidak ada keadaan internal untuk dibicarakan yang akan menyebabkan output dari metode berubah.
Jika
Dice.roll()
hanya mengembalikan nomor acak baru dari 1 ke 6, itu tidak mengubah keadaan. Memang, Anda mungkin berbagiRandom
contoh, tapi saya tidak akan menganggap bahwa perubahan status secara definisi, output akan selalu baik, acak. Ini juga thread-safe sehingga tidak ada masalah di sini.Anda akan sering melihat "Pembantu" akhir atau kelas utilitas lain yang memiliki konstruktor pribadi dan anggota statis. Konstruktor pribadi tidak mengandung logika dan berfungsi hanya untuk mencegah seseorang membuat instance kelas. Pengubah akhir hanya membawa pulang ide ini bahwa ini bukan kelas yang ingin Anda dapatkan. Ini hanyalah kelas utilitas. Jika dilakukan dengan benar, seharusnya tidak ada anggota tunggal atau anggota kelas lain yang tidak statis dan final.
Selama Anda mengikuti pedoman ini dan Anda tidak membuat lajang, sama sekali tidak ada yang salah dengan ini. Anda menyebutkan kelas controller, dan ini hampir pasti akan memerlukan perubahan keadaan, jadi saya akan menyarankan agar tidak menggunakan metode statis saja. Anda dapat sangat bergantung pada kelas utilitas statis, tetapi Anda tidak dapat membuatnya menjadi kelas utilitas statis.
Apa yang dianggap sebagai perubahan status untuk suatu kelas? Baiklah, mari kita singkirkan angka acak selama sedetik, karena mereka tidak ditentukan oleh definisi dan karenanya nilai pengembalian sering berubah.
Fungsi murni adalah fungsi yang deterministik, artinya, untuk input yang diberikan, Anda akan mendapatkan satu dan tepat satu output. Anda ingin metode statis menjadi fungsi murni. Di Jawa ada cara untuk mengubah perilaku metode statis untuk mempertahankan keadaan, tetapi mereka hampir tidak pernah merupakan ide yang baik. Ketika Anda mendeklarasikan suatu metode sebagai statis , programmer umumnya akan langsung menganggap bahwa itu adalah fungsi murni. Menyimpang dari perilaku yang diharapkan adalah bagaimana Anda cenderung membuat bug di program Anda, secara umum dan harus dihindari.
Singleton adalah kelas yang berisi metode statis tentang kebalikan dari "fungsi murni" yang Anda bisa. Seorang anggota pribadi statis tunggal disimpan secara internal ke kelas yang digunakan untuk memastikan ada satu contoh. Ini bukan praktik terbaik dan dapat membuat Anda kesulitan nanti karena sejumlah alasan. Untuk mengetahui apa yang sedang kita bicarakan, berikut adalah contoh sederhana dari singleton:
sumber
Dice.roll()
bukan pengecualian yang valid untuk aturan "no global state".random.nextInt(6) + 1
. ;)RollAndMove()
menggulung lagi ketika kita memasok enam ganda, maka cara termudah, paling kuat untuk melakukannya adalah dengan mengejek salah satuDice
atau nomor acak generator. Ergo,Dice
tidak ingin menjadi kelas statis menggunakan generator acak statis.Untuk memberikan contoh keterbatasan
static
kelas, bagaimana jika beberapa gamer Anda ingin mendapatkan sedikit bonus pada gulungan mereka? Dan mereka bersedia membayar mahal! :-)Ya, Anda bisa menambahkan parameter lain, jadi
Dice.roll(bonus)
,Kemudian Anda membutuhkan D20s.
Dice.roll(bonus, sides)
Ya, tetapi beberapa pemain memiliki prestasi "sangat mampu" sehingga mereka tidak akan pernah bisa "gagal" (roll 1).
Dice.roll(bonus, sides, isFumbleAllowed)
.Ini semakin berantakan, bukan?
sumber
new Dice().roll(...)
harus dianggap sebagai akses statis jugaDice.roll(...)
. Kami hanya mendapat manfaat jika kami menyuntikkan ketergantungan itu.static
kekacauan terjadi dalam setiap panggilan, dan pengetahuan yang diperlukan diperlukan dalam setiap panggilan, sehingga akan tersebar secara global ke seluruh aplikasi Anda. Dalam struktur OOP, hanya konstruktor / pabrik yang perlu berantakan, dan detail yang mati dirangkum. Setelah itu, gunakan polimorfisme dan panggil sajaroll()
. Saya mungkin mengedit jawaban ini untuk menjelaskan.Dalam kasus tertentu dari kelas Dice saya pikir menggunakan metode instance daripada statika akan membuat pengujian secara signifikan lebih mudah.
Jika Anda ingin menguji sesuatu yang menggunakan instance Dice (misalnya kelas Game), maka dari pengujian Anda, Anda dapat menyuntikkan beberapa bentuk uji ganda Dice yang selalu mengembalikan urutan nilai yang tetap. Tes Anda dapat memeriksa apakah permainan memiliki hasil yang tepat untuk gulungan dadu tersebut.
Saya bukan pengembang Java, tetapi saya pikir akan jauh lebih sulit untuk melakukannya dengan kelas Dice yang sepenuhnya statis. Lihat /programming/4482315/why-does-mockito-not-mock-static-methods
sumber
Ini sebenarnya dikenal sebagai pola Monostate , di mana setiap instance (dan bahkan "no-instance") berbagi status mereka. Setiap anggota adalah anggota kelas (yaitu, tidak ada anggota contoh). Mereka biasanya digunakan untuk mengimplementasikan kelas "toolkit" yang menggabungkan satu set metode dan konstanta yang terkait dengan satu tanggung jawab atau persyaratan tetapi tidak memerlukan status untuk bekerja (mereka murni fungsional). Bahkan, Java dilengkapi dengan beberapa dari mereka yang dibundel (misalnya, Matematika ).
Agak di luar topik: Saya jarang setuju dengan penamaan kata kunci di VisualBasic, tetapi dalam kasus ini, saya pikir
shared
tentu saja lebih jelas dan semantik lebih baik ( dibagikan di antara kelas itu sendiri dan semua contohnya) daripadastatic
(tetap setelah siklus hidup dari ruang lingkup yang dideklarasikan dalam).sumber