Apakah variabel bendera jahat? Apakah jenis variabel berikut ini sangat tidak bermoral dan apakah jahat menggunakannya?
"variabel boolean atau integer yang Anda tetapkan nilai di tempat-tempat tertentu kemudian di bawah Anda periksa lalu orther untuk melakukan sesuatu atau tidak, seperti, misalnya menggunakan
newItem = true
beberapa baris di bawah iniif (newItem ) then
"
Saya ingat melakukan beberapa proyek di mana saya benar-benar diabaikan menggunakan bendera dan berakhir dengan arsitektur / kode yang lebih baik; Namun, ini adalah praktik umum di proyek lain tempat saya bekerja, dan ketika kode tumbuh dan bendera ditambahkan, kode-spaghetti IMHO juga tumbuh.
Apakah Anda mengatakan ada kasus di mana menggunakan bendera adalah praktik yang baik atau bahkan perlu ?, atau apakah Anda setuju bahwa menggunakan bendera dalam kode adalah ... bendera merah dan harus dihindari / refactored; saya, saya hanya bertahan dengan melakukan fungsi / metode yang memeriksa keadaan secara real time.
sumber
newItem = true
beberapa baris di bawah iniif (newItem ) then
Jawaban:
Masalah yang saya lihat ketika mempertahankan kode yang menggunakan bendera adalah bahwa jumlah negara tumbuh dengan cepat, dan hampir selalu ada keadaan yang tidak ditangani. Satu contoh dari pengalaman saya sendiri: Saya sedang mengerjakan beberapa kode yang memiliki ketiga flag ini
Ketiga negara ini menciptakan delapan negara bagian (sebenarnya, ada dua bendera lainnya juga). Tidak semua kombinasi nilai yang mungkin dicakup oleh kode, dan pengguna melihat bug:
Ternyata ada situasi di mana asumsi dalam pernyataan if di atas salah.
Bendera cenderung bertambah dari waktu ke waktu, dan mereka menyembunyikan keadaan kelas yang sebenarnya. Itu sebabnya mereka harus dihindari.
sumber
Berikut ini contoh ketika bendera berguna.
Saya memiliki sepotong kode yang menghasilkan kata sandi (menggunakan generator nomor pseudorandom yang aman secara kriptografis). Penelepon metode memilih apakah kata sandi harus mengandung huruf kapital, huruf kecil, digit, simbol dasar, simbol diperluas, simbol Yunani, Cyrillic dan unicode.
Dengan tanda, memanggil metode ini mudah:
dan bahkan dapat disederhanakan untuk:
Tanpa bendera, apa yang akan menjadi metode tanda tangan?
disebut seperti ini:
Seperti disebutkan dalam komentar, pendekatan lain adalah menggunakan koleksi:
Ini jauh lebih mudah dibaca dibandingkan dengan himpunan
true
danfalse
, tetapi masih memiliki dua kelemahan:Kelemahan utama adalah bahwa untuk memungkinkan nilai gabungan, seperti
CharacterSet.LettersAndDigits
Anda akan menulis sesuatu seperti itu dalamGenerate()
metode:mungkin ditulis ulang seperti ini:
Bandingkan ini dengan yang Anda miliki dengan menggunakan flag:
Kelemahan kedua yang sangat kecil adalah bahwa tidak jelas bagaimana metode akan berperilaku jika dipanggil seperti ini:
sumber
newItem = true
beberapa baris di bawah iniif (newItem ) then
Blok fungsi besar adalah baunya, bukan bendera. Jika Anda mengatur bendera pada baris 5, maka hanya memeriksa bendera pada baris 354, maka itu buruk. Jika Anda mengatur bendera pada baris 8 dan memeriksa bendera pada baris 10, itu tidak masalah. Juga, satu atau dua flag per blok kode baik-baik saja, 300 flag dalam suatu fungsi buruk.
sumber
Biasanya bendera dapat sepenuhnya diganti oleh beberapa rasa dari pola strategi, dengan satu implementasi strategi untuk setiap nilai bendera yang mungkin. Ini membuat menambahkan perilaku baru jauh lebih mudah.
Dalam situasi kritis kinerja, biaya tipuan mungkin muncul dan membuat dekonstruksi menjadi bendera yang jelas diperlukan. Yang sedang berkata saya mengalami kesulitan untuk mengingat satu kasus di mana saya benar-benar harus melakukan itu.
sumber
Tidak, bendera tidak buruk atau jahat yang harus di refactored dengan cara apa pun.
Pertimbangkan panggilan Pattern.compile Java (String regex, int flags) . Ini adalah bitmask tradisional dan berfungsi. Sekilas konstanta di Jawa dan di mana pun Anda melihat sekelompok 2 n Anda tahu ada bendera di sana.
Dalam dunia refactored yang ideal, seseorang malah akan menggunakan EnumSet di mana konstanta bukan nilai dalam enum dan ketika dokumentasi berbunyi:
Di dunia yang sempurna, panggilan Pattern.compile itu menjadi
Pattern.compile(String regex, EnumSet<PatternFlagEnum> flags)
.Semua yang dikatakan, masih bendera. Jauh lebih mudah untuk dikerjakan
Pattern.compile("foo", Pattern.CASE_INSENSTIVE | Pattern.MULTILINE)
daripada memilikiPattern.compile("foo", new PatternFlags().caseInsenstive().multiline())
atau gaya lain dalam mencoba melakukan apa sebenarnya bendera dan manfaatnya.Bendera sering terlihat ketika bekerja dengan hal-hal tingkat sistem. Ketika berinteraksi dengan sesuatu di tingkat sistem operasi, orang cenderung memiliki bendera di suatu tempat - baik itu nilai pengembalian suatu proses, atau izin file, atau bendera untuk membuka soket. Mencoba untuk memperbaiki kejadian ini dalam beberapa perburuan terhadap bau kode yang dirasakan kemungkinan akan berakhir dengan kode yang lebih buruk daripada jika orang yang digunakan menerima dan memahami benderanya.
Masalahnya terjadi ketika orang menyalahgunakan bendera untuk melempar mereka bersama-sama dan membuat set frankenflag dari semua jenis bendera yang tidak terkait atau mencoba menggunakannya di mana mereka bukan bendera sama sekali.
sumber
Saya berasumsi kita berbicara tentang flag dalam tanda tangan metode.
Menggunakan satu bendera saja sudah cukup buruk.
Ini tidak akan berarti apa-apa bagi kolega Anda saat mereka melihatnya. Mereka harus melihat kode sumber metode untuk menetapkan apa yang dilakukannya. Anda mungkin akan berada di posisi yang sama beberapa bulan ke depan, ketika Anda lupa tentang apa metode Anda.
Melewati bendera ke metode, biasanya berarti bahwa metode Anda bertanggung jawab untuk banyak hal. Di dalam metode Anda mungkin melakukan pemeriksaan sederhana pada baris:
Itu adalah pemisahan keprihatinan yang buruk dan Anda biasanya dapat menemukan jalan keluarnya.
Saya biasanya memiliki dua metode terpisah:
Ini akan lebih masuk akal dengan nama metode yang berlaku untuk masalah yang Anda pecahkan.
Melewati banyak bendera dua kali lebih buruk. Jika Anda benar-benar harus melewati beberapa flag, daripada mempertimbangkan untuk merangkumnya dalam sebuah kelas. Meski begitu, Anda masih akan menghadapi masalah yang sama, karena metode Anda kemungkinan melakukan banyak hal.
sumber
Bendera dan sebagian besar variabel temp adalah bau yang kuat. Kemungkinan besar mereka bisa di refactored dan diganti dengan metode kueri.
Direvisi:
Flag dan variabel temp ketika menyatakan status, harus direaktor ulang ke metode kueri. Nilai-nilai negara (boolean, int, dan primitif lainnya) harus hampir selalu disembunyikan sebagai bagian dari detail implementasi.
Bendera yang digunakan untuk kontrol, perutean, dan aliran program umum juga dapat menunjukkan peluang untuk merombak bagian-bagian dari struktur kontrol menjadi strategi atau pabrik yang terpisah, atau apa pun yang mungkin sesuai secara situasional, yang terus menggunakan metode kueri.
sumber
Ketika kita berbicara tentang bendera, kita harus tahu bahwa mereka akan dimodifikasi dari waktu ke waktu pelaksanaan program dan bahwa mereka akan mempengaruhi perilaku program berdasarkan negara mereka. Selama kita memiliki kontrol rapi atas dua hal ini, mereka akan bekerja dengan baik.
Bendera bisa berfungsi dengan baik jika
Jika ada banyak flag, pekerjaan desain yang baik harus didahului sejak flag kemudian mulai memainkan peran kunci dalam perilaku program. Anda dapat memilih diagram Negara untuk pemodelan. Diagram seperti itu juga berfungsi sebagai dokumentasi dan panduan visual saat menghadapinya.
Selama semua ini ada di tempat saya pikir itu tidak akan menyebabkan kekacauan.
sumber
Saya berasumsi dari pertanyaan bahwa QA adalah variabel flag makna (global), dan bukan bit parameter fungsi.
Ada situasi di mana Anda tidak memiliki banyak kemungkinan lain. Misalnya, tanpa sistem operasi Anda harus mengevaluasi interupsi. Jika interupsi datang sangat sering dan Anda tidak punya waktu untuk melakukan evaluasi panjang dalam ISR, itu tidak hanya diizinkan tetapi kadang-kadang bahkan praktik terbaik untuk hanya menetapkan beberapa bendera global di ISR (Anda harus menghabiskan waktu sesedikit mungkin. di ISR), dan untuk mengevaluasi flag-flag itu di loop utama Anda.
sumber
Saya tidak pernah berpikir bahwa apapun adalah kejahatan mutlak dalam pemrograman.
Ada situasi lain di mana bendera mungkin dalam urutan, yang belum disebutkan di sini ...
Pertimbangkan penggunaan penutupan dalam cuplikan Javascript ini:
Fungsi batin, diteruskan ke "Array.forEach", tidak bisa begitu saja "mengembalikan true".
Karenanya, Anda perlu menjaga negara di luar dengan bendera.
sumber