Kode Bersih menyarankan untuk menghindari variabel yang dilindungi di bagian "Jarak Vertikal" pada bab "Memformat":
Konsep-konsep yang berkaitan erat harus dijaga secara vertikal dekat satu sama lain. Jelas aturan ini tidak berfungsi untuk konsep yang termasuk dalam file terpisah. Tapi kemudian konsep yang berkaitan erat tidak boleh dipisahkan menjadi file yang berbeda kecuali Anda memiliki alasan yang sangat bagus. Memang, ini adalah salah satu alasan mengapa variabel yang dilindungi harus dihindari .
Apa alasannya?
code-quality
clean-code
variables
Matsemann
sumber
sumber
Jawaban:
Variabel yang dilindungi harus dihindari karena:
Tapi seperti yang Anda lihat, semua ini 'cenderung'. Terkadang anggota yang dilindungi adalah solusi yang paling elegan. Dan fungsi yang dilindungi cenderung memiliki lebih sedikit masalah ini. Tetapi ada beberapa hal yang menyebabkan mereka diperlakukan dengan hati-hati. Dengan apa pun yang membutuhkan perawatan semacam itu, orang akan membuat kesalahan dan dalam dunia pemrograman yang berarti bug dan masalah desain.
sumber
Itu alasan yang sama persis Anda menghindari global, hanya pada skala yang lebih kecil. Itu karena sulit untuk menemukan di mana-mana variabel sedang dibaca, atau lebih buruk, ditulis, dan sulit untuk membuat penggunaan konsisten. Jika penggunaannya terbatas, seperti ditulis di satu tempat yang jelas di kelas turunan dan dibaca di satu tempat yang jelas di kelas dasar, maka variabel yang dilindungi dapat membuat kode lebih jelas dan ringkas. Jika Anda tergoda untuk membaca dan menulis variabel mau tak mau di seluruh banyak file, lebih baik untuk merangkumnya.
sumber
Saya belum membaca buku itu, tetapi saya bisa mengerti apa yang dimaksud Paman Bob.
Jika Anda memakai
protected
sesuatu, itu artinya suatu kelas dapat mewarisinya. Tetapi variabel anggota seharusnya milik kelas di mana mereka terkandung; ini adalah bagian dari enkapsulasi dasar. Memakaiprotected
variabel anggota memecah enkapsulasi karena sekarang kelas turunan memiliki akses ke detail implementasi dari kelas dasar. Ini masalah yang sama yang terjadi ketika Anda membuat variabelpublic
di kelas biasa.Untuk memperbaiki masalah, Anda dapat merangkum variabel dalam properti yang dilindungi, seperti:
Ini memungkinkan
name
untuk secara aman diatur dari kelas turunan menggunakan argumen konstruktor, tanpa mengekspos detail implementasi dari kelas dasar.sumber
protected
danpublic
anggota. JikaBaseType
mengekspos anggota publik, itu menyiratkan bahwa semua jenis turunan harus memiliki anggota yang sama bekerja dengan cara yang sama, karena sebuahDerivedType
instance dapat diteruskan ke kode yang menerimaBaseType
referensi dan berharap untuk menggunakan anggota itu. Sebaliknya, jikaBaseType
mengeksposprotected
anggota, makaDerivedType
mungkin berharap untuk mengakses anggota itubase
, tetapibase
tidak bisa lain dari aBaseType
.Argumen Paman Bob terutama salah satu dari jarak: jika Anda memiliki konsep yang penting untuk suatu kelas, bundel konsep tersebut bersama-sama dengan kelas dalam file itu. Tidak dipisahkan di dua file pada disk.
Variabel anggota yang dilindungi tersebar di dua tempat, dan, agaknya terlihat seperti sulap. Anda referensi variabel ini, namun tidak didefinisikan di sini ... di mana adalah itu didefinisikan? Dan dengan demikian perburuan dimulai. Lebih baik hindari
protected
sama sekali, argumennya.Sekarang saya tidak percaya bahwa aturan harus dipatuhi surat sepanjang waktu (seperti: Anda tidak akan menggunakan
protected
). Lihatlah semangat apa yang dia dapat ... bundel hal-hal terkait bersama menjadi satu file - gunakan teknik pemrograman dan fitur untuk melakukan itu. Saya akan merekomendasikan agar Anda tidak menganalisis secara berlebihan dan terperangkap dalam detail tentang ini.sumber
Beberapa jawaban yang sangat bagus sudah ada di sini. Tapi satu hal yang perlu ditambahkan:
Dalam sebagian besar bahasa OO modern itu adalah kebiasaan yang baik (dalam Java AFAIK diperlukan) untuk menempatkan setiap kelas ke file sendiri (tolong jangan mengerti tentang C ++ di mana Anda sering memiliki dua file).
Jadi hampir tidak mungkin untuk menjaga fungsi-fungsi dalam kelas turunan dengan mengakses variabel yang dilindungi dari kelas dasar "secara vertikal dekat" dalam kode sumber dengan definisi variabel. Tetapi idealnya mereka harus disimpan di sana, karena variabel yang dilindungi dimaksudkan untuk penggunaan internal, yang membuat fungsi acessing mereka sering "konsep yang terkait erat".
sumber
Gagasan dasarnya adalah bahwa "bidang" (variabel tingkat instance) yang dinyatakan sebagai terproteksi mungkin lebih terlihat daripada seharusnya, dan lebih sedikit "terlindungi" daripada yang mungkin Anda inginkan. Tidak ada pengubah akses di C / C ++ / Java / C # yang setara dengan "hanya dapat diakses oleh kelas anak dalam rakitan yang sama", sehingga memberi Anda kemampuan untuk menentukan anak-anak Anda sendiri yang dapat mengakses bidang di rakitan Anda, tetapi tidak mengizinkan anak-anak yang dibuat di majelis lain akses yang sama; C # memiliki pengubah internal dan terlindungi, tetapi menggabungkan mereka membuat akses "internal atau dilindungi", bukan "internal dan dilindungi". Jadi, bidang yang dilindungi dapat diakses oleh anak mana pun, baik Anda menulisnya atau orang lain melakukannya. Dengan demikian dilindungi adalah pintu terbuka bagi seorang peretas.
Juga, bidang menurut definisi mereka tidak memiliki validasi yang melekat dalam mengubahnya. di C # Anda dapat membuat satu hanya baca, yang membuat tipe nilai secara efektif konstan dan tipe referensi tidak dapat diinisialisasi ulang (tapi masih sangat bisa berubah), tapi hanya itu saja. Dengan demikian, bahkan dilindungi, anak-anak Anda (yang tidak dapat Anda percayai) memiliki akses ke bidang ini dan dapat mengaturnya untuk sesuatu yang tidak valid, membuat keadaan objek tidak konsisten (sesuatu yang harus dihindari).
Cara yang diterima untuk bekerja dengan bidang adalah menjadikannya pribadi dan mengaksesnya dengan properti, dan / atau metode pengambil dan penyetel. Jika semua konsumen kelas membutuhkan nilainya, jadikan pengambil (setidaknya) publik. Jika hanya anak-anak yang membutuhkannya, buat rajin rajin rajin
Pendekatan lain yang menjawab pertanyaan adalah bertanya pada diri sendiri; mengapa kode dalam metode anak memerlukan kemampuan untuk mengubah data keadaan saya secara langsung? Apa yang dikatakan tentang kode itu? Itulah argumen "jarak vertikal" di wajahnya. Jika ada kode pada seorang anak yang harus secara langsung mengubah status induk, maka mungkin kode itu harus menjadi milik orangtua di tempat pertama?
sumber
Ini diskusi yang menarik.
Sejujurnya, alat yang baik dapat mengurangi banyak masalah "vertikal" ini. Bahkan, menurut pendapat saya gagasan tentang "file" sebenarnya adalah sesuatu yang menghambat pengembangan perangkat lunak - sesuatu yang sedang dikerjakan proyek Light Table (http://www.chris-granger.com/2012/04/12/light- tabel --- a-new-ide-concept /).
Keluarkan file dari gambar, dan cakupan yang dilindungi menjadi jauh lebih menarik. Konsep yang dilindungi menjadi paling jelas dalam bahasa seperti SmallTalk - di mana setiap warisan hanya memperluas konsep asli kelas. Itu harus melakukan segalanya, dan memiliki segalanya, yang dilakukan oleh kelas induknya.
Menurut pendapat saya, hierarki kelas harus sedangkal mungkin, dengan sebagian besar ekstensi berasal dari komposisi. Dalam model seperti itu, saya tidak melihat alasan mengapa variabel pribadi tidak dapat dilindungi. Jika kelas diperluas harus mewakili ekstensi termasuk semua perilaku kelas induk (yang saya percaya seharusnya, dan karena itu percaya metode pribadi secara inheren buruk), mengapa kelas diperluas tidak mewakili penyimpanan data juga?
Dengan kata lain - dalam hal apa pun di mana saya merasa variabel pribadi akan lebih cocok daripada yang dilindungi, pewarisan bukanlah solusi untuk masalah di tempat pertama.
sumber
Seperti dikatakan di sana, ini hanya salah satu alasan, yaitu, kode yang terhubung secara logis harus ditempatkan di dalam entitas yang terhubung secara fisik (file, paket dan lainnya). Pada skala yang lebih kecil ini sama dengan alasan Anda tidak menempatkan kelas yang membuat DB query di dalam paket dengan kelas yang menampilkan UI.
Namun alasan utama bahwa variabel yang dilindungi tidak direkomendasikan adalah karena mereka cenderung memecah enkapsulasi. Variabel dan metode harus memiliki visibilitas sebatas mungkin; untuk referensi lebih lanjut lihat Joshua Bloch's Java Efektif , Butir 13 - "Minimalkan aksesibilitas kelas dan anggota".
Namun, Anda tidak boleh menggunakan semua iklan litteram ini, hanya sebagai guildline; jika variabel yang dilindungi sangat buruk mereka tidak akan ditempatkan di dalam bahasa di tempat pertama. Tempat yang masuk akal untuk bidang yang dilindungi karena berada di dalam kelas dasar dari kerangka pengujian (kelas uji integrasi memperpanjangnya).
sumber
Saya menemukan menggunakan variabel yang dilindungi untuk tes JUnit dapat bermanfaat. Jika Anda menjadikannya pribadi maka Anda tidak dapat mengaksesnya selama pengujian tanpa refleksi. Ini bisa bermanfaat jika Anda menguji proses yang rumit melalui banyak perubahan status.
Anda bisa menjadikannya pribadi, dengan metode getter yang dilindungi, tetapi jika variabel hanya akan digunakan secara eksternal selama tes JUnit, saya tidak yakin itu solusi yang lebih baik.
sumber
Ya, saya setuju itu agak aneh mengingat bahwa (seingat saya) buku ini juga membahas semua variabel non-pribadi sebagai sesuatu yang harus dihindari.
Saya pikir masalah dengan pengubah yang dilindungi adalah bahwa tidak hanya anggota yang terpapar ke subkelas tetapi juga dapat dilihat oleh seluruh paket. Saya pikir inilah aspek ganda yang Paman Bob ambil pengecualian di sini. Tentu saja, seseorang tidak dapat selalu memiliki metode yang dilindungi, dan dengan demikian kualifikasi variabel yang dilindungi.
Saya pikir pendekatan yang lebih menarik adalah membuat semuanya publik, yang akan memaksa Anda untuk memiliki kelas kecil, yang pada gilirannya menjadikan seluruh metrik jarak vertikal agak diperdebatkan.
sumber