Saya mengajukan pertanyaan ini karena saya percaya mereka melakukannya untuk alasan yang sangat bagus dan kebanyakan orang tidak menggunakannya dengan benar, baik dari pengalaman saya di industri sejauh ini. Tetapi jika teori saya benar maka saya tidak yakin mengapa mereka memasukkan pengubah akses pribadi ...?
Saya percaya bahwa jika akses standar digunakan dengan benar itu memberikan peningkatan kemampuan uji coba sambil mempertahankan enkapsulasi. Dan itu juga menjadikan pengubah akses pribadi berlebihan.
Pengubah akses default dapat digunakan untuk memberikan pengaruh yang sama dengan menggunakan paket unik untuk metode yang perlu disembunyikan dari seluruh dunia, dan ia melakukan ini tanpa mengurangi testabilitas, seperti paket dalam folder uji, dengan paket yang sama. dapat mengakses semua metode default yang dinyatakan dalam folder sumber.
Saya percaya ini sebabnya Java menggunakan akses paket sebagai 'default'. Tapi saya tidak yakin mengapa mereka juga termasuk akses pribadi, saya yakin ada kasus penggunaan yang valid ...
Jawaban:
Saya kira mereka memiliki ide bagus tentang apa yang akan dilakukan oleh programmer biasa. Dan dengan rata-rata programmer yang saya maksud adalah orang yang tidak benar-benar pandai pemrograman, tetapi tetap mendapatkan pekerjaan karena tidak ada yang cukup bagus dan harganya mahal.
Jika mereka membuat "publik" mengakses yang default, kebanyakan programmer tidak akan pernah repot-repot menggunakan yang lain. Hasilnya akan banyak kode spaghetti di mana-mana. (Karena jika Anda secara teknis diizinkan untuk memanggil sesuatu dari mana saja, mengapa pernah repot-repot merangkum beberapa logika dalam suatu metode?)
Menjadikan "pribadi" akses default hanya akan sedikit lebih baik. Kebanyakan programmer pemula hanya akan menciptakan (dan berbagi di blog mereka) aturan praktis bahwa "Anda perlu menulis 'publik' di mana-mana", dan kemudian mereka akan mengeluh mengapa Jawa begitu buruk sehingga memaksa mereka untuk menulis "publik" di mana-mana. Dan mereka juga akan menghasilkan banyak kode spageti.
Akses paket adalah sesuatu yang memungkinkan pemrogram untuk menggunakan teknik pemrograman ceroboh mereka saat menulis kode dalam satu paket, tetapi kemudian mereka harus mempertimbangkannya ketika membuat lebih banyak paket. Ini adalah kompromi antara praktik bisnis yang baik dan kenyataan buruk. Seperti: tulis beberapa kode spageti, jika Anda bersikeras, tapi tolong tinggalkan kekacauan yang jelek di dalam paket; setidaknya buat beberapa antarmuka yang lebih bagus di antara paket-paket.
Mungkin ada alasan lain juga, tapi saya tidak akan meremehkan yang ini.
sumber
Akses default tidak membuat pengubah akses pribadi menjadi berlebihan.
Posisi desainer bahasa yang tercermin dalam tutorial resmi - Mengontrol Akses ke Anggota Kelas dan itu cukup jelas (untuk kenyamanan Anda, pernyataan yang relevan dalam kutipan dibuat tebal ):
Daya tarik Anda terhadap testabilitas sebagai pembenaran untuk sepenuhnya menjatuhkan pengubah pribadi adalah salah, seperti dibuktikan misalnya dengan jawaban di New to TDD. Haruskah saya menghindari metode pribadi sekarang?
Posisi desainer bahasa pada tujuan dan penggunaan akses tingkat paket dijelaskan dalam tutorial resmi lain, Membuat dan Menggunakan Paket dan tidak ada kesamaan dengan ide menjatuhkan pengubah pribadi (untuk kenyamanan Anda, pernyataan yang relevan dalam kutipan dibuat tebal ) :
<Kata kasar "Kurasa aku sudah cukup banyak mendengar rengekan. Sepertinya sudah waktunya untuk mengatakan dengan keras dan jelas ...">
Metode pribadi bermanfaat untuk pengujian unit.
Catatan di bawah ini mengasumsikan bahwa Anda terbiasa dengan cakupan kode . Jika tidak, luangkan waktu untuk belajar, karena itu cukup berguna bagi mereka yang tertarik dalam pengujian unit dan pengujian sama sekali.
Baiklah, jadi saya punya metode pribadi dan tes unit, dan analisis cakupan memberi tahu saya bahwa ada celah, metode pribadi saya tidak dicakup oleh tes. Sekarang...
Apa yang saya peroleh dari merahasiakannya
Karena metode bersifat pribadi, satu-satunya cara untuk melanjutkan adalah mempelajari kode untuk mempelajari cara menggunakannya melalui API non-pribadi. Biasanya, penelitian semacam itu mengungkapkan bahwa alasan untuk kesenjangan adalah bahwa skenario penggunaan tertentu tidak ada dalam tes.
Demi kelengkapan, alasan lain (kurang sering) untuk kesenjangan cakupan ini bisa berupa bug dalam spesifikasi / desain. Saya tidak akan terjun jauh ke sini di sini, untuk menjaga hal-hal sederhana; Cukuplah untuk mengatakan bahwa jika Anda melemahkan batasan akses "hanya untuk membuat metode dapat diuji", Anda akan kehilangan kesempatan untuk mengetahui bahwa bug ini ada sama sekali.
Baik, untuk memperbaiki kesenjangan, saya menambahkan unit test untuk skenario yang hilang, ulangi analisis cakupan dan verifikasi bahwa celah itu hilang. Apa yang saya miliki sekarang? Saya telah mendapatkan sebagai unit test baru untuk penggunaan khusus API non-pribadi.
Tes baru memastikan bahwa perilaku yang diharapkan untuk penggunaan ini tidak akan berubah tanpa pemberitahuan karena jika itu berubah, tes akan gagal.
Pembaca dari luar dapat melihat ke tes ini dan belajar bagaimana seharusnya menggunakan dan berperilaku (di sini, pembaca dari luar mencakup diri saya di masa depan, karena saya cenderung melupakan kode satu atau dua bulan setelah saya selesai dengan itu).
Tes baru toleran terhadap refactoring (apakah saya refactor metode pribadi? Anda bertaruh!) Apa pun yang saya lakukan
privateMethod
, saya selalu ingin mengujinonPrivateMethod(true)
. Apa pun yang saya lakukanprivateMethod
, tidak perlu memodifikasi tes karena metode tidak dipanggil secara langsung.Tidak buruk? Anda bertaruh.
Apa yang saya lepas dari pelemahan batasan akses
Sekarang bayangkan bahwa alih-alih di atas, saya hanya memperlemah batasan akses. Saya melewatkan studi kode yang menggunakan metode dan melanjutkan langsung dengan tes yang memanggil saya
exPrivateMethod
. Besar? Tidak!Apakah saya mendapatkan tes untuk penggunaan khusus API non-pribadi yang disebutkan di atas? Tidak: tidak ada tes untuk
nonPrivateMethod(true)
sebelumnya, dan tidak ada tes seperti itu sekarang.Apakah pembaca luar mendapatkan kesempatan untuk lebih memahami penggunaan kelas? Tidak. "- Hei apa tujuan dari metode yang diuji di sini? - Lupakan saja, ini hanya untuk penggunaan internal. - Ups."
Apakah toleran terhadap refactoring? Tidak mungkin: apa pun yang saya ubah
exPrivateMethod
, kemungkinan akan memecahkan tes. Ganti nama, gabungkan ke beberapa metode lain, ubah argumen dan pengujian hanya akan berhenti mengkompilasi. Sakit kepala? Anda bertaruh!Kesimpulannya , bertahan dengan metode pribadi memberi saya peningkatan yang berguna, andal dalam unit test. Sebaliknya, melemahnya batasan akses "untuk testabilitas" hanya memberi saya kode tes yang tidak jelas dan sulit dipahami, yang juga beresiko permanen dipatahkan oleh refactoring minor; terus terang apa yang saya dapatkan tampak seperti utang teknis .
</rant>
sumber
Alasan yang paling mungkin adalah: ini ada hubungannya dengan sejarah. Nenek moyang Jawa, Oak, hanya memiliki tiga tingkat akses: pribadi, dilindungi, publik.
Kecuali bahwa private di Oak sama dengan package private di Java. Anda dapat membaca bagian 4.10 dari Spesifikasi Bahasa Oak (penekanan milik saya):
Jadi untuk titik Anda, akses pribadi, seperti yang dikenal di Jawa, awalnya tidak ada di sana. Tetapi ketika Anda memiliki lebih dari beberapa kelas dalam satu paket, tidak memiliki privat seperti yang kita tahu sekarang akan mengarah ke mimpi buruk tabrakan nama (misalnya, java.until.concurrent memiliki hampir 60 kelas), yang mungkin mengapa mereka memperkenalkannya.
Namun akses paket default (semula disebut pribadi) semantik tidak berubah antara Oak dan Java.
sumber
Ada situasi di mana seseorang ingin dua kelas terpisah yang lebih terikat daripada mengekspos segala sesuatu dengan publik. Ini memiliki ide yang mirip dari 'teman' di C ++ di mana kelas lain yang dinyatakan sebagai 'teman' dari orang lain dapat mengakses anggota pribadi mereka.
Jika Anda melihat ke jeroan kelas-kelas seperti BigInteger Anda akan menemukan sejumlah paket perlindungan standar pada bidang dan metode (semua yang segitiga biru dalam daftar). Ini memungkinkan kelas-kelas lain dalam paket java.math untuk memiliki akses yang lebih optimal ke jeroan mereka untuk operasi tertentu (Anda dapat menemukan metode ini disebut dalam BigDecimal - BigDecimal didukung oleh BigInteger dan menyimpan implementasi ulang BigInteger lagi . Bahwa ini adalah tingkat paket bukan t masalah untuk perlindungan karena java.math adalah paket yang disegel dan tidak ada kelas lain yang bisa ditambahkan.
Di sisi lain, ada banyak hal yang memang bersifat pribadi, sebagaimana mestinya. Sebagian besar paket tidak disegel. Tanpa pribadi, rekan kerja Anda dapat memasukkan kelas lain ke dalam paket itu dan mengakses bidang pribadi (tidak lagi) dan menghancurkan enkapsulasi.
Sebagai catatan, pengujian unit bukanlah sesuatu yang dipikirkan kembali ketika cakupan perlindungan sedang dibangun. JUnit (kerangka pengujian XUnit untuk Java) tidak disusun sampai 1997 (salah satu penuturan kisah itu dapat dibaca di http://www.martinfowler.com/bliki/Xunit.html ). Versi Alpha dan Beta dari JDK adalah pada tahun 1995 dan JDK 1.0 pada tahun 1996, meskipun tingkat perlindungan tidak benar-benar dipaku sampai JDK 1.0.2 (sebelum itu Anda bisa memiliki
private protected
tingkat perlindungan).Beberapa orang akan berpendapat bahwa standarnya tidak boleh tingkat paket, tetapi pribadi. Yang lain berpendapat bahwa seharusnya tidak ada perlindungan default tetapi semuanya harus dinyatakan secara eksplisit - beberapa pengikut ini akan menulis kode seperti:
Catat komentar di sana.
Alasan sebenarnya mengapa perlindungan tingkat paket adalah default kemungkinan hilang ke catatan desain Java (saya sudah menggali dan tidak dapat menemukan mengapa artikel, banyak orang yang menjelaskan perbedaannya, tetapi tidak ada yang mengatakan "ini adalah alasannya ").
Jadi saya akan menebak. Dan hanya itu - tebakan.
Pertama-tama, orang masih mencoba mencari tahu desain bahasa. Bahasa sejak itu telah belajar dari kesalahan dan keberhasilan Jawa. Ini bisa didaftar sebagai kesalahan untuk tidak memiliki sesuatu yang perlu didefinisikan untuk semua bidang.
public
, danprivate
karena ini memiliki dampak terbesar pada akses.Dengan demikian, privat tidak default dan well, semuanya jatuh ke tempatnya. Lingkup default dibiarkan sebagai default. Ini mungkin merupakan ruang lingkup pertama yang dibuat dan untuk kepentingan kompatibilitas dengan kode lama, dibiarkan begitu saja.
Seperti yang saya katakan, ini semua dugaan .
sumber
Enkapsulasi adalah cara untuk mengatakan "Anda tidak perlu memikirkan hal ini".
Menempatkan ini ke dalam istilah nonteknis.
sumber
Saya tidak berpikir mereka fokus pada pengujian, hanya karena pengujian tidak terlalu umum saat itu.
Apa yang saya pikir ingin mereka capai adalah enkapsulasi pada tingkat paket. Kelas dapat, seperti Anda ketahui, memiliki metode dan bidang internal dan hanya memaparkannya melalui anggota publik. Dengan cara yang sama paket dapat memiliki kelas internal, metode, dan bidang, dan hanya memaparkan beberapa di antaranya. Jika Anda berpikir seperti ini, sebuah paket memiliki implementasi internal dalam serangkaian kelas, metode, dan bidang, bersama dengan antarmuka publik di kelas, metode, dan bidang lainnya (mungkin sebagian tumpang tindih).
Coders paling berpengalaman yang saya tahu berpikir seperti ini. Mereka mengambil enkapsulasi dan menerapkannya ke tingkat abstraksi yang lebih tinggi dari kelas: paket, atau komponen jika Anda suka. Masuk akal bagi saya bahwa desainer Jawa sudah matang dalam desain mereka, mengingat seberapa baik Jawa masih bertahan.
sumber