Як запобігти глибоким відступам? [зачинено]


17

Які заходи та заходи я можу вжити, щоб запобігти глибоким відступам у своєму коді?


2
Тут багато говоритимуть про рефакторинг. Можливо, це занадто багато, щоб запитати, але якби ви розмістили якийсь (не занадто довгий) код з глибоким відступом, і люди могли б показати вам, як вони його переробляють. Звичайно, це, мабуть, робить мову питання специфічною тоді ...
Paddyslacker

3
Використовуйте меншу ширину вкладки.
mipadi

6
Arrowhead анти-шаблон. Google це, безліч підказок
NimChimpsky

2
Перестаньте використовувати python: D
back2dos

Настав час переглянути свою логіку управління та циклу. Ймовірно, ваш код складніший, ніж повинен бути, і повторна концептуалізація проблеми призведе до набагато коротшого коду. Вивчіть хороший код та вивчіть методи.
Macneil

Відповіді:


14

Глибокий відступи зазвичай не проблема , якщо кожна функція / метод у вашій програмі робить одну і тільки одну річ. Іноді, можливо, буде потрібно вкладати умовні умови на кілька рівнів глибоко, але я, чесно можу сказати, що я написав лише глибоко відрізаний код кілька разів за 12+ років кодування.


26

Найкраще, що ви можете зробити - це методи вилучення:

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
Це також працює для складних умов if. Якщо ви будете до кінця, ви отримаєте виконуваний псевдокод.
Алан Плюм

Інше найкраще, що ми можемо зробити - це, ймовірно, скинути непотрібні elseблоки.
sepehr

16

Може, ви могли б розглянути питання про охорону ?

замість

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

Зробіть

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
}

Якщо у вас є можливість, я рекомендую вам прочитати Code Complete від Steve McConnell. У нього багато чудових порад щодо цих тем.

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

Більше про "охоронні положення" див: https://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses


8

Інвертувати свої ifs.

Замість:

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

Я напишу:

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

Те саме стосується if- elseблоків. Якщо elseкоротше / менш вкладене, поверніть їх.

Перевірте значення параметрів в одному місці

Перевірте всі параметри на незаконні значення, як тільки ви вводите свій метод, а потім продовжуйте знати, що ви в безпеці. Це забезпечує більш читабельний код, але також заощаджує згодом накопичення умовних блоків і розповсюдження цих чеків по всій підпрограмі.


1
Чи має цей стиль конкретну назву?
Томас Лаурія

@ThomasLauria не те, що я б знав. Це просто рано. Ifs на початку коду, який зупиняє виконання потоку через невиконання якоїсь умови, також відомі як захисні положення , як, наприклад, @JasonTuran. І це, здається, наближається до того, що має чітке ім'я.
Конрад Моравський

кілька років тому мій керівник сказав мені, що цей стиль був названий "лінійним програмуванням", але я думаю, що це була його фантазія;)
Томас Лаурія

4

Як правило, я бачив, що глибоко відрізаний код зазвичай є проблематичним кодом. Якщо ви зіткнулися з цією проблемою, тоді відступіться і оцініть, чи ваша функція робить занадто багато речей.

У той же час, щоб відповісти на ваше запитання, чи є необхідність в цьому відступі настільки глибоко, я б запропонував вам дозволити йому бути там. З тієї простої причини, що в такому коді відступ допоможе, оскільки це, ймовірно, дуже довгий фрагмент коду.


2

Розбийте вкладені компоненти (особливо повторювані) на окремі функції (це простіше, якщо ваша мова підтримує закриття) або замініть ряд вкладених циклів рекурсією.

Також відступ два пробіли замість чотирьох.


5
Після того, як ви перейшли до кроку зміни ширини вкладки, ви
стикаєтеся

Вкладки з двох просторів - це важкі речі ....
Девід Торнлі

6
Зміна відступу - це лише спосіб приховування проблеми, а не рішення
Мерф

1

Я не бачу глибоких відступів як категоричної проблеми, яку слід усунути (і я не бачу рефакторинг як справжню відповідь на все).

Зазвичай замість вкладених ifs я люблю писати логічні заяви:

if (foo && bar && baz) 

а не

if foo 
 if bar
   if baz

Проблема полягає в тому, що існують також цикли циклів, які не підпадають під це правило.
Тамара Війсман

@TomWij: Я не намагаюся викликати категоричний імператив щодо стилю.
Пол Натан


1

Я сам не повірив, але відповідно до Code Complete, це зручне місце для використання break(якщо ваша команда знаходиться на борту). Я думаю, що це більш прийнятно для програмістів на C ++, хоча там, де він breakвикористовується у switchвисловлюваннях, ніж у програмах Delphi, де breakвикористовується лише тоді, коли ви не хочете писати whileцикл.


0

Відступ - це справді думка боротися. Що я навчився робити, це спершу розділити метод на шматки, а потім скористатися дивним трюком, щоб пропустити всі наступні фрагменти, якщо одна деталь не вдалася. Ось приклад:

Замість :

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

Я зараз пишу:

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

Спочатку це здалося мені дивним, але оскільки я цим користуюся, вартість технічного обслуговування була розділена наполовину, а мій мозок в кінці дня прохолодніший.

Насправді, виграш, який запроваджує ця "техніка", полягає в тому, що складність коду дійсно розділена, оскільки код менш щільний.

Читаючи код, вам не потрібно нічого пам’ятати про минулі умови: якщо ви знаходитесь в цьому пункті X у коді, попередні кроки проходять і успішно виконуються.

Ще одна вигода полягає в тому, що "шлях та стан втечі" від усіх тих, що вкладені "інше" спрощується.


Чи можете ви детальніше розповісти про "витрати на технічне обслуговування розділили навпіл" Крім того, як би ви насправді знали, що якщо зупинено виконання?
Кріс

Я зробив кілька редагувань. Сподіваюся, я відповім на ваші запитання ...
П'єр Уалет

2
Якщо ви хочете пройти навіть просто, у вас є рядок goto error_handling.
Пол Натан

Це не гарно. Вибачте, але його просто немає. Потім я знову дивний
Мерф

3
замість того, щоб наслідувати спробу лову, чому б не використати її безпосередньо?
Ньютопський
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.