Membuat metode yang tidak bergantung pada bidang contoh, statis?

19

Baru-baru ini saya mulai pemrograman di Groovy untuk kerangka pengujian integrasi, untuk proyek Java. Saya menggunakan Intellij IDEA dengan plug-in Groovy dan saya terkejut melihat sebagai peringatan untuk semua metode yang tidak statis dan tidak bergantung pada bidang contoh apa pun. Di Jawa, bagaimanapun, ini bukan masalah (setidaknya dari sudut pandang IDE).

Haruskah semua metode yang tidak bergantung pada bidang instance diubah menjadi fungsi statis? Jika benar, apakah ini khusus untuk Groovy atau tersedia untuk OOP secara umum? Dan mengapa?

m3th0dman
sumber
Apakah metode ini memanggil metode contoh lain? Atau apakah mereka benar-benar tidak ada hubungannya sama sekali dengan objek kelas itu? Bisakah Anda memberi contoh?
Ray Toal

Jawaban:

26

Perhatikan bahwa IDEA memiliki inspeksi ini untuk Java juga, itu disebut Metode mungkin 'statis' ,

Inspeksi ini melaporkan setiap metode yang mungkin dibuat statis. Suatu metode mungkin statis jika tidak mereferensikan salah satu metode non-statis kelasnya dan bidang non-statis dan tidak diganti dalam subkelas ...

Masalahnya adalah bahwa untuk kode Java, inspeksi ini dimatikan secara default (programmer dapat menyalakannya atas kebijakan mereka). Alasan untuk hal ini kemungkinan besar bahwa validitas / kegunaan inspeksi semacam itu dapat ditentang, berdasarkan beberapa sumber yang cukup otoritatif.

Untuk memulainya, tutorial resmi Java agak membatasi kapan metode harus statis:

Penggunaan umum untuk metode statis adalah untuk mengakses bidang statis.

Diberikan di atas, orang dapat berargumen bahwa menyalakan secara default pemeriksaan yang disebutkan tidak sesuai dengan penggunaan pengubah statis yang disarankan di Jawa.

Selain itu, ada beberapa sumber lain yang sejauh menyarankan pendekatan yang bijaksana dalam menggunakan ide-ide yang ada di balik inspeksi ini atau bahkan mengecilkannya.

Lihat misalnya artikel Java World - Tn. Happy Object mengajarkan metode statis :

Metode apa pun yang independen dari keadaan instance adalah kandidat untuk dinyatakan sebagai statis.

Perhatikan bahwa saya mengatakan "kandidat untuk dinyatakan statis." Bahkan dalam contoh sebelumnya tidak ada yang memaksa Anda untuk menyatakan instances()sebagai statis. Mendeklarasikannya sebagai statis hanya membuatnya lebih mudah untuk memanggil karena Anda tidak perlu instance untuk memanggil metode. Terkadang Anda akan memiliki metode yang tampaknya tidak bergantung pada keadaan instance. Anda mungkin tidak ingin menjadikan metode ini statis. Bahkan Anda mungkin hanya ingin menyatakannya sebagai statis jika Anda perlu mengaksesnya tanpa instance.

Selain itu, meskipun Anda dapat mendeklarasikan metode seperti itu sebagai statis, Anda mungkin tidak ingin karena masalah warisan yang disisipkan ke dalam desain Anda. Lihatlah "Desain Berorientasi Objek Efektif" untuk melihat beberapa masalah yang akan Anda hadapi ...

Sebuah artikel di blog pengujian Google bahkan menyatakan bahwa Metode Statis adalah Kematian untuk Testabilitas :

Mari kita lakukan latihan mental. Misalkan aplikasi Anda tidak memiliki apa pun kecuali metode statis. (Ya, kode seperti itu adalah mungkin untuk ditulis, itu disebut pemrograman prosedural.) Sekarang bayangkan grafik panggilan dari aplikasi itu. Jika Anda mencoba untuk mengeksekusi metode daun, Anda tidak akan memiliki masalah pengaturan negaranya, dan menyatakan semua kasus sudut. Alasannya adalah bahwa metode daun tidak membuat panggilan lebih lanjut. Saat Anda bergerak semakin jauh dari daun dan semakin dekat ke main()metode root , akan semakin sulit untuk mengatur keadaan dalam tes Anda dan lebih sulit untuk menegaskan hal-hal. Banyak hal akan menjadi mustahil untuk ditegaskan. Tes Anda akan semakin besar. Setelah Anda mencapaimain()metode Anda tidak lagi memiliki tes unit (karena unit Anda adalah seluruh aplikasi) Anda sekarang memiliki tes skenario. Bayangkan aplikasi yang Anda coba uji adalah pengolah kata. Tidak banyak yang bisa Anda tegaskan dari metode utama ...

Terkadang metode statis adalah pabrik untuk objek lain. Ini lebih lanjut menjelaskan masalah pengujian. Dalam pengujian kami mengandalkan fakta bahwa kami dapat mentransfer objek secara berbeda menggantikan dependensi penting dengan ejekan. Setelah newoperator dipanggil, kami tidak dapat mengganti metode dengan sub-kelas. Penelepon dari pabrik statis semacam itu secara permanen terikat pada kelas beton yang diproduksi oleh metode pabrik statis. Dengan kata lain kerusakan metode statis jauh melampaui metode statis itu sendiri. Memotong-motong kabel grafik objek dan kode konstruksi menjadi metode statis sangat buruk, karena kabel grafik objek adalah cara kami mengisolasi sesuatu untuk pengujian ...


Anda lihat, mengingat di atas tampak wajar bahwa inspeksi yang disebutkan dimatikan secara default untuk Java.

Pengembang IDE akan memiliki benar-benar kesulitan menjelaskan mengapa mereka pikir itu sangat penting untuk mengaturnya secara default, terhadap rekomendasi diakui secara luas dan praktik terbaik.

Bagi Groovy, segalanya sangat berbeda. Tak satu pun dari argumen yang tercantum di atas berlaku, terutama yang tentang testability, seperti yang dijelaskan misalnya dalam Mocking Static Methods dalam artikel Groovy di Javalobby:

Jika kelas Groovy yang Anda uji membuat panggilan metode statis di kelas Groovy lain, maka Anda dapat menggunakan ExpandoMetaClass yang memungkinkan Anda menambahkan metode, konstruktor, properti, dan metode statis secara dinamis ...

Perbedaan ini kemungkinan mengapa pengaturan default untuk inspeksi yang disebutkan berlawanan di Groovy. Sementara di Java default "on" akan menjadi sumber kebingungan pengguna, di Groovy, pengaturan yang berlawanan bisa membingungkan pengguna IDE.

"Hei metode ini tidak menggunakan bidang contoh, mengapa kamu tidak memperingatkanku tentang hal itu?" Pertanyaan itu akan mudah dijawab untuk Jawa (seperti dijelaskan di atas), tetapi untuk Groovy, tidak ada penjelasan yang meyakinkan.

agas
sumber
Ngomong-ngomong, ReSharper (dibuat oleh JetBrains untuk C # / Visual Studio) menyarankan hal yang sama
Konrad Morawski
6
Ada perbedaan penting antara metode statis dengan dan tanpa efek samping. Ekstrak Google benar-benar membahas yang pertama.
assylias
@assylias Tidak, tetapi juga membahas bagaimana metode pabrik dapat membuat pengujian lebih sulit (karena itu sangat menyatukan ketergantungan dalam aplikasi). Menggunakan kerangka kerja injeksi ketergantungan adalah salah satu solusi terbaik untuk ini, dan juga memecahkan banyak masalah lainnya.
Per Lundberg
5

Sulit membayangkan bahwa ini akan membuat efek yang terlihat pada kinerja. Satu-satunya manfaat yang dapat saya lihat untuk membuatnya staticadalah memberikan indikasi visual bahwa keadaan instance tidak terpengaruh. Dengan kata lain, ini memberitahu orang yang membaca kode sumber sesuatu ... "menarik" tentang metode itu, hanya karena ada di sana. Pertanyaan sebenarnya adalah, apakah itu menjelaskan atau membingungkan? "Mengapa metode ini statis? Apakah ini metode pabrik? Apakah kemampuan untuk menyebutnya tanpa instance objek diperlukan?"

Selain itu, beberapa orang tidak suka metode statis, karena mereka mengklaim bahwa Anda tidak dapat mengejek mereka, dan karena itu mereka tidak dapat diuji, atau sesuatu di sepanjang garis itu. Tentu saja, jika Anda membuatnya statis untuk alasan biasa, seperti memberikan metode pabrik misalnya, maka saya semua untuk itu. Saya hanya tidak yakin bahwa membuat metode statis hanya karena mereka tidak menyentuh keadaan instance adalah amanah.

Robert Harvey
sumber
5
Pertimbangkan bahwa (dalam Java) metode statis tidak dapat diganti. Meskipun tidak sering menjadi masalah, itu berarti beberapa subkelas nanti tidak dapat mengubah implementasi itu. Ini bukan untuk mengatakan bahwa metode statis bukan jawaban yang tepat tetapi lebih merupakan bagian dari pertimbangan desain.
2
@ user40980 patut dipertimbangkan, benar, tetapi juga patut dipertimbangkan bahwa warisan dapat menjadi alat yang canggung yang sering disalahgunakan, dan beberapa tokoh terkemuka berpendapat bahwa semua kelas harus finalatau secara khusus dirancang dengan pewarisan dalam pikiran.
sara
3

Saya pikir ini untuk memungkinkan kemungkinan refactoring terlihat .

Setelah metode dibuat statis, jelas bahwa itu dapat dipindahkan dari kelas, katakanlah ke kelas persatuan.

Juga mudah untuk mengubahnya menjadi metode instan dari salah satu parameternya, sering kali ini adalah tempat kode seharusnya.

Ian
sumber
-1

Perhatikan bahwa Anda mungkin memiliki kelas stateless yang mengimplementasikan beberapa antarmuka (misalnya java.lang.Runnable- Anda tidak dapat membuat metodenya statis. Beberapa pola (misalnya Strategi) juga dapat menghasilkan objek stateless yang bahkan mungkin memiliki beberapa metode.

Statika adalah sepupu pertama dari lajang. Akan sangat sulit untuk beralih dari statika ke non statika pada titik selanjutnya - jadi ketika Anda perlu menambahkan status Anda akan tergoda untuk mulai memperkenalkan variabel statis.

Eugene
sumber
bagaimana ini menjawab pertanyaan yang diajukan?
nyamuk
1
mengapa sulit untuk beralih dari tidak ada negara ke negara lain? Saya akan mengatakan sebaliknya. lebih mudah mencemari sesuatu yang murni daripada memurnikan sesuatu yang terkontaminasi.
sara