Bagaimana mencegah lekukan yang dalam? [Tutup]

17

Langkah dan tindakan apa yang dapat saya ambil untuk mencegah lekukan yang dalam pada kode saya?

Tamara Wijsman
sumber
2
Banyak orang akan berbicara tentang refactoring di sini. Mungkin ini terlalu banyak untuk ditanyakan, tetapi jika Anda memposting beberapa (tidak terlalu lama) kode yang indentasi dalam, dan orang-orang dapat menunjukkan kepada Anda bagaimana mereka akan memperbaikinya. Tentu saja, itu mungkin membuat bahasa pertanyaan spesifik kemudian ...
Paddyslacker
3
Gunakan lebar tab yang lebih kecil.
mipadi
6
Panah anti-pola. Google itu, banyak tips
NimChimpsky
2
Hentikan penggunaan python: D
back2dos
Saatnya untuk melihat kontrol dan loop logika Anda. Kemungkinan kode Anda lebih rumit daripada yang seharusnya, dan konsep ulang masalah akan mengarah pada kode yang jauh lebih pendek. Pelajari kode yang baik dan pelajari tekniknya.
Macneil

Jawaban:

14

Lekukan yang dalam biasanya tidak menjadi masalah jika setiap fungsi / metode dalam program Anda melakukan satu dan hanya satu hal. Kadang-kadang, mungkin perlu untuk bersarang kondisi beberapa tingkat dalam, tapi saya bisa jujur ​​mengatakan saya hanya menulis kode indentasi dalam beberapa kali dalam 12 + tahun pengkodean.

Chinmay Kanchi
sumber
26

Hal terbaik yang dapat Anda lakukan adalah mengekstrak metode:

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);
    }

    // ....
}
Kekacauan Kekacauan
sumber
2
Ini juga berfungsi untuk ifkondisi- kompleks . Dibawa ke ekstrim, Anda akan berakhir dengan pseudocode yang dapat dieksekusi.
Alan Plum
Hal terbaik lainnya yang dapat kita lakukan adalah mungkin menjatuhkan elseblok yang tidak perlu .
sepehr
16

Mungkin Anda bisa mempertimbangkan klausa penjaga ?

dari pada

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

Melakukan

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
}

Jika Anda pernah mendapat kesempatan, saya akan merekomendasikan Anda membaca Kode Lengkap oleh Steve McConnell. Dia punya banyak nasihat bagus tentang topik ini.

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

Untuk informasi lebih lanjut tentang "klausa penjaga" lihat: https://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses

Jason Turan
sumber
8

Balikkan milikmu if.

Dari pada:

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

Saya akan menulis:

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

Hal yang sama berlaku untuk if- elseblok. Jika elselebih pendek / kurang tersarang, maka kembalikan.

Periksa nilai parameter di satu tempat

Periksa semua parameter untuk nilai ilegal segera setelah Anda memasukkan metode Anda, kemudian lanjutkan dengan mengetahui bahwa Anda aman. Itu membuat kode lebih mudah dibaca, tetapi juga menghemat menumpuk blok bersyarat nanti dan menyebarkan cek ini di seluruh subrutin.

Konrad Morawski
sumber
1
Apakah gaya ini memiliki nama tertentu?
Thomas Lauria
@ Thomas Lauria bukan yang saya tahu. Itu hanya keluar awal. IfPada awal kode yang menghentikan aliran eksekusi karena beberapa kondisi yang tidak terpenuhi juga dikenal sebagai klausa perlindungan , seperti yang ditunjukkan oleh @JasonTuran. Dan itu tampaknya sedekat mungkin dengan memiliki nama yang berbeda.
Konrad Morawski
beberapa tahun yang lalu atasan saya memberi tahu saya bahwa gaya ini dinamai sebagai "pemrograman linier", tetapi saya pikir ini adalah bayangannya;)
Thomas Lauria
4

Biasanya, saya telah melihat bahwa kode indentasi dalam biasanya kode bermasalah. Jika Anda menghadapi masalah ini, maka mundur dan evaluasi apakah fungsi Anda melakukan terlalu banyak hal.

Pada saat yang sama, untuk menjawab pertanyaan Anda, jika ada kebutuhan untuk lekukan sedalam itu, saya sarankan Anda membiarkannya ada di sana. Untuk alasan sederhana bahwa dalam kode seperti itu, lekukan akan membantu karena itu kemungkinan merupakan potongan kode yang sangat panjang.

Vaibhav
sumber
2

Hancurkan komponen bersarang (terutama yang berulang) keluar ke fungsi yang terpisah (ini lebih mudah jika bahasa Anda mendukung penutupan) atau ganti serangkaian loop bersarang dengan rekursi.

Juga, indentasi dua spasi, bukan empat.

Hoa Long Tam
sumber
5
Setelah Anda pergi ke langkah mengubah lebar tab Anda, Anda dalam kesulitan besar ...
Daenyth
Tab dua ruang adalah hal yang sulit ....
David Thornley
6
Mengubah indentasi hanyalah cara menyembunyikan masalah bukan solusi
Murph
1

Saya tidak melihat lekukan yang dalam sebagai masalah kategoris yang harus dihapus (saya juga tidak melihat refactoring sebagai jawaban sejati untuk semuanya).

Biasanya alih-alih bersarang, saya suka menulis pernyataan logis:

if (foo && bar && baz) 

daripada

if foo 
 if bar
   if baz
Paul Nathan
sumber
Masalahnya adalah, ada juga ada dan sementara loop yang tidak termasuk dalam aturan ini.
Tamara Wijsman
@ TomWij: Saya tidak mencoba memaksakan imperatif kategoris tentang gaya.
Paul Nathan
1
??? `` `` ``
Tamara Wijsman
1

Saya sendiri tidak percaya, tetapi menurut Code Complete ini adalah tempat yang tepat untuk digunakan break(jika tim Anda ada di papan). Saya membayangkan ini lebih dapat diterima dengan programmer C ++, di mana breakdigunakan dalam switchpernyataan daripada dengan programmer Delphi di mana breakhanya digunakan ketika Anda tidak merasa ingin menulis whileloop.

Peter Turner
sumber
0

Lekukan benar-benar pemikiran untuk bertarung, memang. Apa yang saya pelajari adalah membagi metode menjadi beberapa bagian terlebih dahulu, kemudian menggunakan trik aneh untuk melewati setiap bagian berikut jika salah satu bagian gagal. Berikut ini sebuah contoh:

Dari pada :

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

Saat ini saya menulis:

 {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();
       } 
 }
 ...

Ini terasa aneh bagi saya pada awalnya, tetapi karena saya menggunakan ini, biaya perawatan telah dibagi setengah, dan otak saya lebih dingin pada akhir hari.

Sebenarnya, keuntungan yang diperkenalkan oleh "teknik" ini adalah bahwa kompleksitas kode benar-benar terbagi karena kode kurang padat.

Saat membaca kode, Anda tidak harus mengingat apa pun tentang kondisi sebelumnya: jika Anda berada pada titik X dalam kode, langkah-langkah sebelumnya dilewati dan telah berhasil.

Keuntungan lain adalah "jalan keluar dan kondisi" dari semua yang "bersarang" yang disederhanakan.

Pierre Watelet
sumber
Bisakah Anda menguraikan "biaya pemeliharaan telah dibagi setengah" Juga, bagaimana Anda benar-benar tahu yang mana jika menghentikan eksekusi?
Chris
Saya sudah melakukan beberapa pengeditan. Saya harap saya menjawab pertanyaan Anda ...
Pierre Watelet
2
Jika Anda ingin pergi bahkan hanya, Anda memiliki garis error_handling goto.
Paul Nathan
Itu tidak baik. Maaf, tapi tidak. Kemudian lagi saya aneh
Murph
3
alih-alih meniru coba tangkap mengapa tidak menggunakannya secara langsung?
Newtopian