İstisnadan sonra başka bir yöntem kullanın (veya kullanmayın)


9

Şu kod parçasını düşünün:

if (x == 1)
{
  throw "no good; aborting" ;
}

[... more code ...]

Şimdi şu kodu düşünün:

if (x == 1)
{
  throw "no good; aborting" ;
}
else
{
  [... more code ...]
}

İki dava da aynı şekilde çalışıyor. İlk durumda avantajı, kodun geri kalanını bir else. İkincisi, elseher biri için açık bir şekilde sahip olma uygulamasını takip etme avantajına sahiptir if.

Biri diğerinin lehine sağlam argümanlar sağlayabilir mi?


5
Açıkça tercih ettiğiniz uygulama elsesahte görünüyor. Çoğu zaman, elsegeriye doğru bükülmedikçe bloğa konacak hiçbir şey yoktur .

Tutarlılık? Kod değişikliği karşısında sağlamlığa izin verilsin mi? Okunabilirlik?
Thomas Eding

1
Ehhhh, ben her ifihtiyacın olduğu bir fikrin hayranı değilim else. Kod tabanımızda çalışan son programcı bunu katı bir şekilde takip etti ( iyi, bazen ... bu bir tür şizofrenik ). Sonuç olarak, else { /* do nothing */ }kodu
çöpten

4
"Her if için başka bir şey" bir bulut mimar tarafından (aptalca) bir tutarlılık adına yayınlanan bazı tuhaf bildiriler gibi görünüyor. Bu uygulamayı takip etmenin hiçbir avantajını görmüyorum ve hiçbir yerde duymadım bile.
Erik Dietrich

Başka bir şey. .NET yığını ile çalışıyorsanız, ReSharper'ı yükleyin ve diğer tüm gereksiz ifadeleri kaldırmanızı hatırlatacaktır.
CodeART

Yanıtlar:


16

A veya a içerenler gibi kontrol akışını koşulsuz olarak kesen dallardan elsesonra eklememelisiniz . Bu, dal tarafından getirilen gereksiz yuvalama düzeyini kaldırarak programınızın okunabilirliğini artıracaktır .ifthrowreturnelse

throwBir satırda az ya da çok iyi görünen şey , arka arkaya birkaç atış yapıldığında gerçekten çirkinleşir:

void myMethod(int arg1, int arg2, int arg3) {
    // This is demonstrably ugly - do not code like that!
    if (!isValid(arg1)) {
        throw new ArgumentException("arg1 is invalid");
    } else {
        if (!isValid(arg2)) {
            throw new ArgumentException("arg2 is invalid");
        } else {
            if (!isValid(arg3)) {
                throw new ArgumentException("arg3 is invalid");
            } else {
                // The useful code starts here
            }
        }
    }
}

Bu snippet aynı şeyi yapıyor, ancak çok daha iyi görünüyor:

void myMethod(int arg1, int arg2, int arg3) {
    if (!isValid(arg1)) {
        throw new ArgumentException("arg1 is invalid");
    }
    if (!isValid(arg2)) {
        throw new ArgumentException("arg2 is invalid");
    }
    if (!isValid(arg3)) {
        throw new ArgumentException("arg3 is invalid");
    }
    // The useful code starts here
}

+1 Doğru. İkinci OP vakası sizi dikkatlice okumaya zorlar, ardından bir WTF ile bırakır. Ama ... yöntemleri daima kýsa yapmaya çalýţ. 200 satırlık bir yöntemin ortasındaki bir dönüş de kötüdür.
Tulains Córdova

1
Adil olmak gerekirse, sadece tekrarlı kullanıyorsanız, bunu yapabilirsiniz else if.
Guvante

2
@Guvante: Her ifbir durum tek bir durum için test eder ve durum doğruysa bununla ilgilenir ve koşul yanlışsa olması gereken başka bir şey olmadığı sürece else ifs gereksizdir. Ofisimde dasblinkenlight'ın ilk snippet'i gibi kod için bir terim var: " pachinko makineleri."
Blrfl

Blrfl pachinko machines hah, mükemmel benzetme +1
Jimmy Hoffa

@Blrfl: Tekrarlananların çok fazla iç içe yerleştirmenin kötü bir örneği olduğunu belirtiyordum. Zaten iç içe geçiyor olmamanız gerekir. Genel olarak, az miktarda koddan bahsetmediğiniz sürece, dahil etmek için bir neden olmadığını kabul ediyorum else.
Guvante

5

Eğer sizin için başka bir özel durum kodu olmadığı gerçeğini gizlediğinden, bir anti-desen olarak adlandırdığınız "açık başka" uygulamayı çağırırdım.

Okunabilirlik / sürdürülebilirlik, çoğunlukla gerekli kod akışı yapılarından başka bir şeye sahip olmadığınız ve bunları en aza indirdiğinizde geliştirilir. Bu, gereksiz elses anlamına gelir ve tüm bir fonksiyona bir kapsam ekleyecekse, onu takip etmeyi ve sürdürmeyi zorlaştırır.

Diyelim ki bu işleve sahipsiniz:

public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
    if (_validColors.Contains(oblogonToConfigure.Color))
    {
        oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
    }
    else
    {
        oblogonToConfigure.Color = _validColors[0];
        oblogonToConfigure.ColorIndex = 0;
    }
}

Şimdi gereksinim, yapılandırma sırasında oblogon'un tür / tür dizinini de belirtmeniz gerektiğinde, birisinin bu kodu yerleştirebileceği ve geçersiz kodla sonuçlanabileceği birden fazla kapsam olduğu anlamına gelir.

public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
    if (!_validOblogons.Contains(oblogonToConfigure.Type))
    {
        oblogonToConfigure.Type = _validOblogons[0];
        oblogonToConfigure.TypeIndex = 0;
        if (_validColors.Contains(oblogonToConfigure.Color))
        {
            oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
        }
        else
        {
            oblogonToConfigure.Color = _validColors[0];
            oblogonToConfigure.ColorIndex = 0;
        }
    }
    else
    {
        oblogonToConfigure.TypeIndex = _validOblogons.IndexOf(oblogonToConfigure.Type);
    }
}

Orijinal kod, gerekli ve en aza indirgenmiş minimum kontrol akış yapıları ile yazılmışsa, bunu karşılaştırın.

public void ConfigureOblogon(Oblogon oblogonToConfigure)
{
    if (!_validColors.Contains(oblogonToConfigure.Color))
    {
        oblogonToConfigure.Color = _validColors[0];
    }

    oblogonToConfigure.ColorIndex = _validColors.IndexOf(oblogonToConfigure.Color);
}

Şimdi yanlışlıkla yanlış bir şeye yanlış bir şey koymak veya bu fonksiyonun uzun vadeli büyümesinde ve bakımında tekrarlamaya neden olan kapsamları şişirmek çok daha zor olacaktır. Ayrıca, bu işlev aracılığıyla olası akışların ne olduğu açıktır, böylece okunabilirlik artırılmıştır.

Biliyorum, örnek biraz karışık, ama birçok kez gördüm

SomeFunction()
{
    if (isvalid)
    {
        /* ENTIRE FUNCTION */
    }
    /* Nothing should go here but something does on accident, and an invalid scenario is created. */
}

Bu yüzden kontrol akışı yapılarıyla ilgili bu kuralları resmileştirmek, insanların böyle kod yazmaya başladıklarında bir şey koklamak için gerekli sezgiyi geliştirmelerine yardımcı olabileceğini düşünüyorum. Sonra yazmaya başlayacaklar ..

SomeFunction()
{
    if (!isvalid)
    {
        /* Nothing should go here, and it's so small no one will likely accidentally put something here */
        return;
    }

    /* ENTIRE FUNCTION */
}
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.