Які заходи та заходи я можу вжити, щоб запобігти глибоким відступам у своєму коді?
Які заходи та заходи я можу вжити, щоб запобігти глибоким відступам у своєму коді?
Відповіді:
Глибокий відступи зазвичай не проблема , якщо кожна функція / метод у вашій програмі робить одну і тільки одну річ. Іноді, можливо, буде потрібно вкладати умовні умови на кілька рівнів глибоко, але я, чесно можу сказати, що я написав лише глибоко відрізаний код кілька разів за 12+ років кодування.
Найкраще, що ви можете зробити - це методи вилучення:
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);
}
// ....
}
if
. Якщо ви будете до кінця, ви отримаєте виконуваний псевдокод.
else
блоки.
Може, ви могли б розглянути питання про охорону ?
замість
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
Інвертувати свої if
s.
Замість:
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
коротше / менш вкладене, поверніть їх.
Перевірте значення параметрів в одному місці
Перевірте всі параметри на незаконні значення, як тільки ви вводите свій метод, а потім продовжуйте знати, що ви в безпеці. Це забезпечує більш читабельний код, але також заощаджує згодом накопичення умовних блоків і розповсюдження цих чеків по всій підпрограмі.
If
s на початку коду, який зупиняє виконання потоку через невиконання якоїсь умови, також відомі як захисні положення , як, наприклад, @JasonTuran. І це, здається, наближається до того, що має чітке ім'я.
Як правило, я бачив, що глибоко відрізаний код зазвичай є проблематичним кодом. Якщо ви зіткнулися з цією проблемою, тоді відступіться і оцініть, чи ваша функція робить занадто багато речей.
У той же час, щоб відповісти на ваше запитання, чи є необхідність в цьому відступі настільки глибоко, я б запропонував вам дозволити йому бути там. З тієї простої причини, що в такому коді відступ допоможе, оскільки це, ймовірно, дуже довгий фрагмент коду.
Розбийте вкладені компоненти (особливо повторювані) на окремі функції (це простіше, якщо ваша мова підтримує закриття) або замініть ряд вкладених циклів рекурсією.
Також відступ два пробіли замість чотирьох.
Я не бачу глибоких відступів як категоричної проблеми, яку слід усунути (і я не бачу рефакторинг як справжню відповідь на все).
Зазвичай замість вкладених ifs я люблю писати логічні заяви:
if (foo && bar && baz)
а не
if foo
if bar
if baz
Я сам не повірив, але відповідно до Code Complete, це зручне місце для використання break
(якщо ваша команда знаходиться на борту). Я думаю, що це більш прийнятно для програмістів на C ++, хоча там, де він break
використовується у switch
висловлюваннях, ніж у програмах Delphi, де break
використовується лише тоді, коли ви не хочете писати while
цикл.
Відступ - це справді думка боротися. Що я навчився робити, це спершу розділити метод на шматки, а потім скористатися дивним трюком, щоб пропустити всі наступні фрагменти, якщо одна деталь не вдалася. Ось приклад:
Замість :
{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 у коді, попередні кроки проходять і успішно виконуються.
Ще одна вигода полягає в тому, що "шлях та стан втечі" від усіх тих, що вкладені "інше" спрощується.