Apa gunanya properti?

11

Berikut adalah beberapa argumen untuk properti dan kontra-argumen saya:

Lebih mudah digunakan daripada menulis metode pengambil dan penyetel

Pasangan metode pengambil dan penyetel adalah bau kode. Membuatnya lebih mudah untuk menulis ini seperti membuatnya lebih mudah untuk gagal dalam ujian matematika dengan menggunakan formulir Scantron dan mengisi semua 'C'. Objek yang hanya berisi status, untuk ketekunan, tidak boleh menggunakan getter / setter dan harus membuat objek tidak berubah pada saat kegigihan.

Yang penting bagi konsumen suatu objek adalah apa yang dilakukannya, bukan bagaimana melakukannya. Perilakunya adalah apa yang dilakukannya; keadaannya adalah bagaimana ia melakukannya. Jika Anda mendapati diri Anda peduli dengan keadaan objek (kecuali kegigihan, meskipun ini juga merusak OO), Anda tidak melakukan OOP dan kehilangan kelebihannya.

Mereka memberikan indikasi kinerja yang kasar kepada konsumen

Ini adalah sesuatu yang bisa berubah di masa depan, untuk properti apa pun. Misalkan dalam rilis 1.0, mengakses PropertyX hanya mengembalikan bidang. Dalam rilis 1.5, jika bidangnya nol, PropertyX menggunakan pola Objek Null untuk membuat objek null baru. Dalam rilis 2.0, bidang ini semakin divalidasi oleh metode pengambil di PropertyX.

Ketika properti semakin kompleks, indikasi kinerja menggunakan properti tampaknya semakin tidak jujur.

Mereka lebih baik daripada bidang publik

Ini benar. Tapi begitu juga metode.

Mereka mewakili aspek yang berbeda secara fundamental dari suatu objek daripada metode, dan semua konsumen objek harus peduli tentang hal ini

Apakah Anda yakin kedua pernyataan di atas benar?

Mereka lebih mudah mengetik, bung

Tentu, mengetik myObject.Lengthlebih mudah daripada mengetik myObject.Length(), tetapi tidak bisakah itu diperbaiki dengan sedikit gula sintaksis?


Mengapa menggunakan metode alih-alih properti?

  • Tidak ada jaminan kinerja. API akan tetap jujur ​​bahkan jika metodenya menjadi lebih kompleks. Konsumen akan perlu membuat profil kode mereka jika mereka menjalankan masalah kinerja, dan tidak bergantung pada kata-of-API.

  • Kurang bagi konsumen untuk dipikirkan. Apakah properti ini memiliki setter? Metode yang pasti tidak.

  • Konsumen berpikir dari pola pikir OOP yang tepat. Sebagai konsumen API, saya tertarik berinteraksi dengan perilaku objek. Ketika saya melihat properti di API, tampilannya sangat mirip keadaan. Bahkan, jika properti melakukan terlalu banyak, mereka seharusnya tidak menjadi properti, jadi benar-benar, properti dalam keadaan API ARE seperti yang terlihat oleh konsumen.

  • Pemrogram API akan berpikir lebih mendalam tentang metode dengan nilai pengembalian, dan menghindari mengubah keadaan objek dalam metode tersebut, jika memungkinkan. Pemisahan perintah dari pertanyaan harus ditegakkan sedapat mungkin.


Jadi saya bertanya kepada Anda, mengapa menggunakan properti alih-alih metode? Sebagian besar poin pada MSDN adalah bau kode dalam dan dari dirinya sendiri, dan tidak termasuk dalam properti atau metode.

(Pikiran-pikiran ini datang kepada saya setelah memikirkan tentang CQS.)

xofz
sumber
5
+1. Properti adalah metode dengan sintaks bidang dan itu tidak masuk akal.
Nemanja Trifunovic
23
@Nemanja Trifunovic: Masuk akal jika Anda telah menulis type GetFoo() void SetFoo()sepuluh ribu kali. Sepanjang waktu saya menulis kode C # saya tidak pernah bingung dengan properti.
Ed S.
23
Bagi saya, sepertinya Anda sudah mengambil keputusan. Apa pertanyaannya?
Dean Harding
9
@Nemanja Trifunovic: "Getters dan setter umumnya buruk" Anda dapat mengulanginya sebanyak yang Anda suka, tetapi itu tidak akan membuatnya menjadi kenyataan. Bagaimana dengan menjelaskan mengapa Anda berpikir mereka buruk? Sejauh SO lumpuh karena mengetikkan nama properti alih-alih nama variabel yang mendasarinya, itu tidak mungkin untuk dilewatkan karena menganggapnya akan merusak program Anda segera setelah Anda menelepon properti dan itu sangat jarang. Ketika itu terjadi, saya tahu persis apa yang saya lakukan untuk menyebabkannya dan saya memperbaikinya dalam dua detik. Saya tidak melihat masalah.
Ed S.
3
Hanya lewat untuk menunjukkan kepada @NemanjaTrifunovic bahwa metode getter dan setter adalah artikel jahat sudah cukup tua , adalah tentang java dan menggarisbawahi kelemahan java : kelemahan tidak memiliki properti . (karenanya memamerkan terlalu banyak detail implementasi) ... menggigit ekor kami di sini. (seharusnya judul getter dan setter buruk di Jawa, karena kita tidak punya standar yang baik tentang hal itu )
ZJR

Jawaban:

44

Mengapa "metode melawan properti"? Suatu metode melakukan sesuatu. Properti adalah, yah, anggota suatu objek. Mereka hal yang sama sekali berbeda, meskipun dua jenis metode yang biasa ditulis - getter dan setter - sesuai dengan properti. Karena membandingkan properti dengan metode secara umum tidak berarti, saya akan menganggap Anda bermaksud berbicara tentang getter / setter.

Pasangan metode pengambil dan penyetel adalah bau kode.

Tidak harus, saya berpendapat, tapi bagaimanapun ini bukan masalah getter / setter vs properti tetapi masalah apakah keduanya harus digunakan. Perhatikan juga bahwa Anda dapat mis meninggalkan setXbagian seperti Anda dapat membuat properti read-only.

Yang penting bagi konsumen suatu objek adalah apa yang dilakukannya, bukan bagaimana melakukannya. Perilakunya adalah apa yang dilakukannya; keadaannya adalah bagaimana ia melakukannya. Jika Anda mendapati diri Anda peduli dengan keadaan objek (kecuali kegigihan, meskipun ini juga merusak OO), Anda tidak melakukan OOP dan kehilangan kelebihannya.

Sikap yang sangat dipertanyakan. Jika GUI ingin menampilkan data yang dipegang oleh a DataStuffManagerImpl, ia perlu mendapatkan nomor itu entah bagaimana (dan tidak, menjejalkan setengah dari aplikasi ke dalam kelas widget bukan merupakan pilihan).

Ketika properti semakin kompleks, indikasi kinerja menggunakan properti tampaknya semakin tidak jujur.

[Metode miliki] Tidak ada jaminan kinerja. API akan tetap jujur ​​bahkan jika metodenya menjadi lebih kompleks. Konsumen akan perlu membuat profil kode mereka jika mereka menjalankan masalah kinerja, dan tidak bergantung pada kata-of-API.

Dalam hampir semua kasus, semua logika validasi, dll. Masih efektif O (1), atau dapat diabaikan biaya. Jika tidak, mungkin Anda sudah melangkah terlalu jauh dan inilah saatnya untuk perubahan. Dan suatu getX()metode biasanya diperlakukan dengan murah juga!

Tentu, mengetik myObject. Panjang lebih mudah daripada mengetik myObject. Panjang (), tetapi tidak bisakah itu diperbaiki dengan sedikit gula sintaksis?

Khasiatnya adalah gula sintaksis.

Kurang bagi konsumen untuk dipikirkan. Apakah properti ini memiliki setter? Metode yang pasti tidak.

"Apakah ada setter untuk pengambil ini?" Perbedaan yang sama.

Pemrogram API akan berpikir lebih mendalam tentang metode dengan nilai pengembalian, dan menghindari mengubah keadaan objek dalam metode tersebut, jika memungkinkan. Pemisahan perintah dari pertanyaan harus ditegakkan sedapat mungkin.

Saya tidak yakin apa yang Anda coba sampaikan kepada kami di sini. Untuk properti, ada hukum tertulis yang bahkan lebih kuat untuk tidak menyebabkan efek samping.

ChrisF
sumber
3
+1, Dan ini bukan hukum tidak tertulis. Panduan penggunaan properti pada MSDN telah ditulisnya dengan banyak lainnya. Saya pikir OP harus melalui mereka untuk membuat dirinya jelas dari banyak keraguan. Dan saya tidak dapat memposting tautan di sini karena saya menulis ini dari ponsel saya, tetapi pedoman harus mudah ditemukan.
Decyclone
@delnan: Properti bukan gula sintaksis. Properti dapat diperlakukan seperti bidang (mereka dapat digunakan sebagai target penugasan, jika mereka memiliki setter). Metode tidak bisa.
xofz
1
@SamPearson: obj.x = ypeta ke obj.setX(y)dan obj.xpeta ke obj.getX(). Bagaimana itu berbeda?
1
@SamPearson Anda dapat mengubah visibilitas setter properti dan pengambil independen satu sama lain. Saya menggunakan ini sepanjang waktu dengan objek Kerangka Entitas saya: setter saya dilindungi (jadi hanya kerangka kerja yang dapat menetapkan nilai). Jadi sangat masuk akal untuk mengatakan int length = myObject.Length tanpa mengizinkan myObject.Length = 10
Michael Brown
19

Pasangan metode pengambil dan penyetel adalah bau kode.

Itu adalah asumsi yang salah dan sepenuhnya salah. Metode Get / Set adalah cara untuk merangkum anggota data dan sama sekali bukan "bau kode". Saya benar-benar benci cara beberapa orang melempar istilah "kode bau", tetapi toh ...

Ini adalah sesuatu yang bisa berubah di masa depan, untuk properti apa pun. Misalkan dalam rilis 1.0, mengakses PropertyX hanya mengembalikan bidang. Dalam rilis 1.5, jika bidangnya nol, PropertyX menggunakan pola Objek Null untuk membuat objek null baru. Dalam rilis 2.0, bidang ini semakin divalidasi oleh metode pengambil di PropertyX.

Ketika properti semakin kompleks, indikasi kinerja menggunakan properti tampaknya semakin tidak jujur.

Kedengarannya seperti API yang dirancang dengan buruk, saya tidak melihat bagaimana itu adalah kesalahan sintaksis properti.

Properti dalam C # hanyalah gula sintaksis untuk pola yang sangat umum yang membuat hidup kita sebagai programmer sedikit lebih mudah. Namun, akhir-akhir ini, jika Anda ingin menggunakan pengikatan data, Anda "harus" menggunakan properti, jadi mereka sekarang sedikit lebih dari gula sintaksis. Saya kira saya benar-benar tidak setuju dengan poin Anda sama sekali dan saya tidak mengerti mengapa Anda tidak menyukai fitur bahasa yang secara langsung mendukung pola umum.

Ed S.
sumber
1
Saya akan memberikan hadiah untuk menghasilkan istilah yang lebih baik daripada kode bau. Baca saja sebuah buku tentang refactoring di mana ia digunakan sekitar seribu kali. Ini seperti kuku di papan tulis.
JeffO
1
@ Jeff O: Ya, saya menemukan bahwa orang-orang yang tampaknya menggunakan istilah itu biasanya tidak memiliki banyak pengalaman.
Ed S.
6
@Jeff O dan @Ed S: IME, "kode bau" telah menjadi istilah umum yang digunakan orang ketika mereka benar-benar berarti "Saya tidak suka itu, tapi saya sebenarnya tidak punya alasan"
Steven Evers
3
@SnOrfus: Yap, atau ketika mereka memiliki pandangan "religius" yang sering tidak masuk akal dalam praktik, seperti "metode seharusnya tidak pernah memiliki lebih dari X jumlah baris" , yang pada gilirannya biasanya hanya pengulangan dari sesuatu yang mereka baca di suatu tempat.
Ed S.
1
The pantas penggunaan metode pengambil / penyetel adalah kode bau, tapi demikian juga harus menjadi penggunaan yang tidak apa-apa . Bahkan ketika hal-hal memiliki kasus penggunaan yang sempit, menggunakan hal-hal seperti itu untuk kasus penggunaan tersebut tidak boleh dianggap sebagai bau kode. Penciptaan pemukim untuk segala sesuatu seharusnya tidak menjadi kebiasaan yang buta, tetapi orang tidak boleh takut untuk memasukkannya saat yang tepat. Apa yang diperlukan adalah menyeimbangkan kegunaan bagi klien untuk dapat mengubah keadaan, dibandingkan dengan dapat mengetahui di masa depan apa keadaan sebelumnya (mudah jika keadaan tidak dapat diubah). Keduanya berguna, tetapi kode harus memilih satu.
supercat
10

Premis Anda salah.

Properti sama sekali bukan kontrak untuk kinerja atau implementasi internal atau apa pun.
Properti adalah pasangan metode khusus, yang secara semantik mewakili suatu atribut, jika Anda mau. Dan dengan demikian satu - satunya kontrak adalah, bahwa properti berperilaku seperti yang Anda harapkan atribut berperilaku.
Jika saya meminta warna objek, saya tidak membuat asumsi apakah itu diperoleh dengan akses bidang biasa, atau apakah itu dihitung tepat waktu.
Intinya adalah, memiliki kemampuan untuk mengekspos perilaku atribut dengan menggunakan metode, sementara itu transparan untuk konsumen antarmuka, apakah Anda menggunakan bidang atau pengakses.

Memiliki atribut (dan benar-benar menyembunyikan implementasinya, karena properti bertentangan dengan bidang) adalah fitur deklaratif yang kuat , yang merupakan dasar untuk memiliki pengawas objek visual dan pembuatan tampilan otomatis lainnya, untuk pengikatan data dan banyak hal berguna lainnya. Dan yang paling penting, itu jelas mengangkut informasi ini untuk sesama programmer Anda juga.

back2dos
sumber
6

Konsumen berpikir dari pola pikir OOP yang tepat. Sebagai konsumen API, saya tertarik berinteraksi dengan perilaku objek. Ketika saya melihat properti di API, tampilannya sangat mirip keadaan. Bahkan, jika properti melakukan terlalu banyak, mereka seharusnya tidak menjadi properti, jadi benar-benar, properti dalam keadaan API ARE seperti yang terlihat oleh konsumen.

Properti seharusnya menjadi sebuah negara. Jika setter atau pengambil kode yang mendasarinya berubah untuk menambahkan secara signifikan pada pemrosesan yang diperlukan untuk mengatur atau mendapatkan status maka sebenarnya itu bukan lagi properti dan Anda harus menggantinya dengan metode. Ini terserah Anda sebagai pengembang kode.

Menempatkan terlalu banyak (berapa banyak terlalu banyak bergantung) kode dalam setter atau pengambil adalah salah, tetapi hanya karena itu mungkin bukan alasan untuk membuang pola dalam semua kasus.

ChrisF
sumber
6

Satu hal yang Anda lewatkan, dan saya tidak tahu apakah ini karena ketidaktahuan atau jika Anda sengaja mengabaikan detail ini, adalah bahwa properti ADALAH metode.

Saat Anda menggunakan sintaksis properti C #, kompiler diam-diam membuat metode pengambil dan penyetel dengan metadata yang memberi tahu bahasa yang memahami properti sebagai fitur sintaksis kelas satu untuk memperlakukannya seperti itu. Faktanya, itu adalah gula sintaksis yang Anda minta. Beberapa bahasa yang dapat dijalankan pada CLR tidak sepenuhnya menyembunyikan detail ini dari Anda (Boo, jika ingatanku, dan beberapa implementasi Lisp), dan Anda dapat memanggil getter dan setter secara eksplisit.

Properti kadang-kadang memiliki efek samping, seperti memicu perubahan pemberitahuan acara (INotifyPropertyChanged, misalnya) atau menandai turunan kelas sebagai kotor. Di sinilah mereka memiliki nilai sebenarnya, meskipun membuat mereka sedikit lebih banyak pekerjaan (kecuali di Boo, yang memiliki makro sintaksis-cerdas).

Sekarang, pertanyaan yang lebih luas adalah apakah metode pengambil dan penyetel sebenarnya adalah A Good Thing. Jelas ada pengorbanan; jika Anda memiliki metode mutator, kode Anda secara inheren kurang dapat diparalelkan, karena Anda sekarang harus berurusan dengan masalah sinkronisasi utas. Dan sangat mungkin bahwa Anda akan berisiko melanggar Hukum Demeter menggunakan metode mutator (apakah disebut properti atau metode pengambil / penyetel; mereka setara), karena sangat nyaman untuk melakukannya.

Tapi terkadang itu hal yang benar untuk dilakukan. Terkadang masalah Anda adalah mengambil data dari beberapa sumber, mengubahnya sedikit, menyajikan data yang diperbarui kepada pengguna, dan menyimpan perubahan. Idiom itu dilayani dengan baik oleh properti. Seperti yang dikatakan artikel Allen Holub , hanya karena getter dan setter memiliki masalah bukan berarti Anda tidak boleh menggunakannya. (Bayan abstrak Guruspeak dianggap berbahaya). Bahkan ketika Anda mengikuti pendekatan Kelas / Tanggung Jawab / Kolaborator, Anda tetap akan mengungkap informasi atau presentasi informasi kepada seseorang; intinya adalah meminimalkan luas permukaan keterjeratan.

Kelebihan dari properti adalah sangat mudah untuk membuat objek lain memanfaatkannya. Kelemahan dari properti adalah sangat mudah untuk membuat objek lain memanfaatkannya, dan Anda tidak dapat dengan mudah mencegahnya.

Mutasi objek masuk akal pada lapisan pengontrol, misalnya, dalam arsitektur MVC. Itu kolaborator Anda. Pandangan Anda juga kolaborator, tetapi seharusnya tidak secara langsung mengubah objek Anda, karena memiliki tanggung jawab yang berbeda. Menggulirkan kode presentasi ke objek bisnis Anda juga tidak selalu merupakan cara yang tepat untuk menghindari getter / setter.

Persamaan berubah sedikit jika Anda menggunakan abstraksi fungsional, bukan murni OO, yang umumnya membuat salinan objek "rekaman" dengan beberapa perubahan yang cukup sepele, meskipun tidak gratis. Dan hei, Jika Anda mencoba untuk mendapatkan jaminan kinerja, properti umumnya lebih dapat diprediksi daripada malas membangun kembali koleksi abadi.

Jason True
sumber
5

Alasan penting lain dalam buku saya untuk menggunakan properti adalah properti itu dapat meningkatkan keterbacaan secara signifikan.

account.setBalance(Account.getBalance()+deposit);

jelas jauh lebih mudah dibaca daripada

account.Balance += deposit;
apoorv020
sumber
6
Kecuali bahwa Balance tidak boleh properti karena pasti ada logika bisnis yang signifikan terkait dengan mengubahnya (periksa cerukan; biaya layanan, catat transaksi, dll.) Poin keterbacaan Anda benar-benar valid jika diterapkan pada contoh berbeda ( Temperatur, BackgroundColour dll.)
Kate Gregory
9
Kenapa tidak akun. Deposit (jumlah)?
xofz
4
@ Sam Pearson: +1. Contoh sempurna mengapa getter / setter sering menunjukkan desain yang buruk.
Nemanja Trifunovic
4

Anda memiliki sudut pandang agama yang hampir berlawanan dengan saya :)

Ketika saya pindah dari Delphi ke Jawa, kurangnya properti merupakan penghinaan besar bagi saya. Saya terbiasa mendeklarasikan properti dan mengarahkannya langsung ke variabel pribadi atau menulis pengambil & penyetel (terlindungi), lalu "menyambungkannya" ke properti. Ini merangkum properti dan mengontrol bagaimana itu harus diakses dengan cara yang jelas. Anda dapat memiliki properti hanya baca yang menghitung total ketika diakses dan menyebutnya "Total" bukan "_getTotal ()" atau ballochs serupa. Ini juga berarti bahwa Anda dapat membatasi akses ke properti dengan membuatnya terlindungi di kelas dasar abstrak lalu memindahkannya ke publik atau diterbitkan dalam subkelas.

Bagi saya, properti adalah cara yang lebih alami & ekspresif untuk mengatur & mendapatkan keadaan objek. Mengandalkan konvensi pengkodean unenforced lebih merupakan "bau kode" daripada apa pun yang Anda kritik properti. Juga, seperti yang dikatakan orang lain, muncul dengan penggunaan properti yang dirancang dengan buruk dan menggunakan kegagalannya untuk mencoba & menolak konsep properti secara umum adalah bentuk yang sangat buruk. Mungkin saja Anda baru saja melihat penggunaan properti yang buruk & menganggap itu memang seharusnya, tetapi Anda harus melakukan lebih banyak penelitian sebelum menjadi terlalu dogmatis.

mcottle
sumber
+1 Itu benar-benar menggunakan properti. Jawaban yang bagus " Itu juga berarti bahwa Anda dapat membatasi akses ke properti dengan membuatnya terlindungi dalam kelas dasar abstrak lalu memindahkannya ke publik atau diterbitkan dalam subclass. "
Karthik Sreenivasan
Delphi menyalahgunakan properti dan mual. Anda tidak mengurutkan daftar, Anda mengatur sorted propertinya true. Jadi pengaturannya untuk falsememberi Anda daftar asli. : D Atau apakah itu mengocoknya secara acak? : D Atau apa pun, itu hanya bodoh. Selain itu, sangat lambat dibandingkan dengan set diurutkan yang tepat. Properti tidak buruk, tetapi saya telah belajar menggunakannya sangat hemat (sampai pada titik cukup senang dengan pengambil dan setter; Saya menggunakan sebagian besar Jawa).
maaartinus
1

Salah satu alasan properti diperkenalkan dalam Java Beans Framework adalah untuk memungkinkan integrasi dengan IDE - Anda dapat menyeret komponen tersebut ke IDE dan mengedit properti menggunakan editor properti.

(saat itu mereka hanya getter dan setter reguler - dan hanya ditentukan oleh konvensi penamaan - dan ini memang berbau)

Saat ini ada lebih banyak lagi kasus di mana properti diakses dan dimodifikasi tidak melalui kode biasa - seperti saat debugging.

Ophir Yoktan
sumber
1

Satu sudut lain - mereka benar-benar berasal dari VB. Ingat, kembali pada hari-hari gelap abad ke-20 ketika .NET dikonsepsikan sebagai satu penekanan utama adalah itu adalah penggantian drop-in yang mudah untuk VB sehingga programmer VB Anda hanya dapat menarik dan melepas sesuatu ke dalam formulir web. VB memiliki properti sehingga Anda perlu menjaga fitur itu agar hal-hal yang diterjemahkan benar.

Wyatt Barnett
sumber
1
Anders Heljsberg mendesain C # (dan beberapa IL) dan juga mendesain Delphi - yang memiliki properti.
Jesse C. Slicer
1

Setidaknya ada dua tujuan untuk properti:

  • Mereka secara konseptual identik dengan bidang bahkan jika mereka diterapkan secara berbeda. Seorang pengambil harus tidak mengubah keadaan objek dan seharusnya tidak memiliki efek samping. Seorang setter seharusnya hanya mengubah keadaan dengan cara yang secara konseptual mirip dengan memodifikasi bidang dan tidak memiliki efek samping lainnya.

  • Secara sintaksis identik dengan bidang publik (mungkin hanya baca). Ini berarti bidang publik dapat diubah menjadi properti tanpa melanggar penelepon di tingkat sumber.

dsimcha
sumber
Ya, tetapi perhatikan kata "harus". Tidak ada apa-apa tentang properti yang mencegah getter dari memiliki efek samping dan sebenarnya saya telah melihat banyak kasus di mana itu terjadi.
Nemanja Trifunovic
1
Mengubah bidang publik ke properti akan merusak kompatibilitas biner, kode yang digunakan harus dikompilasi ulang - meskipun tidak dimodifikasi yang saya duga adalah apa yang Anda dapatkan :)
MattDavey
@MattDavey: Terima kasih. Itu yang saya maksud. Diedit.
dsimcha