Geliştirici, ifadelerin ihmal koşullarının olmaması ve her zaman başka bir bloğa sahip olması gerektiğinde ısrar eder


169

Benden daha deneyimli bir geliştiricim var. Programlama uygulamaları hakkında konuşuyorduk ve 'if' ifadeleri konusundaki yaklaşımından şaşırmıştım. Oldukça garip bulduğum ifadelerle ilgili bazı uygulamalarda ısrar ediyor.

Öncelikle , eğer bir if ifadesi, içine koymak için bir şey olup olmadığına bakılmaksızın başka bir ifade tarafından takip edilmelidir. Bu gibi görünen kod yol açar:

if(condition) 
{
    doStuff();
    return whatever;
}
else
{
}

İkincisi , yanlış yerine gerçek değerleri test etmek daha iyidir. Bu, '! DoorOpened' değişkeni yerine 'doorClosed' değişkenini test etmenin daha iyi olduğu anlamına gelir

Argümanı, kodun ne yaptığını daha açık hale getirdiğidir .

Bu beni biraz şaşırtıyor, çünkü bu iki kuralın bir kombinasyonu, şartlar karşılanmadığında bir şeyler yapmak isterse bu tür bir kod yazmasına neden olabilir.

if(condition)
{
}
else
{
    doStuff();
    return whatever;
}

Bununla ilgili hislerim gerçekten çok çirkin ve / veya varsa kalite kalitesinin ihmal edilebilir olduğudur. Ama bir çocuk olarak, içgüdülerimden şüphe duymaya meyilliyim.

Öyleyse benim sorularım: Uygulama iyi mi / kötü mü / "farketmez mi"? Yaygın pratik mi?



57
İş arkadaşınızın, yaşam ve uzvunun tehlikede olabileceği bir arka plandan gelmesi mümkün mü? Kodda bir miktar ton test ve otomatik analiz yapılan ve yanlış almanın gerçek anlamda birisinin hayatına mal olabileceği sistemlerde bu tür şeylerden bahsettiğime inanıyorum.
jpmc26

11
Şirketinizin kod stili kılavuzunuz ne diyor?
Thorbjørn Ravn Andersen

4
"İkincisi" sorunuza kısmi yanıt. Eylem bloklarından biri uzun ve diğer kısa ise, önce kısa bloğu koyan bir koşulu test edin, böylece kodu okurken kaçırılmaması daha az olasıdır. Bu durum bir olumsuzluk olabilir ya da doğru için bir test yapmak için yeniden adlandırılabilir.
Ethan Bolker,

9
Resharper'ın arkadaşına, "Kodun gereksiz ve işe yaramaz, onu silmemi / yeniden düzenlememi ister misin?"
BgrWorker

Yanıtlar:


184

Açık elseblok

İlk kural sadece kodu kirletir ve ne daha okunaklı, ne de daha az hataya meyilli yapar. İş arkadaşınızın amacı - herhalde - geliştiricinin koşulun değerlendirilebileceğinin tam olarak farkında olduğunu göstererek, açık olmaktır false. Açık olması iyi bir şey olsa da, bu açıklık üç ekstra kod satırı pahasına olmamalıdır .

Bir ififadenin mutlaka elseya hiç ya da hiçbiri tarafından takip edilmemesi gerçeğinden bahsetmiyorum bile : Bir ya da daha fazla elifs tarafından da takip edilebilir .

İfadenin varlığı returnişleri daha da kötüleştirir. Aslında elseblok içinde yürütmek için kodunuz olsa bile , bu şekilde yapmak daha okunaklı olacaktır:

if (something)
{
    doStuff();
    return whatever;
}

doOtherThings();
return somethingElse;

Bu, kodun iki satırı daha az almasını sağlar ve elsebloğu ayırır . Muhafız maddeleri bununla ilgili.

Bununla birlikte, meslektaşınızın tekniğinin, boşluksuz, çok kötü bir yığılmış koşullu blok kalıbını kısmen çözebileceğine dikkat edin:

if (something)
{
}
if (other)
{
}
else
{
}

Önceki kodda, ilk satırdan sonra mantıklı bir satır sonu olmaması ifkodu yanlış yorumlamayı çok kolaylaştırır. Bununla birlikte, iş arkadaşınızın kuralı kodu yanlış okumayı zorlaştırırken, daha kolay bir çözüm basitçe yeni bir satır eklemek olacaktır.

İçin test true değil,false

İkinci kural biraz mantıklı gelebilir, fakat şu anki haliyle değil.

Kapalı bir kapı için yapılan testlerin, açılmayan bir kapı için yapılan testlerden daha sezgisel olduğu yanlış değildir . Olumsuz görüşmeler ve özellikle iç içe geçmiş olumsuzlukların anlaşılması genellikle zordur:

if (!this.IsMaster || (!this.Ready && !this.CanWrite))

Bunu çözmek için, boş bloklar eklemek yerine , gerektiğinde veya yerel değişkenler ek özellikler yaratın .

Yukarıdaki durum kolayca okunabilir hale getirilebilir:

if (this.IsSlave || (this.Synchronizing && this.ReadOnly))

169
Boş bloklar her zaman bana hata gibi gelir. Hemen dikkatimi çekecek ve 'Neden burası burada?'
Nelson

50
@Neil Bir koşulu olumsuzlamak ille de herhangi bir CPU zamanı gerektirmez. X86 için derlenen c, atlama komutunu JZ(Sıfır ise Zıpla) if (foo)ile JNZ(Sıfır değilse Zıpla) arasında değiştirebilir if (!foo).
8bittree

71
" net adlarla ek özellikler oluşturun ": Etki alanını daha derin bir şekilde analiz edemediğiniz sürece, yerel bir sorunu (belirli bir işletme kuralının uygulaması) çözmek için genel kapsamı (orijinal sınıfı) değiştiriyor olabilir. Burada yapılabilecek bir şey, "var isSlave =! This.IsMaster" gibi istenen duruma sahip yerel boolean'lar oluşturmak ve eğer başka birkaç özellik oluşturmak yerine, yerel boolean'larla varsa uygulayın. Bu nedenle, bir tuz taneciği ile tavsiyede bulunun ve yeni özellikler oluşturmadan önce alanı analiz etmek için biraz zaman ayırın.
Machado

82
Bu, "üç satır kod" ile ilgili değildir, uygun kitleye (en azından temel bir programlama bilgisine sahip olan biri için) yazmakla ilgilidir. An if, koşulun yanlış olabileceği veya bunun için test yapamayacağınız konusunda zaten açıktır. Boş bir blok, işleri daha az netleştirir, daha fazlasını değil, çünkü onu beklemek için hiçbir okuyuculu kullanılmaz ve şimdi oraya nasıl ulaşabileceğini düşünmek zorunda kalmazlar.
Ocaklar

15
@Mark, yorumda bile, söylemekten daha az net if (!commonCase) { handle the uncommon case },.
Paul

62

İlk kurala gelince, bu işe yaramaz bir yazma örneğidir. Sadece yazmak daha uzun sürmekle kalmaz, aynı zamanda kodu okuyan herkes için büyük miktarda karışıklığa neden olur. Kod gerekli değilse, yazmayın. Bu else, kod ifbloğundan döndüğünde davanızda doldurulmayacak kadar uzar:

if(condition) 
{
    doStuff();
    return whatever;
}

doSomethingElse(); // no else needed
return somethingelse;

İkinci noktaya gelince, negatif içeren boolean adlardan kaçınmak iyidir:

bool doorNotOpen = false; // a double negative is hard to reason
bool doorClosed = false; // this is much clearer

Bununla birlikte, bunu, bir negatif için tekrar test etmemeye genişletmek, belirttiğiniz gibi, daha işe yaramaz bir şekilde yazmaya yol açar. Aşağıdakiler boş bir ifbloğa sahip olmaktan çok daha net :

if(!condition)
{
    doStuff();
    return whatever;
}

120
Yani ... çift negatifin hayır-hayır olduğunu söyleyebilirsin? ;)
Patsuan

6
@ Patuan, çok akıllıca. Bunu sevdim. :)
David Arno

4
Birçok insanın, iadeleri olan başkalarının nasıl ele alınması gerektiği konusunda hemfikir olmayacağını, hatta bazılarının her senaryoda aynı şekilde ele alınmaması gerektiğini söyleyebileceğini hissediyorum. Kendim için güçlü bir tercihim yok, ancak bunu yapmanın birçok yolunun ardındaki argümanı kesinlikle görebiliyorum.
Dukeling

6
Açıkçası, if (!doorNotOpen)korkunç. Bu yüzden isimler mümkün olduğunca olumlu olmalıdır. if (! doorClosed)Tamamen iyi.
David Schwartz

1
Kapı örneğinizle ilgili olarak, iki örnek adı mutlaka aynı değildir. Fiziksel dünyada açık ve kapalı olmak arasında bir geçiş hali olduğu ile doorNotOpenaynı değildir doorClosed. Endüstriyel uygulamalarımda bunu her zaman görüyorum boolean devletler fiziksel sensörler tarafından belirlendi. Kapının açık tarafında tek bir sensör varsa, yalnızca kapının açık veya açık olmadığını söyleyebilirsiniz. Aynı şekilde, sensör kapalı tarafta ise, sadece kapalı veya kapalı diyebilirsiniz. Ayrıca sensörün kendisi, mantık durumunun nasıl doğrulandığını belirler.
Peter M,

45

1. Boş elseifadeler lehine bir tartışma .

Çoğu zaman, o ilk yapıya benzeyen bir şeyi, boş olanı kullanır (ve tartışırız). Programcının durum hakkında bazı düşünceler içerdiğini kod okuyucularına (hem insan hem de otomatik analiz araçları) bildirir. elseOlması gereken eksik ifadeler insanları öldürdü, araçları düştü ve milyonlarca dolara mal oldu. MISRA-C, örneğin, en azından eksik finalin bir sırada kasıtlı olduğunu söyleyen bir yorumu zorunlu kılar if (condition_1) {do_this;} else if (condition_2) {do_that;} ... else if (condition_n) {do_something_else;}. Diğer yüksek güvenilirlik standartları daha da ileri düzeydedir: birkaç istisna dışında, eksik beyanlar yasaktır.

Bir istisna, satırları boyunca basit bir yorumdur /* Else not required */. Bu, üç satır başka boş olduğu gibi aynı amacı işaret eder. Boş olanın gerekmediği bir başka istisna, hem kodun okuyucuları hem de gereksiz olanı boşaltan otomatik analiz araçlarının açıkça görülmesidir. Örneğin, if (condition) { do_stuff; return; }Benzer şekilde, yerine throw somethingveya goto some_label1 yerine boş bir başkasına gerek yoktur return.

2. if (condition)üzerinden tercih için bir argüman if (!condition).

Bu bir insan faktörüdür. Karmaşık boole mantığı birçok insanı harekete geçirir. Tecrübeli bir programcının bile düşünmesi gerekecek if (!(complex || (boolean && condition))) do_that; else do_this;. En azından, bunu tekrar yaz if (complex || (boolean && condition)) do_this; else do_that;.

3. Bu, birinin boş thenifadeleri tercih etmesi gerektiği anlamına gelmez .

İkinci bölüm "sen" yerine "tercih" diyor. Bu bir kuraldan ziyade bir kılavuzdur. Bu kılavuzun olumlu ifkoşulları tercih etmesinin nedeni , kodun açık ve net olması gerektiğidir. Boş bir boş cümlesi (örneğin, if (condition) ; else do_something;) bunu ihlal ediyor. Programlanmış bir programdır ve en deneyimli programcıların bile ifdurumu olumsuzlanmış haliyle yedeklemesine ve tekrar okumasına neden olur . Öyleyse ilk etapta olumsuzlanmış biçimde yazın ve else ifadesini atlayın (ya da zorunlu kılınması durumunda bu konuda boş bir yorum veya yorum yapın).



1 Sonra ile sona hükümler yazdı return, throwya gotobaşka boş gerektirmez. Aksi cümlenin gerekli olmadığı açıktır. Peki ya goto? Bir kenara bırakıldığında, güvenlik açısından kritik öneme sahip programlama kuralları bazen erken dönüşe izin vermez ve neredeyse her zaman atma istisnalarına izin vermez. Bununla birlikte, gotosınırlı bir biçimde izin verirler (örneğin, goto cleanup1;). Bu sınırlı kullanım, gotobazı yerlerde tercih edilen uygulamadır. Örneğin, Linux çekirdeği bu tür gotoifadelerin tam anlamıyla doludur .


6
!ayrıca kolayca göz ardı edilir. Çok özlü.
Thorbjørn Ravn Andersen

4
Hayır, boş bir başkası, programcının içine bir düşünce koyduğunu açıkça belirtmez. Daha fazla kafa karışıklığına yol açıyor "Planlanan bazı açıklamalar var mıydı ve unuttular mı ya da neden boş bir madde olduğunu?" Bir yorum çok açık.
Simon,

9
@Simon: Tipik bir form else { /* Intentionally empty */ }veya bu satırlar boyunca bir şey. Boş olan kısım, kural ihlali düşüncesizce düşünen statik analizörü tatmin eder. Yorum, okuyuculara boş olanın kasıtlı olduğunu bildirir. Sonra tekrar, tecrübeli programcılar tipik olarak yorumu gereksiz - ama boş bırakmaz. Yüksek güvenilirlik programlama kendi başına bir etki alanıdır. Yapılar yabancılara oldukça garip görünüyor. Bu yapılar sert darbeler okulundan çıkarılan dersler, hayat ve ölüm ya da $$$$$$$$$ elindeyken çok zor olan darbeler nedeniyle kullanılmaktadır.
David Hammen

2
Boş cümleciklerin olmadığı durumlarda cümleciklerin ne kadar boş olduğunu anlamıyorum (bu tarzı seçtiğimizi varsayarak). Görebiliyorumif (target == source) then /* we need to do nothing */ else updateTarget(source)
Bergi

2
@ ThorbjørnRavnAndersen hayır, notdiğer bitsel ve mantıksal operatörler gibi C ++ dilinde bir anahtar kelimedir. Alternatif operatör temsillerine bakın .
Ruslan

31

Çok nadir durumlarda boş bir başka dal (ve bazen boş bir açık dal) kullanırım: Hem eğer hem de diğer kısımların bir şekilde ele alınması gerektiği açık olduğunda, ancak önemsiz olmayan bir nedenden dolayı durumun ele alınabileceği hiçbir şey yapmamak. Bu nedenle, gerekli olan başka bir eylemle kodu okuyan herkes derhal bir şeyin eksik olduğundan şüphelenir ve zamanını boşa harcar.

if (condition) {
    // No action needed because ...
} else {
    do_else_action()
}

if (condition) {
    do_if_action()
} else {
    // No action needed because ...
}

Ama değil:

if (condition) {
    do_if_action()
} else {
    // I was told that an if always should have an else ...
}

5
Bu. Ben ifadeyi if test succeeds -> no action needed -> else -> action neededanlamsal olarak ifadeden çok farklı buluyorum if it applies that the opposite of a test outcome is true then an action is needed. Martin Fowler'in teklifini hatırlattığım: "herkes bilgisayarların anlayabileceği kod yazabilir; iyi programcılar kod anlayabilen insanlar anlayabilir".
Tasos Papastylianou

2
@TasosPapastylianou Bu hile. 'Test başarılı olursa -> hiçbir işlem gerekli değildir' ifadesi, 'test başarılı olmazsa -> işlem gerekli' ifadesidir. 10 kelimeyle doldurdun.
Jerry B

@ JerryB "test" e bağlıdır. Bazen olumsuzluk (dilsel olarak) basittir, ancak bazen değildir ve karışıklığa yol açar. Bu gibi durumlarda, “sonucun doğru olmadığı yönündeki olumsuzluk / olumsuz” veya “sonucun doğru olmadığı”; Bununla birlikte, mesele, 'boş' bir adım atmanın ya da değişken isimlerinin anlamını tersine çevirmenin daha net olacağıdır. Bu "de morgan" durumlarında tipiktir: örneğin if ((missing || corrupt) && !backup) -> skip -> else do stuff, çok daha açık (+ farklı ima edilen niyet)if ((!missing && !corrupt) || backup) -> do stuff
Tasos Papastylianou

1
@TasosPapastylianou Yazabilirsiniz if(!((missing || corrupt) && !backup)) -> do stuffya da daha iyisi if((aviable && valid) || backup) -> do stuff. (Ancak gerçek bir örnekte, kullanmadan önce yedeklemenin geçerli olup olmadığını kontrol etmeniz gerekir)
12431234123412341234123

2
@TasosPapastylianou söylediklerimde çift olumsuzluklar var? Elbette, eğer değişken bir isim olarak bozulmamış kullanıyorsanız, o zaman açık bir noktaya sahip olursunuz. Böyle boolean operatörleri karıştırdığınızda, bu durumda kullanmak için geçici değişkenler kullanmak daha iyi olabilirif : file_ok = !missing && !corrupt; if(file_ok || backup) do_stuff();şahsen bunu daha da netleştirir.
Baldrickk

23

Diğer her şey eşit olduğunda, kısalık tercih eder.

Yazmadığın şeyi kimse okumalı ve anlamalı.

Açık olmak yararlı olsa da, bu, yalnızca, yazdığınızın gerçekten yazmak istediğin şeyin gereğinden fazla bir ayrıntı olmadan açıkça ortaya çıkması durumunda ortaya çıkar.


Bu nedenle, boş dallardan kaçının, sadece işe yaramazlar, aynı zamanda nadir görülürler ve bu nedenle karışıklığa yol açarlar.

Ayrıca, doğrudan if-dalından çıkarsanız başka bir dal yazmaktan kaçının.

Açıklığın kullanışlı bir uygulaması, anahtar davalardan düştüğünüzde bir yorum koymak // FALLTHRUve boş bir ifadeye ihtiyaç duyduğunuz bir yorum veya boş bir blok kullanmak olacaktır for(a;b;c) /**/;.


7
// FALLTHRUUgh, SCREAMING CAPS'ta veya txtspk kısaltmalarıyla değil. Aksi takdirde, bu uygulamayı kendim kabul edip takip ederim.
Cody Gray,

7
@CodyGray - Burası SHOUTING'in iyi bir fikir olduğu bir yer. Çoğu anahtar ifadesi her durumu ile sonlandırır break. Bunun yapılmaması, breakbazı muhteşem yazılım arızalarına yol açmıştır. Bu kasıtlı olduğu kod okuyucularına bağırır bir yorum iyi bir şeydir. Statik analiz araçları bu özel kalıbı arayabilir ve durumun düşmesinden şikayet etmemeyi daha da iyi bir şey yapar.
David Hammen

1
@Wossname: Sadece benim kontrol ettim vimve herhangi bir varyasyonunu tanımıyor FALLTHRU. Ve bence, iyi bir sebepten dolayı: TODOve FIXMEyorumlar, elinizde olması gereken yorumlardır çünkü kodunuzdaki git grephangi bilinen kusurlarınızı ve nerede bulunduğunu sormak isteyebilirsiniz . Bir çöküntü bir kusur değildir ve bunun için aşınmak için hiçbir neden yoktur.
cmaster

4
@DavidHammen Hayır, bağırmak iyi bir fikir değildir: Beklenen bir mola yerine // girmeniz durumunda; herhangi bir geliştiricinin derhal anlaması yeterli olacaktır. Ayrıca, // bu sorun bir kusurdan bahsetmiyor, sadece koşulların göz önüne alındığını ve kırılmayı işaret ediyor; eksik gibi görünen, aslında orada olmaması amaçlanmıştır. Bu tamamen bilgi amaçlı bir amaçtır ve bağırması gereken hiçbir şey yoktur.
cmaster

1
@cmaster - Bağırmak iyi bir fikir değil, senin fikrin. Diğer insanların görüşleri farklıdır. Ve sırf senin tanımadığı vim konfigürasyonu FALLTHRUdiğer insanların bunu yapmak için vim yapılandırılmamış anlamına gelmez.
David Hammen

6

Bir IF beyanı için pozitif veya olumsuz koşullar hakkında benim bilgime değil, sert ve hızlı bir kural yoktur. Kişisel olarak , olumsuz durumlarda değil, olumlu durumlarda da kodlamayı tercih ederim . Bunu kesinlikle yapmayacağım, eğer boş bir IF bloğu yapmama neden oluyorsa, ardından mantık dolu bir ELSE. Eğer böyle bir durum ortaya çıkarsa, yine de olumlu bir durum için test yapmak üzere yeniden ateşlenmesi 3 saniye alacaktır.

Yine de örneklerinizden gerçekten hoşlanmadığım şey, boş ELSE'in kapladığı tamamen gereksiz dikey alan. Bunu yapmak için hiçbir sebep yok. Mantığa hiçbir şey eklemiyor, kodun ne yaptığını belgelemeye yardımcı olmuyor ve okunabilirliği hiç arttırmıyor. Aslında, eklenen dikey boşluğun okunabilirliği azaltabileceğini savunuyorum .


2
Bu gereksiz dikey boşluğun, her zaman parantez kullanmak, başkalarını kaçırmamak ve Allman stilini girintiliğe almak için verilen görevlerin bir sonucudur.
David Hammen

Her zaman ayraç kullanmanın iyi bir şey olduğunu düşünürdüm, çünkü geliştiricilerin niyetlerini açıkça belirtiyor - kodlarını okurken tahminde bulunmaya gerek yok. Bu aptalca gelebilir, ama bana güven, özellikle de genç geliştiricilere danışmanlık yaparken, eksik teller ile ilgili hatalar olur. Ben şahsen hiç bahsetmediğin nedenden dolayı, Allman tarzı girintinin hayranı olmadım: gereksiz dikey alan. Ama bu sadece benim görüşüm ve kişisel tarzım. Sadece başlangıçta öğrendiğim şeydi, bu yüzden okumak her zaman daha rahat hissettirdi.
Langecrew

Kişisel stil: Hangi ayraç stilini kullanırsam kullanayım (Allman, 1TB, ...), her zaman diş telleri kullanırım.
David Hammen

Karmaşık şartlandırmalar veya anlamanın zor olacağını düşündüğünüz durumlar, her zaman kendi metotlarına / fonksiyonlarına yeniden dahil edilerek çözülebilir. Bunun gibi bir şey if(hasWriteAccess(user,file))altında karmaşık olabilir, ancak bir bakışta sonucun tam olarak ne olacağını biliyorsunuzdur. Sadece birkaç koşul olsa bile, örneğin if(user.hasPermission() && !file.isLocked())uygun bir isme sahip bir yöntem çağrısı bu noktaya değinir, böylece negatifler daha az sorun yaratır.
Chris Schneider,

Kabul. Sonra tekrar, mümkün olduğunda yeniden
yapılanma

5

Açık elseblok

Tüm ifadeleri kapsayan bir battaniye ifadesi olarak buna katılmıyorum, ifancak elsealışkanlık dışı bir blok eklemek iyi bir şeydir.

ifAklıma göre bir açıklama aslında iki farklı işlevi kapsar.

Bir şey yapmamız gerekiyorsa, burada yap.

Bu gibi şeyler tabii ki yok değil bir ihtiyaç elseparçasını.

    if (customer.hasCataracts()) {
        appointmentSuggestions.add(new CataractAppointment(customer));
    }
    if (customer.isDiabetic()) {
        customer.assignNurse(DiabeticNurses.pickBestFor(customer));
    }

ve bazı durumlarda bir elseyanıltıcı madde eklemek konusunda ısrar ediyorlar.

    if (k > n) {
        return BigInteger.ZERO;
    }
    if (k <= 0 || k == n) {
        return BigInteger.ONE;
    }

olduğu değil aynı

    if (k > n) {
        return BigInteger.ZERO;
    } else {
        if (k <= 0 || k == n) {
            return BigInteger.ONE;
        }
    }

işlevsel olarak aynı olmasına rağmen. İlkini ifboş elsebırakmak, gereksiz yere çirkin olan ikinci sonuca götürebilir.

Belirli bir durumu kontrol ediyorsak, sadece bu olayı ele elsealmanızı hatırlatmak için boş eklemek iyi bir fikirdir.

        // Count wins/losses.
        if (doors[firstChoice] == Prize.Car) {
            // We would have won without switching!
            winWhenNotSwitched += 1;
        } else {
            // We win if we switched to the car!
            if (doors[secondChoice] == Prize.Car) {
                // We picked right!
                winWhenSwitched += 1;
            } else {
                // Bad choice.
                lost += 1;
            }
        }

Bu kuralların yalnızca yeni kod yazarken geçerli olduğunu unutmayın . IMHO Boş elsemaddeler, check-in işleminden önce kaldırılmalıdır.


Deney içintrue değil,false

Yine, bu genel düzeyde iyi bir tavsiyedir ancak çoğu durumda kodu gereksiz yere karmaşık hale getirir ve daha az okunabilir hale getirir.

Gibi kod gibi

    if(!customer.canBuyAlcohol()) {
        // ...
    }

okuyucuya engel oluyor

    if(customer.canBuyAlcohol()) {
        // Do nothing.
    } else {
        // ...
    }

En azından daha kötüsü yoksa kötüdür.

Ben yıllar önce BCPL içinde kodlanmış ve bu dilde bir orada IFhüküm ve bir UNLESSçok daha okunabilecek şekilde kod böylece fıkra:

    unless(customer.canBuyAlcohol()) {
        // ...
    }

Bu önemli ölçüde daha iyi, ama yine de mükemmel değil.


Benim kişisel süreç

Genel olarak, yeni bir kod yazarken, bu olayı henüz henüz kapsamadığımı hatırlatmak elseiçin sık sık boş bir blok ekleyeceğim if. Bu DFStuzaktan kaçınmama yardımcı oluyor ve kodu gözden geçirdiğimde yapacak daha çok şey olduğunun farkına varmamı sağlıyor. Ancak, genellikle TODOtakip etmek için bir yorum eklerim .

  if (returnVal == JFileChooser.APPROVE_OPTION) {
    handleFileChosen();
  } else {
    // TODO: Handle case where they pressed Cancel.
  }

Genellikle elsekodumda nadiren kullandığımı biliyorum, çünkü kod kokusunu sıklıkla gösterebilir.


"Boş" blokları kullanımınız standart dişleri uygularken standart taslak kodu gibi okuyor ...
Deduplicator

unlessBlok iyi bir öneri olduğunu ve pek BCPL sınırlı.
tchrist

@ TobySpeight Hata! Her nasılsa, yazdıklarımın ...gerçekte olduğu gibi dikkatimden kaçtı return. (Aslında, ile k=-1,n=-2 ilk dönüş almış ama bu büyük ölçüde tartışmaya açıktır edilir.)
David Richerby

Modern Perl ifve var unless. Dahası, aynı zamanda bir açıklamada sonrasında bu izin verir, bu yüzden diyebilirsiniz print "Hello world!" if $born;veyaprint "Hello world!" unless $dead; her ikisinin de tam olarak yaptıklarını düşündüğünüzü yaparsınız.
17'de CVn

1

İlk olarak, IF ifadelerini bu şekilde kullanılmaya zorlayan bir dil kullandım (Opal'de, bir GUI ön ucunu ana sistemlere koymak için bir ana ekran perdesi sıyırıcısının arkasındaki dil) ve IF için yalnızca bir satır kullandım ve ELSE. Hoş bir deneyim değildi!

Herhangi bir derleyicinin bu ek ELSE maddelerini optimize etmesini beklerdim. Ancak canlı kod için hiçbir şey eklemiyor (geliştirme aşamasında daha fazla kod için yararlı bir işaret olabilir).

CASE / WHEN tipi işlemede bu fazladan cümle gibi bir şey kullandığım zamandır. Boş olsa bile daima varsayılan bir fıkra ekliyorum. Bu, uzun süredir böyle bir cümle kullanılmazsa hata çıkaran dillerin alışkanlığıdır ve işlerin gerçekten yerine getirilmesi gerekip gerekmediğine dair bir düşünceyi zorlar.

Uzun zaman önce anabilgisayar (örneğin, PL / 1 ve COBOL) uygulaması, negatif kontrollerin daha az verimli olduğu kabul edildi. Bu, 2. noktayı açıklayabilir, ancak bugünlerde mikro optimizasyon olarak göz ardı edilen çok daha önemli verimlilik tasarrufları olmasına rağmen.

Negatif mantık, bu kadar basit bir IF ifadesinde çok fazla olmasa da, daha az okunabilir olma eğilimindedir.


2
Anlıyorum, bu yüzden oldu bir noktada yaygın bir uygulama.
Patsuan,

@Patsuan - evet, bir ölçüde. Her ne kadar anabilgisayar montajcısı performans kritik kodu için ciddi bir alternatifti.
Kickstart

1
"Uzun zaman önce ... olumsuz çeklerin daha az verimli olduğu kabul edildi." Eh, onlar olan derleyici optimize sürece if !A then B; else Cetmek if A then C; else B. Koşulun olumsuzluğunun hesaplanması, ekstra bir CPU talimatıdır. (Söyleyeceğiniz gibi, bunun önemli ölçüde daha az verimli olması pek mümkün değildir .)
David Richerby

@DavidRicherby Genel olarak konuşuyorsak, bazı diller bu tür optimizasyonları gerçekten zorlaştırabilir. Örneğin, C ++ 'ı aşırı yüklenmiş !ve ==operatörlerle birlikte alın . Aslında kimsenin bunu yapması
gerekmiyor

1

İkinci olarak, boş elseblokların hemen hemen her zaman zararlı bir elektronik mürekkep israfı olduğuna dair cevapların çoğunu söylerdim . Bunu yapmak için çok iyi bir nedeniniz yoksa bunları eklemeyin, bu durumda boş blok hiç boş olmamalıdır, neden orada olduğunu açıklayan bir yorum içermelidir.

Olumsuzluklardan kaçınmayla ilgili sorun yine de biraz daha fazla ilgiyi hak ediyor: Genellikle, bir boole değeri kullanmanız gerektiğinde, ayarlandığında çalışmak için bazı kod bloklarına ve ayarlanmadığında çalışmak için diğer bazı bloklara ihtiyacınız vardır. Dolayısıyla, negatif olmayan bir kural uygularsanız,if() {} else {...} ifadeleri (boş bir ifblokla!) da reddedilen değerini içeren her bir boole için ikinci bir boolean yaratırsınız. Her iki seçenek de okuyucuların kafasını karıştırdığından kötü.

Yararlı bir politika şudur: Asla bir booleanın adı içinde olumsuzlanmış bir form kullanmayın ve olumsuzlamayı tek olarak ifade edin !. Gibi bir ifade if(!doorLocked)tamamen açık, if(!doorUnlocked)düğüm beyin gibi bir ifadedir . Daha sonra ifade türü, !bir if()koşulda tek bir kişinin varlığı değil, ne pahasına olursa olsun kaçınmanız gereken şeydir .


0

Bunun kesinlikle kötü bir uygulama olduğunu söyleyebilirim. Başka ifadeler eklemek, kodunuza hiçbir şey yapmayan ve okumayı daha da zorlaştıran çok sayıda anlamsız satır ekleyecektir.


1
Performansınızı, dönem başına üretilen SLOC'lere göre derecelendiren bir işveren için hiç çalışmadığınızı duydum ...
CVn

0

Boş bir if-blok olan ikinci durumu ele almakla ilgili henüz bahsetmemiş başka bir kalıp var. Bununla başa çıkmanın bir yolu, if bloğuna geri dönmek olacaktır. Bunun gibi, böyle:

void foo()
{
    if (condition) return;

    doStuff();
    ...
}

Bu, hata koşullarını kontrol etmek için kullanılan yaygın bir kalıptır. Olumlu durum hala kullanılmaktadır ve bunun içi artık bir operasyonun kasıtlı olup olmadığını merak etmek için gelecekteki programcıları bırakmaktan boş değildir. Ayrıca, yeni bir işlev yapmanız gerekebileceğinden okunabilirliği artırabilir (böylece büyük işlevleri daha küçük bireysel işlevlere böler).


0

Başka bir cevapta görmediğim "her zaman başka bir cümleye sahip" argümanını dikkate alırken bir nokta var: işlevsel bir programlama tarzında mantıklı olabilir. Sırala.

İşlevsel bir programlama tarzında, ifadeler yerine ifadelerle ilgilenirsiniz. Dolayısıyla her kod bloğunun bir dönüş değeri vardır - bir if-then-elseifade dahil . Ancak bu, boş bir elsebloğu engeller. Bir örnek vereyim:

var even = if (n % 2 == 0) {
  return "even";
} else {
  return "odd";
}

Şimdi, C stili veya C stili esin kaynağı olan sözdiziminde (Java, C # ve JavaScript gibi, sadece birkaçını belirtmek gibi) dillerde bu garip görünüyor. Ancak böyle yazıldığında çok daha tanıdık geliyor:

var even = (n % 2 == 0) ? "even" : "odd";

elseŞubeyi burada boş bırakmak bir değerin tanımlanmamasına neden olur - çoğu durumda, işlevselliği programlamada geçerli bir durum olmak istediğimiz şey değildir. Tamamen dışarıda bırakmakla aynı şey. Ancak, yinelemeli bir şekilde programlama yaparken her zaman bir elsebloğa sahip olmak için çok az neden belirledim .


0

... bir if ifadesini, içine koymak için bir şey olup olmadığına bakılmaksızın başka bir ifade izlemelidir.

Katılmıyorum if (a) { } else { b(); }olarak yeniden yazılmalı if (!a) { b(); }ve if (a) { b(); } else { }yeniden yazılmalı if (a) { b(); }.

Ancak, nadiren boş bir dalım olduğuna dikkat çekiyor. Bunun nedeni normalde boş olan dallara girdiğimi kaydetmem. Bu sayede sadece log mesajlarının dışında gelişebilirim. Nadiren bir hata ayıklayıcı kullanırım. Üretim ortamlarında hata ayıklayıcı alamazsınız; geliştirmek için kullandığınız araçlarla üretim sorunlarını giderebilmek çok güzel.

İkincisi, yanlış yerine gerçek değerleri test etmek daha iyidir. Bu, '! DoorOpened' değişkeni yerine 'doorClosed' değişkenini test etmenin daha iyi olduğu anlamına gelir

Bununla ilgili karışık hislerim var. Sahip bir dezavantaj doorClosedve doorOpenedpotansiyel olduğunu bilmeniz gerekir kelimeler / terimler sayısını iki katına çıkarır. Diğer bir dezavantaj zaman içinde anlamlıdır doorClosedvedoorOpened değiştirebilir değişebilir (sizden sonra gelen diğer geliştiriciler) ve artık birbirlerinin kesin olarak olumsuzlanamayacağı iki özellikle sonuçlanabilir. Olumsuzluklardan kaçınmak yerine, kodun dilini (sınıf adları, değişken adları vb.) İşletme kullanıcılarının sözlüğüne ve verdiğim gereksinimlere uyarlamaya değer veriyorum. Önlemek için tamamen yeni bir terim yapmak istemem!Bu terimin yalnızca işletme kullanıcılarının anlayamayacağı bir geliştirici için anlamı varsa. Geliştiricilerin, kullanıcılar ve yazma gereksinimleri ile aynı dili konuşmasını istiyorum. Şimdi eğer yeni terimler modeli sadeleştirirse, o zaman bu önemlidir, ancak şartlar sonuçlanmadan önce değil sonra ele alınmalıdır. Geliştirme, kodlamaya başlamadan önce bu sorunu çözmelidir.

İçgüdülerimden şüphe duymaya meyilliyim.

Kendini sorgulamaya devam etmek iyidir.

İyi mi / kötü mü / "farketmez" alıştırması mı?

Bir dereceye kadar bunun bir önemi yok. Kodunuzu gözden geçirin ve ekibinize uyarlayın. Bu genellikle yapılacak doğru şeydir. Ekibinizdeki herkes belirli bir şekilde kodlamak isterse, bu şekilde yapmak en iyisidir (1 kişiyi değiştirmek - kendiniz - bir grup insanı değiştirmekten daha az hikaye puanı alır).

Yaygın pratik mi?

Boş bir dal gördüğünü hiç hatırlayamıyorum. Olumsuzluktan kaçınmak için insanların yeni özellikler eklediğini görüyorum.


0

Sorunun sadece ikinci kısmını ele alacağım ve bu, endüstriyel sistemlerde çalışma ve gerçek dünyadaki cihazları manipüle etme bakış açımdan geliyor.

Ancak bu, bir cevaptan ziyade, genişletilmiş bir yorumdur.

Belirtildiği zaman

İkincisi, yanlış yerine gerçek değerleri test etmek daha iyidir. Bu, '! DoorOpened' değişkeni yerine 'doorClosed' değişkenini test etmenin daha iyi olduğu anlamına gelir

Argümanı, kodun ne yaptığını daha açık hale getirdiğidir.

Benim görüşüme göre, burada en azından üçlü bir durum olduğunda kapı durumunun ikili bir durum olduğu varsayılmaktadır:

  1. Kapı açık.
  2. Kapı tamamen açık veya tamamen kapalı değil.
  3. Kapı kapatıldı.

Böylece, tekli, ikili bir dijital sensörün bulunduğu yere bağlı olarak, yalnızca iki konseptten birini tahmin edebilirsiniz:

  1. Sensör kapının açık tarafında ise: Kapı açık veya açık değil
  2. Sensör kapının kapalı tarafında ise: Kapı kapalı veya kapalı.

Ve bu kavramları ikili bir olumsuzlama kullanarak değiştiremezsiniz. Böylece doorClosedve !doorOpenedmuhtemelen eş anlamlı değildir ve onlar eşanlamlı olduklarını iddia yönelik herhangi bir girişimin gerçekte olandan daha sistem durumunun daha büyük bir bilgi varsayar hatalı düşünmedir.

Sorunuza geri dönerken, değişkenin temsil ettiği bilgilerin kaynağına uyan sözlüğü destekleyeceğim. Bilgi daha sonra devam kapının kapalı tarafı elde edilir Bu nedenle, eğer doorClosedvb Bu kullanılarak anlamına gelebilir ya doorClosedveya !doorClosedreddi kullanımı ile bir karışıklık sonuçlanan gerektirdiği şekilde çeşitli tablolarda, gerektiği şekilde. Ancak yapmaması gereken, sistemin durumuna ilişkin varsayımları dolaylı olarak yaymaktır.


Yaptığım işin tartışma amaçları için, sistemin durumu hakkında edindiğim bilgi miktarı, genel sistemin kendisi için gerekli olan işlevselliğe bağlıdır.

Bazen sadece kapının kapalı mı yoksa kapalı mı olduğunu bilmem gerekir. Bu durumda sadece tek bir ikili sensör yeterli olacaktır. Ancak diğer zamanlarda kapının açık, kapalı ya da geçiş halinde olduğunu bilmem gerekiyor. Bu gibi durumlarda ya iki ikili sensör (her bir kapı hareketinin en uç noktasında - kapının aynı anda açık ve kapalı olmasına karşı hata kontrolü ile) ya da kapının ne kadar 'açık' olduğunu ölçen bir analog sensör olacaktır.

Birincinin bir örneği, mikrodalga fırın üzerindeki kapı olabilir. Kapının kapalı veya kapalı olmasına göre fırının çalışmasını sağlarsınız. Kapının ne kadar açık olduğu umrumda değil.

İkincisinin bir örneği, basit bir motor tahrikli aktüatör olabilir. Aktüatör tamamen dışarıdayken motoru ileri sürmeyi engellersiniz. Aktüatör tamamen içeri girdiğinde motoru geriye doğru sürmeyi engellersiniz.

Temel olarak, sensörlerin sayısı ve türü, istenen işlevselliği elde etmek için neyin ihtiyaç duyulduğuna dair ihtiyaç analizine karşı sensörlerin maliyet analizini yapmaktan ibarettir.


"Benim açımdan, en azından üçlü bir durum olduğunda kapı durumunun ikili bir durum olduğu varsayımı burada yapılıyor:" ve "Kapının kapalı veya kapalı olmasına bağlı olarak fırının çalışmasını sağlıyorsunuz "Kapının ne kadar açık olduğu umurumda değil." birbiriyle çelişmek. Ayrıca, sorunun kapı ve sensörler hakkında olduğunu sanmıyorum.
Sanchises,

@Sanchises İfadeler, bağlam dışına çıkardığınız için çelişkili değildir. İlk ifadeler bağlamda, üçlü bir durumun iki karşıt ikili ölçümünün ikili olumsuzlama ile değiştirilemeyeceği bağlamındadır. İkinci ifade, bir uygulamanın doğru çalışması için yalnızca bir üçlü devlet hakkındaki kısmi bilginin yeterli olabileceği bağlamındadır. Kapılara gelince, OP'ler sorusu başvurulan kapıların açık ve kapalı olduğunu gösteriyor. Sadece verinin nasıl işlendiğini etkileyebilecek bariz bir varsayımı işaret ediyorum.
Peter M,

-1

Somut stil kuralları her zaman kötüdür. Yönergeler iyidir, ancak sonunda, kurallara uymayan bir şeyi yaparak işleri daha net hale getirebileceğiniz durumlar vardır.

Bununla birlikte, boş olan "satırları boşa harcıyor" "ekstra yazma" için çok fazla nefret var, bu sadece kötü. Gerçekten düşey boşluğa ihtiyacınız varsa, parantezleri aynı satıra taşıma argümanını oluşturabilirsiniz, ancak bu bir sorunsa, yine de {ayrı bir satıra koymamanız gerekir.

Başka bir yerde de belirtildiği gibi, başka bir bloğa sahip olmak, açıkça diğer davada bir şey olmasını istemediğinizi göstermek için çok kullanışlıdır. Çok fazla işlevsel programlama yaptıktan sonra (başka bir yerde gerekliyse), @OldCurmudgeon'dan bahsettiğimiz gibi gerçekten iki farklı kullanım durumu olduğundan bahsederseniz, if yazarken her zaman başkalarını düşünmeniz gerektiğini öğrendim. Birinde bir başkası olmalı, bir tane olmamalı. Ne yazık ki, her zaman bir bakışta söyleyebileceğiniz bir şey değil, bir linter ile bile yalnızım, dolayısıyla dogmatik “her zaman başka bir blok koy”.

'Olumsuz' söz konusu olduğunda yine mutlak kurallar kötüdür. Boş olması, eğer başka bir şeye ihtiyaç duymuyorsa, yani hepsini yazmak yerine, tuhaf olabilirse, garip olabilir! ya da bir == yanlış yanlış. Bununla birlikte, olumsuzun mantıklı olduğu birçok durum var. Yaygın bir örnek bir değeri önbelleğe almak olacaktır:

static var cached = null

func getCached() {
    if !cached {
        cached = (some calculation, etc)
    }

    return cached
}

Eğer gerçek (zihinsel / ingilizce) mantık olumsuz içeriyorsa, if ifadesi de olmalıdır.

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.