Anahtar kutularını kullanırken varsayılan durum eklemek gerekli midir?


41

Son bir kod incelemesi sırasında , yapılacak herhangi bir şey olmasa bile, bloğun kullanıldığı defaulttüm dosyalara dava açmam istendi . Bu, davayı koymam ve içine hiçbir şey yazmam gerektiği anlamına geliyor .switchdefaultdefault

Bu yapılacak doğru şey mi? Hangi amaca hizmet eder?


9
Bu size kalmış ... Gözetmen kod tarzı demek istiyorum.
SD

1
Sanırım varsayılan bir dava istemediğiniz durumlar bile var. Bir enum değiştirmeyi düşünün. Anahtarınız tüm olası değerler için bir durum tanımlar. Şimdi bir enum bir değer ekleyerek gerektiğini bu anahtarın bir dava ekleyerek sonuçlanır. Bunu yapmadıysanız, bu bir hata olabilir, çünkü bu yeni enum değeri için bir şeyler yapmak istiyorsunuz , ancak kodunuz değil. Derleyiciniz sizi bu konuda uyarabilir (bence; Java hakkında emin değilim), ancak yalnızca varsayılan bir durum belirtmediyseniz . Alternatif olarak, kodun asla ulaşmadığından emin olduğunuzda, varsayılan durumda bir uyarı yazdırabilirsiniz.
leemes

6
Ben ve arkadaşlarım buna "Geliştirici İstisnası" vakası diyoruz - koddaki bir şey asla olmayacağını bildiğiniz bir şey olduğunda (mantıksal / kod nedenleriyle), sonra atılan bir "Geliştirici İstisnası" ekliyoruz. Bu şekilde, bu gerçekleşirse, bir Geliştirici İstisnası atılır ve en azından olayların ciddi şekilde yanlış gittiğini biliyoruz.
Marco

Yanıtlar:


31

Bir defaultifadenin gerekli olmadığı üç vaka olduğu görülüyor :

  1. başka hiçbir durum kalmaz, çünkü içine giren sınırlı bir değer kümesi vardır switch case. Ancak bu zamanla (kasıtlı olarak veya kazayla) değişebilir default caseve kullanıcıyı yanlış bir değere göre kaydedebileceğiniz ya da uyaracağınız bir şeyde değişiklik olması durumunda, sizin için iyi olur .

  2. nasıl ve nerede switch casekullanılacağını ve hangi değerlerin girileceğini biliyorsunuz. Yine, bu değişebilir ve ekstra bir işleme gerekebilir.

  3. diğer durumlarda herhangi bir özel işleme gerek yoktur. Bu durumda, benden bir eklenmesi istenir default case, çünkü kabul edilen bir kodlama stilidir ve kodunuzu daha okunaklı kılar.

İlk iki dava varsayımlara dayanıyor. Dolayısıyla (düzenli kod incelemeleriniz olduğundan beri küçük olmayan bir takımda çalıştığınızı varsayarsak), bu varsayımları yapmayı göze alamazsınız. Kodunuzla kimin çalışacağını veya kodunuzdaki işlevlere / çağrı yöntemlerine çağrı yapacaklarını bilmiyorsunuz. Benzer şekilde, başkasının kodu ile çalışmanız gerekebilir. Aynı kodlama stiline sahip olmak, birinin kodunuzla başa çıkmayı kolaylaştıracaktır.


14
Durum 1 ve 2'de, varsayılan durum bir hata olmalıdır. Kodlama stiliniz her zaman varsayılan kullanıyorsa, bunu yapın, ancak 1 ve 2'de bir hata vermesini sağlayın. Mümkün olduğunda derleme zamanında çıkarması gerekir; En azından kullanıcının "Bu değeri geçerek kendinizi
vuruyorsunuz

11
Varsayılan bir durum her zaman iyi bir fikirdir, çünkü örneğin bir enum durumunda, biri enuma yeni bir giriş eklerse, varsayılan durumunuz throw new IllegalStateException("Unrecognised case "+myEnum), hatanın nerede ve ne olduğunu gösterene benzer bir şey yapmalıdır .
Zengin

Bunun olmaması gerektiğini bilseniz bile, elseher şeyden sonra her zaman bir maddeye sahip olmanız gerektiği anlamına mı if/else ifgeliyor? Bana iyi bir fikir gibi görünmüyor ...
jadkik94

2
Çalışmamdan bir fıkra ekleyebilirsem: Bazı sınıfları başlatmak için enum kullanan bir fabrika yöntemim vardı. Ne zaman o projeye yeni bir sınıf eklesen, enum'a bir değer eklemek zorunda kaldığın ve anahtara bir dava verdiğine dair talimatlar bırakmıştım. Elbette, kodu kapattıktan bir hafta sonra çalışmamayı bıraktı, istisnalardan biri asla kaldırılmamalıydı. Programcının yanına gidip sordum: "anahtara dava açtın mı?" ve kesinlikle yeterli, o yapmadı. O gün "Bu mesajı alırsanız, koda dokunan son geliştiriciyi suçla" diyerek istisnayı değiştirdim.
Ziv

28

Bu yapılacak doğru şey mi? Hangi amaca hizmet eder?

Tüm kodlamalar için şirket kodlama standartlarının varsayılan bir durum gerektirmesi nadir değildir switch. Bunun bir nedeni okuyucuların sonunu bulmasını kolaylaştırmasıdır switch. Bir başka, muhtemelen daha iyi neden, durumun beklentilerinize uymadığında kodunuzun ne yapması gerektiği hakkında bir saniye düşünmenizi sağlamasıdır. İhtiyaç sebebi ne olursa olsun, eğer bir şirket standardıysa, hava sızdırmaz bir neden olmadıkça bunu takip etmelisiniz.

switchMümkün olan her koşul için durumları içerdiğini düşünüyorsanız, yapılacak en iyi şey assertvarsayılan duruma bir ifade koymaktır . Bu şekilde, biri kodu değiştirdiğinde ve istemeden switchkapsamadığınız bir koşul eklediğinde , isabet alır assertve kodun bu bölümünü ele almaları gerektiğini anlar .

Eğer senin switchtek olası durumların birkaç kapsar, ancak özel bir şey diğerleri için yapılmalıdır, varsayılan durumda boş bırakabilirsiniz. Varsayılan durumda kasıtlı olarak boş olduğunu belirtmek için bu durumda bir yorum eklemek iyi bir fikirdir, çünkü onu vuran şartlar için herhangi bir çalışma yapılması gerekmez.


1
Bir nedir assert?
FLY

1
@FLY Java’da bir anahtar kelime ve genellikle C, C ++ ’da bir makrodur.
Caleb

Önceki yorumumu wikipedia 'ya bir linkle
FLY

Boş bir dava bırakmamalısınız. Anahtarınız tüm olası koşulları kapsamıyorsa, ikinci paragrafınızdaki varsayılan durumda bir iddia eklemenizi önerdiğiniz nedenle, varsayılan durumunuzdaki diğer koşulları da belirtmelisiniz.
rold2007

12

Saf numaralandırma tipine "geçerseniz" varsayılan geri dönüşün olması tehlikelidir. Daha sonra numaralandırma türüne değer eklediğinizde, derleyici, kapsanmayan yeni değerlerle anahtarları vurgulayacaktır. Eğer orada varsayılan fıkra varsa, derleyici sessiz kalacak ve onu kaçırabilirsin.


1
Derleme zamanında ve çalışma zamanında değil sorunu yakalamak için +1.
SylvainD

Tamamen yanıltıcı cevabın nasıl oylanıp kabul edildiğini merak ediyorum. Hızlı arama, java derleyicisinin bu tür bir uyarıda bulunduğunu gösterir. Neden yeryüzünde çalışma zamanında hata bekliyorsunuz millet?
Artur

Bu davranış hakkında bir şey bilmiyordum. Benim ideone kod örneğim ideone.com/WvytWq başka türlü önerir. Söylediğinin doğru olduğunu kabul edersek, birisi numaralandırma türüne değer eklerse ne olur, ancak kodunuzu yeniden derlemezseniz ne olur?
emory


1
Açıkçası, yeni değerler varsayılan durum olmadan switch ifadesiyle ele alınmamaktadır. Ancak, arayüzler değiştiğinde uygulamalarınızı yeniden derlemezseniz, derleme sisteminiz gerçekten bozuktur.
Artur

9

Birçok bakımdan, bu soru sıkça sorulanlarla aynıdır Her seçeneği kapsayan / merdivenin sonunda bir elsemaddeye ihtiyacım var mıifelse if ?

Cevap, sözdizimsel olarak konuşursak, hayır demezsiniz. Ama bir tane var ...

Bir defaultmadde (en azından) iki nedenden ötürü olabilir:

  1. Bir hata işleyicisi olarak - kesinlikle, buraya asla gelmemelisin! iddia edilebilecek bir iddia, fakat eğer öyleyse? Veri bozulması veya daha da kötüsü, doğrulanmadıkça veri doğrulaması yapılmaz, program başarısızlığına yol olmaz. Bu durumda, boş bir madde olmamalıdır!
  2. Tasarım / Kod Kapsamı - akış şemasının en basit haliyle bile, bir if ifadesinden iki yol ve her zaman otherwisebir durumdan. Bunları kaynak koduna dahil etmemenin bir nedeni yoktur.

Felsefem her zaman oldukça basittir - iki seçeneğin en kötü senaryosunu değerlendirin ve en güvenli olanı seçin. Boş elseya da defaultyan tümce durumunda, en kötü durum seçenekleri şunlardır:

  • Onları ekleyin: Fazladan üç veya dört satır "gereksiz" kod.
  • Bunları Dahil Etmeyin: Hileli veriler veya beklenmeyen bir koşul yakalanmadı, bu da potansiyel olarak programın başarısız olmasına neden oluyor.

Overdramatic? Belki ... ama o zaman benim yazılım yanlış giderse insanları öldürme potansiyeline sahiptir. Bu riski almamayı tercih ederim.


Bir kenara, MISRA-C kurallar {eğilimleri için bilgilerini görmek} bir tavsiye defaulther boyunca maddesiniswitch


Sadece bir merdivenin sonunda değil. Soru şu: bir elsesonra ihtiyacım var if. Ama dediğin gibi, hayır, değil.
ott

Bir hata işleyicisi olarak, boş varsayılanı engelleyen biraz değiştirilmiş bir form öneririm. İnsanları öldürmeye gelince, bunun gerçekten önemli olduğunu düşünmüyorum - insanlar, varsayılan maddeye sahip olsanız da olmasanız da ölü olacaklar, ancak neden öldüklerini öğrenmeyi kolaylaştıracak.
emory

İyi bir nokta, @ emory - bu çok net değildi, öyleydi ... ... düzenlendi :)
Andrew

6

Java, 'varsayılan' bir ifadeye sahip olmanız için zorlamaz, ancak koda hiç ulaşılmasa bile (şu anda) her zaman birinin olması iyi bir uygulamadır . İşte birkaç neden:

Ulaşılamaz bir varsayılan maddeye sahip olarak, kodunuzun okuyucusuna değerleri düşündüğünüzü ve ne yaptığınızı bildiğinizi gösterirsiniz. Ayrıca gelecekteki değişikliklere izin verirsiniz, örneğin: yeni bir enum değeri eklenir, anahtar yeni değeri sessizce göz ardı etmemelidir; Bunun yerine bir İstisna atabilir veya başka bir şey yapabilirsiniz.

Girilen beklenmedik bir değeri yakalamak için (bir enum açmamış olmanız durumunda) - örneğin beklediğinizden daha büyük veya daha az olabilir.

'Varsayılan' eylemleri işlemek için - anahtarların özel davranış için olduğu yerler. Örneğin, anahtarın dışında bir değişken ilan edilebilir, ancak başlatılamaz ve her durum farklı bir şeye başlatılır. Bu durumda varsayılan değer, varsayılan değere sıfırlanabilir, böylece anahtarın hemen ardından gelen hata bir istisna alamaz.

Varsayılan değere hiçbir şey koymamaya karar verseniz bile (istisnalar, günlüğe kaydetme vb.) O zaman varsayılanın asla gerçekleşmeyeceğini düşündüğünüz bir yorum bile, kodunuzun okunabilirliğine yardımcı olabilir; ama bu kişisel tercihlere bağlı.


2

Ayrıca, kullandığınız dilin felsefesine bağlı olduğunu da eklerdim. Örneğin, Erlang’da, “çökmesine izin vermenin” yaygın bir yaklaşımı olduğu durumlarda, varsayılan bir durum tanımlamazsınız, ancak bunun için hazırlanmayan casebir durum ortaya çıkarsa, ifadenizin hata yapmasına izin verirsiniz .


0

Tüm davaları kesin ve kalıcı olarak ele almadığınız sürece, her zaman bir varsayılanınız olmalıdır. Hiçbir maliyeti yoktur ve değişen bir programda anahtar ifadenizi sürdüremememe sigortasıdır.

Başka hiçbir vakayı umursamadığınıza eminseniz, default: break; // umrumda değil ama default varsayılan, varsayılan gibi bir şey olmalıdır:

Aynı şekilde, bırakmayı düşündüğünüz etkiye yorum eklemeden, önemsiz olmayan bir vaka yapısını asla "bırakmamalısınız". Java bunu tasarım aşamasında yanlış anladı.


-2

Düşünmek

enum Gender
{
       MALE ,
       FEMALE ;
}

ve

void run ( Gender g )
{
      switch ( g )
      {
           case MALE :
                 // code related to males
                 break ;
           default :
                 assert Gender . FEMALE . equals ( g ) ;
                 // code related to females
                 break ;
      }
}

Bunun bir MALE davası, bir FEMALE davası ve bir istisna atan varsayılan davaya göre daha üstün olduğunu iddia ediyorum.

Test aşamanız sırasında, bilgisayar g'nin FEMALE olup olmadığını kontrol edecektir. Üretim sırasında kontrol ihmal edilir. (Evet bir mikro-optimizasyon!)

Daha da önemlisi,% 100 kod kapsamı hedefinizi koruyacaksınız. İstisnalar atan varsayılan bir durum yazdıysanız, nasıl test edersiniz?


1
1. Mikrooptimalizasyona gerek yok - son 30 yıl boyunca derleyicilerde ölü kod ortadan kaldırılması kullanılıyor ve bu nedenle JIT tarafından elimine edilecek. 2.% 100 kod kapsamı genellikle önemli olarak kabul edilmez (bir yandan% 100 kapsam tüm kenar durumları yakalayamayabilir, başka hiçbir testte assert_not_reached satırları doğru programda yakalayamaz). Bu durumda hiçbir varsayılan durumda bırakma derleyici hatasına neden olmaz. Öte yandan - arsanın işe yarayıp yaramadığını nasıl kontrol edersiniz (sorunu değiştirir ve aynı söze sahip olmak yerine 'gerçekleşmeyecek söz veriyorum' yerine% 100 kapsama kadar gizlersiniz).
Maciej Piechotka

1
3. Ne zaman Gender . FEMALE . equals ( FEMALE ) ;değerlendirir false? Sen demek Gender.FEMALE.equals (g)ama kararlı olmak çeteleler başvurular bağlıdır çünkü sadece yazabilirsiniz g == Gender.FEMALE. 4. (Kişisel görüş) böyle bir kodun okunması çok zordur ve biraz daha kafa karıştırıcı hatalar üretecektir.
Maciej Piechotka

@ MaciejPiechotka g hakkında iyi yakalamak. Evet, mikrooptimizasyon bir avantaj değil, aynı zamanda bir dezavantaj değil. % 100 kod kapsamı, hedeflerinizden biri olan ve bir kod kapsamı aracınızın iddiaları kontrol etmemesi gereken bir avantajdır (hangisi olmamalıdır).
emory

Öyleyse neden hedeflerimden biri olsun? 'İlginç' bölüm tüm kenar durumları için test edilmelidir (kod satırlarına bakılmaksızın) ve 'sıkıcı' bölümler testte zaman kazanmak için kolayca atlanabilir. IMHO kod kapsamı testlerin kötü ölçümüdür.
Maciej Piechotka
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.