Apakah Show () + Hide () atau SetVisible (bool terlihat) lebih baik?

59

Apa yang lebih baik dan mengapa? (Dari sudut pandang desain-antarmuka):

a) Untuk memiliki dua Show()dan Hide()fungsi

b) Untuk memiliki satu SetVisible(bool visible)fungsi

EDIT: Misalnya beberapa objek memiliki status visibilitas dan fungsi ini digunakan untuk mengubahnya.

c) Untuk memiliki ketiga Show(), Hide(), SetVisible(bool visible)fungsi

pengguna3123061
sumber
4
Dalam konteks apa? Secara umum tidak masalah
Aviv Cohn
6
Mengapa tidak semuanya publik? Ada kasus di mana Anda tahu mereka akan selalu ditampilkan atau disembunyikan dan ada kasus di mana Anda ingin ditampilkan atau disembunyikan secara kondisional.
plve
@pllee: Itu mungkin poin yang sangat bagus.
user3123061
4
Di java, itu akan menjadi setVisible, hide, dan show tanpa huruf awal.
Pierre Arlaud

Jawaban:

81

Saya lebih suka SetVisible(bool visible), karena memungkinkan saya menulis kode klien seperti ini:

SetVisible(DetermineIfItShouldBeVisible());

alih-alih harus menulis

if (DetermineIfItShouldBeVisible()) {
    Show();
} else {
    Hide();
}

The SetVisiblePendekatan juga memungkinkan untuk pelaksanaan lebih mudah. Misalnya, jika kelas konkret tertentu hanya mendelegasikan metode ke kelas kompositnya, maka SetVisibleberarti satu metode lebih sedikit untuk diterapkan.

void ButtonWithALabel::SetVisible(bool visible) {
    myButton.SetVisible(visible);
    myLabel.SetVisible(visible);
}
Josh Kelley
sumber
25
Setara, Anda juga bisa membuat properti Terlihat, dengan asumsi bahasa Anda mendukungnya. MyObject.Visible = false;menurut saya lebih intuitif daripadaMyObject.SetVisible(false);
Brian
9
@Brian Bagi saya itu kurang mudah dibaca dan dapat disangkal, karena menyembunyikan perilaku program di mata saya - panggilan metode yang mendasarinya - tapi itu cerita lain. Java tidak mendukung sintaks itu, pokoknya ini soal preferensi dan pelatihan mata.
ignis
10
SetVisible()tidak menyarankan (kepada saya) bahwa Anda benar-benar menampilkan sesuatu. Bunyinya lebih seperti Anda mengatur properti visibilitas suatu objek, mungkin menyerahkannya ke metode yang sesuai Refresh()atau Redisplay()untuk memeriksa nilai properti ini untuk menentukan apakah objek tersebut harus ditampilkan atau disembunyikan.
TMN
1
Sayangnya Java tidak mendukung properti seperti C #, hanya getter dan setter yang Anda lihat di atas.
theGreenCabbage
1
@ TMN: Saya berharap bahwa dengan tidak adanya faktor lain yang mencegah visibilitas (urutan Z, visibilitas induk, lokasi, dll.) setVisible(true)Akan menggerakkan proses di mana objek akan ditarik ketika sistem idle berikutnya, jika tidak sebelumnya. Saya berharap bahwa refreshmungkin berguna untuk mempercepat tampilan objek, tetapi objek tersebut pada akhirnya akan ditarik terlepas (kecuali misalnya visibilitasnya diatur falsesebelum itu terjadi).
supercat
35

Saya tidak setuju dengan semua poster yang menyarankan beberapa fungsi untuk melakukan hal yang sama adalah hal yang baik. Sementara tiga fungsi bukan satu mungkin tidak tampak seperti banyak mengasapi, ingat bahwa kelas Anda mungkin berakhir dengan banyak fungsi tersebut (misalnya setEnabled, enable, disable) dan dengan demikian pendekatan ini akan berakhir dengan banyak antarmuka kelas yang lebih besar. Selain itu, kemungkinan Anda akan berakhir dengan sekelompok fungsi / properti terdengar serupa / apa pun di kelas Anda dan penggandaan fungsi lebih lanjut akan mengaburkan mana yang sesuai dengan apa.

Dalam bahasa yang mendukung properti, ini harus lebih disukai tetapi karena Java maupun C ++ tidak melakukannya, saya kira itu adalah poin yang bisa diperdebatkan.

Saya pikir setVisible()harus lebih disukai karena alasan ini:

  1. Segera jelas apa fungsi kebalikannya. Untuk membalikkan setVisible(false)Anda menelepon setVisible(true)sedangkan sebaliknya hide()bisa dengan mudah reveal().
  2. Secara pemrograman lebih sederhana setiap kali Anda menentukan negara mana yang harus diambil dalam kode, yaitu Anda dapat menelepon setVisible(wantToSee)daripada menggunakan ifpernyataan.
  3. Setelah Anda memiliki beberapa fungsi serupa, setX()formatnya akan digeneralisasi sehingga Anda dapat memiliki satu set fungsi yang konsisten sedangkan pendekatan verbed akan memunculkan sejumlah fungsi yang sulit ditemukan jika Anda tidak tahu apa yang Anda cari. Konsistensi dalam API membuatnya lebih mudah dipelajari dan diingat.
Jack Aidley
sumber
3
C ++ tidak memiliki properti, tetapi memiliki fungsi bebas, sehingga Anda dapat memperluas antarmuka kelas tanpa menambahkan fungsi anggota baru, yaitu dengan kopling derajat rendah.
phresnel
Qt sering memberikan ketiganya sebagai kenyamanan sehingga hide () dan show () dapat dihubungkan langsung ke acara lain menggunakan sistem sinyal / slot. Ini benar-benar keterbatasan sistem slot - jika menggunakan sesuatu yang lebih seperti boost :: functions, argumen true / false dapat diikat pada saat mengatur callback.
1
"Dalam bahasa yang mendukung properti, ini harus lebih disukai tetapi karena Java maupun C ++ tidak melakukannya, saya kira itu adalah poin yang bisa diperdebatkan." belum tentu. Lebih suka getter / setter? Iya. Tapi set_visible sebenarnya bukan setter.
Miles Rout
19

Itu tergantung pada apa yang ditunjukkan dan disembunyikan artinya dalam konteks. Pertama Anda ingin mencari tahu mana yang merupakan "jalan utama" Anda, dan fokus pada pengembangan itu:

  • Alasan untuk memilih setVisible(bool)
    • Itu hanya sedikit-flip sederhana, atau objek Anda terutama memegang status
    • Objek Anda akan menghabiskan sebagian besar waktunya dalam kerangka CRUD
    • Ada banyak kode yang mudah dibagikan antara menampilkan dan menyembunyikan
  • Alasan untuk memilih show()danhide()
    • Ada efek samping yang penting atau banyak logika yang dijalankan, seperti ketika objek harus memeriksa semua wadahnya untuk keadaan visibilitas mereka , atau memicu animasi transisi.
    • Apakah itu bagian dari model domain di mana mengekspresikan maksud itu penting

OK, jadi sekarang setelah Anda mengkodekan inti "standar emas" itu, Anda perlu mencari tahu apakah itu layak menambahkan metode kenyamanan tipis dalam gaya lain, untuk membuat hidup lebih mudah bagi siapa pun yang akan menggunakan objek Anda.

  • Kenyamanan setVisible(bool)
    • Memungkinkan Anda menghindari pernyataan if yang memiliki kondisi sepele dan hanya memengaruhi visibilitas (mis. setVisible(a==b))
    • Dapat ditransfer ke kerangka pengambil / penyetel tertentu, jika itu sesuatu yang Anda harapkan terjadi
  • Kenyamanan show()danhide()
    • Berguna dalam bahasa dengan fungsi dan panggilan balik kelas satu (mis. onSuccess(widget.show))
    • Jauh lebih mudah dibaca dengan tumpukan-jejak dan profil kinerja, karena Anda dapat dengan cepat melihat apa yang coba dilakukan oleh program

TLDR: Cari tahu mana yang paling penting, terapkan, dan kemudian tanyakan pada diri Anda apakah perlu menambahkan gaya lain sebagai metode kenyamanan yang tipis.

Darien
sumber
11

Saya akan mengatakan "ketiganya".

Show()dan Hide()cenderung lebih mudah grok daripada SetVisible(true)dan SetVisible(false). Namun, ketika Anda ingin mengatur visibilitas secara logis, lebih baik memiliki metode yang mengambil booldaripada membangun ifsekitar itu bool.

Anda dapat mendukung ketiganya tanpa menduplikasi logika dan boilerplate minimal:

void Show() {
    foo.Show();
    bar.Show();
}

void Hide() {
    foo.Hide();
    bar.Hide();
}

void SetVisible(bool visible) {
    if (visible) {
        Show();
    } else {
        Hide();
    }
}

Atau, jika hal-hal yang Anda bungkus memiliki SetVisibleAPI lebih -ish:

void Show() {
    SetVisible(true);
}

void Hide() {
    SetVisible(false);
}

void SetVisible(bool visible) {
    foo.SetVisible(visible);
    bar.SetVisible(visible);
}
Garry Shutler
sumber
40
Microsoft menggunakan pendekatan ini untuk memulai dan menghentikan System.Windows.Forms.Timer. Secara pribadi, saya menemukan ini membingungkan. Ketika saya melihat keduanya Showdan SetVisible, kecenderungan pertama saya adalah bertanya-tanya apakah ada beberapa perbedaan penting antara kedua fungsi tersebut.
Brian
1
Anda dapat dengan mudah mendokumentasikannya untuk menghilangkan kebingungan itu. Saya tidak melakukannya karena ini adalah contoh sederhana.
Garry Shutler
20
Jadi sekarang saya perlu menghabiskan X menit ekstra membaca dokumentasi sebelum saya merasa nyaman menggunakan kelas? Atau, sebagai alternatif, saya perlu membuang X menit tambahan waktu menjadi bingung (atau memperkenalkan bug)? Tentu, X cukup kecil untuk hal semacam ini, tapi jelas bukan nol. Menawarkan ketiga opsi berarti menawarkan fungsi tiga kali lebih banyak dari yang diperlukan, yang berarti Anda menghabiskan lebih banyak dokumentasi kerja dan saya menghabiskan lebih banyak pekerjaan untuk belajar bagaimana menggunakan kelas. Lebih lanjut, ini memperkenalkan satu lagi cara agar pengembang yang berbeda menjadi tidak konsisten saat menggunakan kelas Anda.
Brian
5
Ini adalah pelanggaran yang jelas terhadap prinsip Segregasi Antarmuka, salah satu prinsip SOLID. Pendapat lain yang menentang pendekatan Anda adalah pendapat dari jaroslav tulach, perancang netbeans, yang banyak kali bersikeras untuk menyediakan hanya satu cara untuk melakukan satu hal dalam API dalam desain API praktis bukunya.
AlfredoCasado
@ AlfredoCasado saya setuju. Bagaimana jika SetVisible dilindungi ? Anda bisa mengaksesnya dari subkelas, tetapi panggilan ke entitas yang diberikan dengan antarmuka ini (seperti API) haruslah Sembunyikan / Tampilkan.
Pierre Arlaud
5

Saya lebih suka show () dan hide (), pada kenyataannya, setiap metode yang menerima satu boolean dapat diubah untuk dua metode dan mengekspresikan maksud API dengan lebih baik. Sebagai contoh, Robert Martin dalam kode bersih merekomendasikan untuk memilih metode dengan argumen nol daripada metode dengan satu argumen.

Argumen penting lainnya bagi saya adalah keterbacaan, menurut saya kode yang baik dapat dibaca seperti prosa, prosa yang benar-benar aneh seperti "main_window setVisible false" daripada "main_window hide", Anda menulis atau berbicara seperti itu secara normal?, Mengapa menggunakan ini aneh konstruksi bahasa dalam program perangkat lunak, kapan mungkin menggunakan bahasa yang lebih alami?

AlfredoCasado
sumber
1
Bukankah prosa Assembler cukup?
Alexander
Saya berharap bahwa urutan it.setVisible(false); it.setVisible(true);tidak akan mempengaruhi visibilitas orang tua kontrol, juga tidak akan mempengaruhi urutan atau lokasi Z kontrol. Sebaliknya hide(); show(),; bisa secara masuk akal memaksa orangtua kontrol untuk terlihat, memindahkannya di atas kontrol lain, dan membatasi posisinya ke suatu tempat yang dapat dilihat. Dalam beberapa kasus, berguna untuk memastikan sesuatu benar-benar terlihat (seperti yang disebutkan di atas show(), tetapi dalam kasus lain, berguna untuk mengubah bendera visibilitas tanpa mengubah apa pun yang lain.
supercat
Dalam Object Oriented API tidak ada "flags", OO adalah tentang perpesanan, ini tentang memberitahu objek lain melakukan beberapa tugas, bukan tentang mengubah "flags" yang merupakan keadaan objek. Anda membuat banyak asumsi tentang kontrol, orang tua, pemesanan-z, dan hal-hal yang ANDA harapkan berdasarkan pengalaman Anda sebelumnya dengan API lain, itu ide yang sangat buruk merancang API berdasarkan perasaan pribadi dan asumsi tentang suatu domain.
AlfredoCasado
5

Saya percaya bahwa semakin metode ini ekspresif, semakin mudah dibaca, dan konsekuensinya, kode akan dapat dipertahankan. Pertimbangkan dua kasus berikut:

Kasus 1:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  customerPanel.setVisible(customer.isCustomerEnabled());
}

Kasus 2:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  //always show customer panel
  customerPanel.setVisible(true);
}

Dalam kasus pertama, jelas apa fungsi "setVisible" lakukan, tetapi jika Anda ingin membacanya, Anda akan mengatakan:

atur panel pelanggan agar terlihat jika pelanggan diaktifkan atau setel ke tersembunyi jika pelanggan dinonaktifkan.

Sementara itu lebih deskriptif untuk mengatakan:

  • periksa status pelanggan:
    • jika pelanggan diaktifkan maka tunjukkan panel pelanggan
    • jika tidak, sembunyikan

yang akan mengubah fungsi "Kasus 1" menjadi yang berikut:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  if(customer.isCustomerEnabled()){
    customerPanel.Show();
  }
  else{
    customerPanel.Hide();
  }
}

ini menghasilkan lebih banyak kode, tetapi lebih mudah dibaca.

Kasing kedua memiliki cacat yang jelas, yaitu, Anda sudah tahu bahwa Anda ingin menampilkan panel, jadi mengapa tidak menggunakan fungsi "Tampilkan"?

Saya tidak mengatakan bahwa menggunakan "setVisible" benar-benar salah, tetapi akan membingungkan ketika Anda mencoba membaca kode yang tidak ditulis oleh Anda dari waktu ke waktu, dan itu tidak sesuai dengan aturan "Fungsi harus hanya menjalankan satu operasi" aturan.

OKAN
sumber
Saya akan mengatakan: show customer panel iff the user/customer is enabled. Saya setuju bahwa mungkin ada banyak kondisi yang lebih kompleks yang tidak semudah dibaca sebagai contoh Anda, namun, dalam kasus-kasus tersebut saya akan membagi kondisi-kondisi tersebut menjadi beberapa baris yang berbeda.
ComFreek
5

Saya percaya bahwa Hide()/ Show()alternatif itu menarik karena lebih mudah untuk memahami apa yang terjadi daripada dengan SetVisible(true), sementara memiliki fungsi tunggal lebih disukai karena menghindari banyak persyaratan.

Jika itu yang terjadi maka saya sarankan menggunakan enumerasi sebagai input SetVisible, sehingga Anda mendapatkan salah satu SetVisible(Visibility.Visible)atau SetVisible(Visibility.Hidden). Anda memiliki satu fungsi, Anda dapat langsung membaca tindakan apa yang sedang diambil.

Menggunakan konvensi penamaan Java, Anda mungkin memiliki setVisible(Visibility.VISIBLE)atau setVisible(Visibility.HIDDEN).

Gabe
sumber
3

Saya setuju dengan jawaban Darien, tetapi ingin menambahkan sudut pandang dari perspektif programmer C #.

Ketika saya melihat kode yang mengatakan 'setXXX' saya membacanya untuk mengatakan bahwa itu menetapkan nilai pada suatu hal, saya tidak berharap ini memiliki efek samping dalam hal itu selain mengatur nilai itu, dan saya berharap ini menjadi idempoten (Yaitu saya bisa terus menyetelnya dengan nilai yang sama dan tidak apa-apa). Ini seperti mengakses bidang. Secara umum saya juga berharap untuk melihat metode 'getXXX' bersama dengan 'setXXX'.

Saya tidak tahu apakah ini yang Anda harapkan di Java dan C ++, tapi itulah yang saya harapkan di C #, meskipun di C # ada tulisan singkat untuk properti ini. Dan inilah beberapa panduan bagus tentang cara menggunakan Properties ( http://msdn.microsoft.com/en-us/library/ms182181.aspx ).

Dengan tampilan ini, maka antarmuka yang saya pilih bergantung sepenuhnya pada apakah ada efek samping (selain mengubah nilai bidang itu):

Jika melakukan tindakan memiliki efek samping, misalnya menampilkan kotak dialog maka saya akan pergi dengan "Tampilkan ()", dan "Sembunyikan ()".

Jika tidak memiliki efek samping, katakan saya sedang mengatur visibilitas "widget" dan sesuatu yang lain membuat widget itu tergantung pada keadaan itu maka saya akan menggunakan setVisibility atau setIsVisible. (Saya tidak akan menyebutnya SetVisible).

Di C # (tidak yakin tentang Java) cukup umum untuk mengadopsi pola pengamat, di mana kerangka kerja UI akan mendengarkan perubahan objek dan secara otomatis merender ulang UI ketika properti seperti perubahan Visibilitas. Itu berarti bahwa pengaturan nilai dengan memanggil setIsVisible muncul seolah-olah ia memiliki efek samping, tetapi dalam definisi saya tidak. Kontrak widget dipenuhi dengan menetapkan nilai bidangnya yang mewakili "IsVisible".

Dengan kata lain, tidak apa-apa bagi saya untuk mengaktifkan visibilitas label pada formulir sebelum formulir ditampilkan. Yaitu label.getIsVisible == true, tetapi formulir tidak ditampilkan.

Tidak apa-apa bagi saya untuk memanggil Hide () ketika formulir tidak ditampilkan.

Daniel James Bryars
sumber
1
Deskripsi getXXX()dan setXXX()metode Anda sebagai cara untuk mengakses bidang tanpa efek samping terdengar seperti Java dan bukan C #. Ini adalah cara Anda harus melakukannya di Jawa karena tidak memiliki properti. Jika saya melihat kode seperti itu di C #, saya kira itu ditulis oleh pengembang Java yang belum belajar tentang properti di C #.
gilly3
+1 untuk SetVisibility.
akaltar
@ gilly3 - Ya, tentu saja. Dan, "Properti" tidak ada di CLR, C # diterjemahkan menjadi panggilan metode get_XXX dan set_YYY di IL. Maksud saya adalah: dalam konteks pertanyaan, jika Anda melihat setXXX, getXXX di Jawa Anda akan berharap itu bekerja dengan semantik yang sama dengan properti di C #. Itu benar, maka saya beralasan bahwa pedoman yang sama untuk properti di C # berlaku untuk pasangan setXXX dan getXXX di Jawa. Saya kebetulan setuju dengan pedoman yang saya referensi di posting, dan karena itu saya menganjurkan pedoman yang sama untuk digunakan dalam skenario ini di Jawa ketika mendefinisikan antarmuka.
Daniel James Bryars
1
Mungkin membantu untuk menjelaskan bahwa ketika Anda bermaksud "efek samping", maksud Anda "selain yang terkait dengan menjadi hal yang 'dapat diamati'". Aturan yang saya sukai adalah untuk mengatakan bahwa jika getXXpanggilan memiliki setXXmetode yang sesuai , maka setYYtidak boleh memengaruhi, tetapi mungkin mempengaruhi getZZpanggilan yang tidak memiliki setZZmetode.
supercat
2

Saya sarankan antarmuka yang sedikit dimodifikasi:

Show();
Hide();
ToggleVisible();
ToggleVisible(bool visible);

Nama yang lebih baik

Nama-nama metode ini membantu pengembang untuk memutuskan metode mana yang akan digunakan berdasarkan apa yang perlu dilakukan. Sedangkan SetVisible(bool visible)dapat membingungkan pengembang karena menyampaikan makna semantik yang sama dengan Show()dan Hide(), Toggle()menyiratkan adanya suatu kondisi yang menentukan tindakan. Dengan demikian menjadi intuitif bagi pengembang kapan harus menggunakan setiap metode.

Mengurangi redundansi kode

Manfaat memiliki banyak metode di antarmuka Anda adalah menyederhanakan kode panggilan. Anda bisa saja mengekspos Show()dan Hide(), tetapi:

  • Anda mungkin akan memerlukan semacam SetVisible()metode pribadi untuk melakukan pekerjaan nyata di belakang layar (atau menulis kode redundan untuk Show()dan Hide()).
  • Kode panggilan mungkin memiliki banyak berlebihan jika / selain itu memblokir hanya untuk memilih metode mana yang akan digunakan. Ini menggembungkan kode menurut saya.
  • Jika saya adalah konsumen, saya mungkin hanya akan menulis fungsi pembungkus saya sendiri yang melakukan apa SetVisible()(atau Toggle()) sudah dilakukan untuk menghindari kode mengasapi (saya benci kode berlebihan). Dengan demikian menduplikasi suatu metode yang mungkin sudah ada sebagai metode pribadi dalam implementasi.
gilly3
sumber
1
Duplikasi metode terdengar masuk akal, meskipun saya tidak akan melakukannya sendiri. Di sisi lain, saya tidak setuju bahwa toggleVisible (bool) intuitif. Bagi saya, itu berarti bahwa itu harus beralih jika bool yang lewat benar, yang akan agak aneh, tetapi saya telah melihat orang asing. Itu tidak akan menganggap bahwa itu benar-benar suatu fungsi yang terselubung.
Patrick M
0

Saya akan menyarankan menggunakan SetVisible(bool)jika ada hanya jika mengaktifkan visibilitas dua kali (tampilkan dan sembunyikan kembali, atau sembunyikan dan tunjukkan kembali) akan meninggalkan hal-hal dalam keadaan yang pada dasarnya sama seperti sebelum operasi dilakukan (tidak apa-apa jika menunjukkan dan menyembunyikan kembali sesuatu atau sebaliknya meninggalkan objek yang membutuhkan redraw, asalkan dapat diharapkan terjadi "secara otomatis"). Jika menyembunyikan dan menunjukkan objek tidak akan memiliki efek selain mengubah satu bit status, maka masuk akal untuk kode luar untuk memiliki beberapa metode yang menerima parameter visibilitas, dan penulisan kode tersebut akan difasilitasi oleh SetVisible.

Jika menyembunyikan dan menampilkan kembali suatu objek mungkin memiliki efek samping seperti mengubah urutan Z, tindakan seperti itu seharusnya lebih mungkin dilakukan dengan metode terpisah. Dalam kasus seperti itu, kegunaan metode luar yang menerima parameter "visibilitas" akan terbatas, sehingga akan ada sedikit keuntungan untuk memfasilitasi mereka. Lebih lanjut, suatu SetVisiblemetode akan (secara keliru) menyarankan bahwa perubahan visibilitas objek dapat dilakukan tanpa efek samping.

supercat
sumber