Derin girintiler nasıl önlenir? [kapalı]


17

Kodumdaki derin girintileri önlemek için hangi adımları ve önlemleri alabilirim?


2
Birçok insan burada yeniden düzenleme hakkında konuşacak. Belki bu sormak için çok fazladır, ancak derinden girintili bazı (çok uzun değil) bir kod yayınladıysanız ve insanlar size nasıl yeniden düzenlediklerini gösterebilirler. Tabii ki, bu muhtemelen soru dilini o zaman özel yapar ...
Paddyslacker

3
Daha küçük bir sekme genişliği kullanın.
mipadi

6
Ok ucu anti-desen. Google, ipuçları bir sürü
NimChimpsky

2
Python kullanmayı bırak: D
back2dos

Kontrol ve döngü mantığınıza bakmanın zamanı geldi. Muhtemelen kodunuz olması gerekenden daha karmaşıktır ve sorunun yeniden kavramsallaştırılması çok daha kısa koda yol açacaktır. İyi kod çalışın ve teknikleri öğrenin.
Macneil

Yanıtlar:


14

Programınızdaki her işlev / yöntem bir ve sadece bir şey yaparsa , derin girinti genellikle bir sorun oluşturmaz. Bazen, koşulluları birkaç seviye derinliğe yerleştirmek gerekebilir , ama dürüstçe söyleyebilirim ki 12+ yıllık kodlamada sadece birkaç kez girintili kod yazdım.


26

Yapabileceğiniz en iyi şey özüt yöntemidir:

int Step1(int state)
{
    if (state == 100)
    {
        return Step2(state);
    }
    else
    {
        return Step3(state);
    }
}

int Step2(int state)
{
    if (state != 100)
    {
        throw new InvalidStateException(2, state);
    }

    // ....
}

2
Bu aynı zamanda karmaşık koşullar için de geçerlidir if. Uç noktaya geldiğinde, çalıştırılabilir sözde kodla sonuçlanacaksın.
Alan Plum

Yapabileceğimiz en iyi şey muhtemelen gereksiz elseblokları düşürmektir .
Haziran 2018

16

Belki nöbet maddelerini düşünebilirsiniz ?

onun yerine

public void DoSomething(int value){
    if (someCondition){
           if(someOtherCondition){
                if(yetAnotherCondition){
                       //Finally execute some code
                }
           }
    }
} 

Yapmak

public void DoSomething(int value){
    if(!(someCondition && someOtherCondition && yetAnotherCondition)){
        return;
        //Maybe throw exception if all preconditions must be true
    }
    //All preconditions are safe execute code
}

Eğer bir şansınız varsa Steve McConnell'in Code Complete'i okumanızı tavsiye ederim. Bu konularda çok büyük tavsiyeleri var.

http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=pd_sim_b_6

"Muhafız hükümleri" hakkında daha fazla bilgi için bakınız: https://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses


8

Anahtar kelimelerinizi ters çevirin if.

Onun yerine:

if (foo != null)
{
    something;
    something;
    if (x)
    {        
       something;
    }
    something;
}
else
{
    boohoo;
}

Yazarım:

if (foo == null)
{
    boohoo;
    return;
}
something;
something;
if (x)
{        
   something;
}
something;

Aynısı if- elseblokları için de geçerlidir . Daha elsekısa / daha az iç içe ise, geri alın.

Parametrelerin değerlerini tek bir yerde kontrol edin

Metodunuzu girer girmez tüm parametreleri geçersiz değerler için kontrol edin, ardından güvenli olduğunuzu bilmeye devam edin. Daha okunabilir kod sağlar, ancak daha sonra koşullu blokları biriktirmenizi ve bu kontrolleri altyordamın her tarafına yaymanızı sağlar.


1
Bu stilin belirli bir adı var mı?
Thomas Lauria

@ThomasLauria bildiğimden değil. Sadece erken çıkıyor. Ifkodun başlangıcında bazı koşulların yerine getirilmemesi nedeniyle yürütme akışını durduran kodlar @ @ JasonTuran'ın işaret ettiği gibi koruma maddeleri olarak da bilinir . Ve bu, farklı bir isme sahip olmak kadar yakın görünüyor.
Konrad Morawski

birkaç yıl önce amirim bana bu tarzın "doğrusal programlama" olarak adlandırıldığını söyledi, ama bence bu onun bir hayaletiydi;)
Thomas Lauria

4

Genellikle, derin girintili kod genellikle sorunlu kod olduğunu gördüm. Bu sorunla karşı karşıyaysanız, geri adım atın ve işlevinizin çok fazla şey yapıp yapmadığını değerlendirin.

Aynı zamanda, sorunuzu cevaplamak için, o kadar derinden girintiye ihtiyaç varsa, orada olmasına izin vermenizi öneririm. Basit bir nedenle, bu kodda girinti çok uzun bir kod parçası olacağından yardımcı olacaktır.


2

Yuvalanmış bileşenleri (özellikle tekrarlananları) ayrı işlevlere ayırın (diliniz kapanmaları destekliyorsa bu daha kolaydır) veya bir dizi iç içe döngüyü özyineleme ile değiştirin.

Ayrıca, dört yerine iki boşluk girin.


5
Sekme genişliğinizi değiştirme adımına gittiğinizde,
başınız büyük

İki boşluklu sekmeler zor şeyler ....
David Thornley

6
Girintiyi değiştirmek sorunu
çözmenin

1

Derin girintileri kaldırılacak kategorik bir sorun olarak görmüyorum (ne de yeniden düzenlemeyi her şeyin gerçek cevabı olarak görmüyorum).

Genellikle iç içe ifs yerine, mantıksal ifadeler yazmak istiyorum:

if (foo && bar && baz) 

ziyade

if foo 
 if bar
   if baz

Sorun şu ki, bu kuralın kapsamına girmeyen döngüler için de var.
Tamara Wijsman

@TomWij: Stil hakkında kategorik bir zorunluluk oluşturmaya çalışmıyorum.
Paul Nathan

1
??? `` `` ``
Tamara Wijsman

1

Kendime inanmadım, ancak Code Complete'e göre burası kullanmak için uygun bir yer break(eğer ekibiniz gemideyse). Bu sadece bir döngü yazmak gibi hissetmiyorum zaman kullanılan Delphi programcılar ile olduğu gibi ifadelerde breakkullanılan olsa da, C ++ programcıları ile daha kabul edilebilir olduğunu hayal ediyorum .switchbreakwhile


0

Girinti gerçekten savaşmayı düşünüyor. Yapmayı öğrendiğim şey, önce yöntemi parçalara bölmek, sonra bir parça başarısız olursa aşağıdaki her parçayı atlamak için garip bir numara kullanmaktır. İşte bir örnek :

Onun yerine :

 {if (networkCardIsOn() == true)
     {if (PingToServer() == true)
        {if (AccesLogin(login,pass) == true)
             {if (nextCondition == true)
                ...
         }
     }
 }

Şu anda yazıyorum:

 {vbContinue = true;

 if (vbContinue) {
       vbContinue = networkCardIsOn();
       if (vbContinue == false) {
             code to Handle This Error();
       } 
 }

 if (vbContinue) {
       vbContinue = PingToServer();
       if (vbContinue == false) {
             code to HandleThisError2();
       } 
 }

 if (vbContinue) {
       vbContinue = AccesLogin(login,pass);
      if (vbContinue == false) {
             HandleThisErrorToo();
       } 
 }
 ...

Bu ilk başta bana garip geldi, ama bunu kullandığımdan beri bakım maliyeti yarıya bölündü ve beynim günün sonunda daha havalı.

Aslında, bu "teknik" ile elde edilen kazanç, kod karmaşıklığının gerçekten bölünmesidir, çünkü kod daha az yoğundur.

Kodu okurken, geçmiş koşullar hakkında hiçbir şey hatırlamanız gerekmez: Kodun o noktasındaysanız, önceki adımlar atılmış ve başarılı olmuştur.

Diğer bir kazanç ise "if-else" ile iç içe olan tüm bu "kaçış yolu ve koşulu" nun basitleştirilmesidir.


"Bakım maliyeti yarıya bölünür" hakkında ayrıntılı bilgi verebilir misiniz? Ayrıca, yürütmeyi durdurduysa hangisini gerçekten bilebilirsiniz?
Chris

Biraz düzenleme yaptım. Umarım sorularınızı cevaplarım ...
Pierre Watelet

2
Hatta basitçe gitmek istiyorsanız, bir error_handling satırınız var.
Paul Nathan

Bu hoş değil. Üzgünüm, ama sadece değil. Sonra tekrar
tuhafım

3
denemek yakalamak taklit yerine neden doğrudan kullanmıyorsunuz?
Newtopian
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.