Seorang kolega saya menyatakan bahwa boolean sebagai argumen metode tidak dapat diterima . Mereka akan diganti dengan pencacahan. Awalnya saya tidak melihat ada manfaat, tapi dia memberi saya contoh.
Apa yang lebih mudah dimengerti?
file.writeData( data, true );
Atau
enum WriteMode {
Append,
Overwrite
};
file.writeData( data, Append );
Sekarang saya paham! ;-)
Ini jelas merupakan contoh di mana enumerasi sebagai parameter kedua membuat kode lebih mudah dibaca.
Jadi, apa pendapat Anda tentang topik ini?
coding-style
boolean
enumeration
Thomas Koschel
sumber
sumber
Jawaban:
Boolean mewakili pilihan "ya / tidak". Jika Anda ingin merepresentasikan "ya / tidak", gunakan boolean, yang seharusnya sudah cukup jelas.
Tetapi jika itu adalah pilihan antara dua opsi, tidak ada yang jelas ya atau tidak, maka enum terkadang bisa lebih mudah dibaca.
sumber
setLightOn(bool)
.Enum juga memungkinkan untuk modifikasi di masa mendatang, di mana Anda sekarang menginginkan pilihan ketiga (atau lebih).
sumber
Gunakan salah satu yang paling sesuai dengan masalah Anda. Dalam contoh yang Anda berikan, enum adalah pilihan yang lebih baik. Namun, ada kalanya boolean lebih baik. Mana yang lebih masuk akal bagi Anda:
atau
Dalam hal ini, saya mungkin memilih opsi boolean karena menurut saya ini cukup jelas dan tidak ambigu, dan saya cukup yakin kunci saya tidak akan memiliki lebih dari dua status. Namun, pilihan kedua masih berlaku, tetapi tidak perlu rumit, IMHO.
sumber
Bagi saya, penggunaan boolean atau enumerasi bukanlah pendekatan yang baik. Robert C. Martin menangkap ini dengan sangat jelas dalam Tip Kode Bersih # 12: Hilangkan Argumen Boolean :
Jika sebuah metode melakukan lebih dari satu hal, Anda sebaiknya menulis dua metode berbeda, misalnya dalam kasus Anda:
file.append(data)
danfile.overwrite(data)
.Menggunakan enumerasi tidak membuat segalanya lebih jelas. Itu tidak mengubah apa pun, itu masih argumen bendera.
sumber
setVisible(boolean visible) { mVisible = visible; }
. Alternatif apa yang Anda sarankan?Saya pikir Anda hampir menjawab ini sendiri, saya pikir tujuan akhirnya adalah membuat kode lebih mudah dibaca, dan dalam hal ini enum melakukan itu, IMO selalu yang terbaik untuk melihat tujuan akhir daripada aturan selimut, mungkin lebih memikirkannya sebagai pedoman yaitu enum seringkali lebih dapat dibaca dalam kode daripada bools generik, ints dll tetapi akan selalu ada pengecualian untuk aturan tersebut.
sumber
Ingat pertanyaan yang diajukan Adlai Stevenson kepada duta besar Zorin di PBB selama krisis rudal Kuba ?
Jika flag yang Anda miliki dalam metode Anda bersifat sedemikian rupa sehingga Anda dapat menjepitnya menjadi keputusan biner , dan keputusan itu tidak akan pernah berubah menjadi keputusan tiga arah atau n, gunakan boolean. Indikasi: bendera Anda disebut isXXX .
Jangan membuatnya menjadi boolean jika terjadi sesuatu yang merupakan sakelar mode . Selalu ada satu mode lagi dari yang Anda pikirkan saat menulis metode di tempat pertama.
Dilema satu mode lainnya misalnya menghantui Unix, di mana mode izin yang mungkin dimiliki file atau direktori saat ini menghasilkan makna ganda yang aneh dari mode tergantung pada jenis file, kepemilikan, dll.
sumber
Ada dua alasan mengapa saya menganggap ini hal yang buruk:
Karena beberapa orang akan menulis metode seperti:
Ini jelas buruk karena terlalu mudah untuk mencampur parameter, dan Anda tidak tahu dengan melihatnya apa yang Anda tentukan. Hanya satu bool tidak terlalu buruk.
Karena mengontrol aliran program dengan cabang ya / tidak sederhana mungkin berarti Anda memiliki dua fungsi yang sama sekali berbeda yang digabungkan menjadi satu dengan cara yang canggung. Misalnya:
Sungguh, ini harus menjadi dua metode
karena kode di dalamnya mungkin sama sekali berbeda; mereka mungkin harus melakukan semua jenis penanganan kesalahan dan validasi yang berbeda, atau bahkan mungkin harus memformat data keluar secara berbeda. Anda tidak dapat mengatakannya hanya dengan menggunakan
Write()
atau bahkanWrite(Enum.Optical)
(meskipun tentu saja Anda dapat memiliki salah satu dari metode tersebut, cukup panggil metode internal WriteOptical / Mag jika Anda mau).Saya kira itu tergantung. Saya tidak akan terlalu mempermasalahkannya kecuali untuk # 1.
sumber
Enum lebih baik tetapi saya tidak akan menyebut parameter boolean sebagai "tidak dapat diterima". Terkadang lebih mudah untuk memasukkan satu boolean kecil dan melanjutkan (pikirkan metode pribadi, dll.)
sumber
Boolean mungkin baik-baik saja dalam bahasa yang memiliki parameter bernama, seperti Python dan Objective-C, karena namanya dapat menjelaskan fungsi parameter:
atau:
sumber
Saya tidak setuju bahwa itu adalah aturan yang baik . Jelas, Enum membuat kode eksplisit atau verbose yang lebih baik di beberapa kasus, tetapi sebagai aturan tampaknya jauh melebihi jangkauan.
Pertama izinkan saya mengambil contoh Anda: Tanggung jawab programmer (dan kemampuan) untuk menulis kode yang baik tidak benar-benar terancam dengan memiliki parameter Boolean. Dalam contoh Anda, pemrogram dapat menulis kode verbose dengan menulis:
atau saya lebih suka yang lebih umum
Kedua: Contoh Enum yang Anda berikan hanya "lebih baik" karena Anda melewati CONST. Kemungkinan besar di sebagian besar aplikasi setidaknya beberapa jika tidak sebagian besar parameter waktu yang diteruskan ke fungsi adalah VARIABEL. dalam hal ini contoh kedua saya (memberikan variabel dengan nama yang bagus) jauh lebih baik dan Enum akan memberi Anda sedikit manfaat.
sumber
Enum memiliki manfaat yang pasti, tetapi Anda tidak boleh hanya mengganti semua boolean Anda dengan enum. Ada banyak tempat di mana benar / salah sebenarnya adalah cara terbaik untuk merepresentasikan apa yang sedang terjadi.
Namun, menggunakannya sebagai argumen metode agak mencurigakan, hanya karena Anda tidak dapat melihat tanpa menggali hal-hal apa yang seharusnya mereka lakukan, karena mereka membiarkan Anda melihat apa yang benar / salah. sebenarnya berarti
Properti (terutama dengan penginisialisasi objek C # 3) atau argumen kata kunci (a la ruby atau python) adalah cara yang jauh lebih baik untuk pergi ke tempat Anda menggunakan argumen boolean.
C # contoh:
Contoh Ruby
Contoh Python
Satu-satunya hal yang dapat saya pikirkan di mana argumen metode boolean adalah hal yang benar untuk dilakukan adalah di java, di mana Anda tidak memiliki properti atau argumen kata kunci. Inilah salah satu alasan saya benci java :-(
sumber
Memang benar bahwa dalam banyak kasus enum lebih dapat dibaca dan lebih dapat diperluas daripada boolean, aturan mutlak bahwa "boolean tidak dapat diterima" adalah konyol. Itu tidak fleksibel dan kontraproduktif - tidak meninggalkan ruang untuk penilaian manusia. Mereka adalah tipe bawaan yang mendasar di sebagian besar bahasa karena berguna - pertimbangkan untuk menerapkannya ke tipe bawaan lainnya: mengatakan misalnya "jangan pernah menggunakan int sebagai parameter" akan gila.
Aturan ini hanyalah masalah gaya, bukan potensi bug atau kinerja waktu proses. Aturan yang lebih baik adalah "lebih memilih enum daripada boolean karena alasan keterbacaan".
Lihatlah kerangka .Net. Boolean digunakan sebagai parameter pada beberapa metode. .Net API tidak sempurna, tetapi menurut saya penggunaan boolean sebagai parameter bukanlah masalah besar. Tooltip selalu memberi Anda nama parameter, dan Anda juga dapat membuat panduan semacam ini - isi komentar XML Anda pada parameter metode, mereka akan muncul di tooltip.
Saya juga harus menambahkan bahwa ada kasus ketika Anda harus merefaktor boolean dengan jelas ke enumerasi - ketika Anda memiliki dua atau lebih boolean di kelas Anda, atau di parameter metode Anda, dan tidak semua status valid (misalnya tidak valid untuk memilikinya keduanya benar).
Misalnya, jika kelas Anda memiliki properti seperti
Dan itu adalah kesalahan jika keduanya benar pada saat yang sama, apa yang sebenarnya Anda dapatkan adalah tiga keadaan yang valid, lebih baik dinyatakan sebagai sesuatu seperti:
sumber
Beberapa aturan yang mungkin lebih baik dipatuhi oleh kolega Anda adalah:
sumber
Boolean hanya dapat diterima jika Anda tidak bermaksud memperluas fungsionalitas kerangka kerja. Enum lebih disukai karena Anda dapat memperpanjang enum dan tidak merusak implementasi pemanggilan fungsi sebelumnya.
Keuntungan lain dari Enum adalah lebih mudah dibaca.
sumber
Jika metode menanyakan pertanyaan seperti:
dimana
Argumen metode boolean tampaknya sangat masuk akal.
sumber
Itu tergantung pada metodenya. Jika metode melakukan sesuatu yang sangat jelas benar / salah maka itu baik-baik saja, misalnya di bawah [meskipun saya tidak mengatakan ini adalah desain terbaik untuk metode ini, ini hanya contoh di mana penggunaannya jelas].
Namun dalam banyak kasus, seperti contoh yang Anda sebutkan, lebih baik menggunakan pencacahan. Ada banyak contoh di .NETFramework itu sendiri di mana konvensi ini tidak diikuti, tetapi itu karena mereka memperkenalkan pedoman desain ini cukup terlambat dalam siklus.
sumber
Itu memang membuat hal-hal sedikit lebih eksplisit, tetapi mulai memperluas kompleksitas antarmuka Anda secara besar-besaran - dalam pilihan boolean belaka seperti menambahkan / menimpa sepertinya berlebihan. Jika Anda perlu menambahkan opsi lebih lanjut (yang tidak dapat saya pikirkan dalam kasus ini), Anda selalu dapat melakukan refactor (tergantung pada bahasanya)
sumber
Enum tentu bisa membuat kodenya lebih mudah dibaca. Masih ada beberapa hal yang harus diperhatikan (setidaknya dalam .net)
Karena penyimpanan yang mendasari enum adalah int, nilai default-nya adalah nol, jadi Anda harus memastikan bahwa 0 adalah default yang masuk akal. (Misalnya, struct memiliki semua bidang disetel ke nol saat dibuat, jadi tidak ada cara untuk menetapkan default selain 0. Jika Anda tidak memiliki nilai 0, Anda bahkan tidak dapat menguji enum tanpa mentransmisikan ke int, yang akan menjadi gaya buruk.)
Jika enum Anda bersifat pribadi untuk kode Anda (tidak pernah diungkapkan secara publik) maka Anda dapat berhenti membaca di sini.
Jika enum Anda diterbitkan dengan cara apa pun ke kode eksternal dan / atau disimpan di luar program, pertimbangkan untuk menomori mereka secara eksplisit. Kompilator secara otomatis menomori mereka dari 0, tetapi jika Anda mengatur ulang enum Anda tanpa memberinya nilai, Anda dapat berakhir dengan cacat.
Saya bisa menulis secara legal
Untuk mengatasi hal ini, kode apa pun yang menggunakan enum yang tidak dapat Anda yakini (mis. API publik) perlu memeriksa apakah enum tersebut valid. Anda melakukan ini melalui
Satu-satunya peringatan
Enum.IsDefined
adalah bahwa ia menggunakan refleksi dan lebih lambat. Itu juga mengalami masalah versi. Jika Anda perlu sering memeriksa nilai enum, sebaiknya Anda melakukan hal berikut:Masalah pembuatan versi adalah bahwa kode lama mungkin hanya tahu bagaimana menangani 2 enum yang Anda miliki. Jika Anda menambahkan nilai ketiga, Enum.IsDefined akan menjadi true, tetapi kode lama belum tentu dapat menanganinya. Ups.
Ada lebih banyak kesenangan yang bisa Anda lakukan
[Flags]
enum, dan kode validasinya sedikit berbeda.Saya juga akan mencatat bahwa untuk portabilitas, Anda harus menggunakan panggilan
ToString()
pada enum, dan menggunakannyaEnum.Parse()
saat membacanya kembali. KeduanyaToString()
danEnum.Parse()
dapat menangani[Flags]
enum, jadi tidak ada alasan untuk tidak menggunakannya. Pikiran Anda, itu adalah kesalahan lain, karena sekarang Anda bahkan tidak dapat mengubah nama enum tanpa mungkin memecahkan kode.Jadi, terkadang Anda perlu menimbang semua hal di atas ketika Anda bertanya pada diri sendiri Bisakah saya lolos hanya dengan bool?
sumber
IMHO sepertinya enum akan menjadi pilihan yang jelas untuk situasi apa pun di mana lebih dari dua opsi dimungkinkan. Tapi pasti ADA situasi di mana boolean adalah semua yang Anda butuhkan. Dalam hal ini saya akan mengatakan bahwa menggunakan enum di mana bool akan bekerja akan menjadi contoh penggunaan 7 kata ketika 4 sudah cukup.
sumber
Boolean masuk akal bila Anda memiliki toggle yang jelas yang hanya bisa menjadi salah satu dari dua hal (yaitu keadaan bola lampu, hidup atau mati). Selain itu, ada baiknya untuk menulisnya sedemikian rupa sehingga jelas apa yang Anda lewati - misalnya penulisan disk - unbuffered, line-buffered, atau synchronous - harus diteruskan seperti itu. Bahkan jika Anda tidak ingin mengizinkan penulisan sinkron sekarang (dan Anda dibatasi pada dua opsi), ada baiknya mempertimbangkan untuk membuatnya lebih bertele-tele untuk tujuan mengetahui apa yang mereka lakukan pada pandangan pertama.
Yang mengatakan, Anda juga dapat menggunakan False dan True (boolean 0 dan 1) dan kemudian jika Anda membutuhkan lebih banyak nilai nanti, perluas fungsi untuk mendukung nilai yang ditentukan pengguna (katakanlah, 2 dan 3), dan nilai 0/1 lama Anda akan porting dengan baik, sehingga kode Anda tidak akan rusak.
sumber
Terkadang lebih mudah untuk memodelkan perilaku yang berbeda dengan kelebihan beban. Untuk melanjutkan dari contoh Anda adalah:
Pendekatan ini menurun jika Anda memiliki beberapa parameter, masing-masing memungkinkan sekumpulan opsi tetap. Misalnya, metode yang membuka file mungkin memiliki beberapa permutasi mode file (buka / buat), akses file (baca / tulis), mode berbagi (tidak ada / baca / tulis). Jumlah total konfigurasi sama dengan produk Cartesian dari masing-masing opsi. Biasanya dalam kasus seperti itu kelebihan beban ganda tidak sesuai.
Enum dapat, dalam beberapa kasus membuat kode lebih mudah dibaca, meskipun memvalidasi nilai enum yang tepat dalam beberapa bahasa (misalnya C #) bisa jadi sulit.
Seringkali parameter boolean ditambahkan ke daftar parameter sebagai beban berlebih baru. Salah satu contoh di .NET adalah:
Kelebihan yang terakhir menjadi tersedia di versi yang lebih baru dari kerangka .NET daripada yang pertama.
Jika Anda tahu bahwa hanya akan ada dua pilihan, boolean mungkin baik-baik saja. Enum dapat dikembangkan dengan cara yang tidak akan merusak kode lama, meskipun pustaka lama mungkin tidak mendukung nilai enum baru sehingga pembuatan versi tidak dapat sepenuhnya diabaikan.
EDIT
Dalam versi C # yang lebih baru, dimungkinkan untuk menggunakan argumen bernama yang, IMO, dapat membuat kode panggilan lebih jelas dengan cara yang sama seperti enum. Menggunakan contoh yang sama seperti di atas:
sumber
Di mana saya setuju bahwa Enum adalah cara yang baik untuk digunakan, dalam metode di mana Anda memiliki 2 opsi (dan hanya dua opsi Anda dapat memiliki keterbacaan tanpa enum.)
misalnya
Suka Enum, tetapi boolean juga berguna.
sumber
Ini adalah entri terlambat pada posting lama, dan sangat jauh di bawah halaman sehingga tidak ada yang akan membacanya, tetapi karena tidak ada yang mengatakannya ....
Komentar sebaris sangat membantu memecahkan masalah yang tidak terduga
bool
. Contoh aslinya sangat keji: bayangkan mencoba menamai variabel dalam dekelusi fungsi! Ini akan menjadi seperti ituTapi, demi contoh, katakanlah itu deklarasi. Kemudian, untuk argumen boolean yang tidak dapat dijelaskan, saya memasukkan nama variabel dalam komentar sebaris. Membandingkan
dengan
sumber
Itu benar-benar tergantung pada sifat argumen yang tepat. Jika bukan ya / tidak atau benar / salah maka enum membuatnya lebih mudah dibaca. Tetapi dengan enum Anda perlu memeriksa argumen atau memiliki perilaku default yang dapat diterima karena nilai yang tidak ditentukan dari tipe yang mendasari dapat diteruskan.
sumber
Penggunaan enum sebagai ganti boolean dalam contoh Anda memang membantu membuat pemanggilan metode lebih mudah dibaca. Namun, ini adalah pengganti item keinginan favorit saya di C #, bernama argumen dalam pemanggilan metode. Sintaks ini:
akan mudah dibaca, dan Anda kemudian dapat melakukan apa yang harus dilakukan oleh programmer, yaitu memilih jenis yang paling sesuai untuk setiap parameter dalam metode tanpa memperhatikan tampilannya di IDE.
C # 3.0 memungkinkan argumen bernama dalam konstruktor. Saya tidak tahu mengapa mereka tidak bisa melakukan ini dengan metode juga.
sumber
Nilai Boolean
true
/false
saja. Jadi tidak jelas apa yang diwakilinya.Enum
dapat memiliki nama yang bermakna, misalnyaOVERWRITE
,APPEND
, dll Jadi enum lebih baik.sumber