Нестифирит - это болезнь стилистического программирования, с которой я сталкивался очень часто. Он характеризуется вложенными if
операторами, которые вкладываются все глубже и глубже по мере добавления функциональности. Как только ваш код поймает это, все становится запутанным, и оттуда все идет под откос.
Нестифирит - это паттерн, который меня глубоко не устраивает, и который я часто вижу в коде контроллера, написанном людьми, которые не делают этого много или просто им наплевать. Я упоминаю контроллеры, но вы увидите это в большинстве функций, которые имеют дело с множеством условных выражений, имеющих причинно-следственную цепочку. Выглядит это так:
if ( good_condition_1 ) { // Do work assuming good_condition_1 if ( good_condition_2 ) { // Do more work assuming good_condition_2 if ( good_condition_3 ) { // If all 3 conditions are good, we can do the rest } else { // handle error 3 } } else { // handle error 2 } } else { // handle error 1 }
Кажется знакомым? Я твердо считаю, что это плохо по следующим причинам:
- при вводе всего 3 условий ваш основной код уже имеет трехуровневый отступ. С отступом в 4 пробела и мягким полем на 80 символов вы израсходовали 15% строк в основной части функции с пустым пространством.
- код обработки ошибок становится все дальше и дальше от условия, которое проверялось, что затрудняет понимание. (т.е. вы проверяете условие № 1 вверху, но обрабатываете его как ложное только внизу).
- легко создает действительно глубокую вложенность.
Некоторые из этих вещей случаются просто при первом знакомстве с чем-то, но многие из примеров, которые я вижу, существуют уже много лет, поэтому я пишу это, чтобы, надеюсь, дать вам другой способ думать о вещах, чтобы вы избегали этого раньше, если это возможно. Часть кода причины заканчивается так, как будто это положительный прогноз в коде. Сначала должно быть если (что-то я хочу), а потом мы займемся проблемами, верно?
Что ж ... если мы столкнемся с нашими проблемами, код будет выглядеть так:
if ( ! good_condition_1 ) { // handle error 1 return } // Do work assuming good_condition_1 if ( ! good_condition_2 ) { // handle error 2 return } // Do work assuming good_condition_2 if ( ! good_condition_3 ) { // handle error 3 return } // Do rest of work assuming all 3 conditions are good here
Вы добавляете несколько точек, когда возвращаетесь раньше, но я не думаю, что мы добавили сложности этой функции. Ключевые преимущества такой схемы заключаются в том, что весь код обработки ошибок теперь напрямую связан с условием, которое он обрабатывает, поэтому легче понять, что он делает. Кроме этого, обратите внимание, что теперь у вас есть «счастливый» путь кода без отступов.
Еще одна вещь - это то, что произойдет, если в какой-то момент в будущем вы решите, что good_condition_2 не должно останавливать выполнение функции, а код обработки ошибок должен просто выдавать предупреждение. При втором подходе вы просто удаляете оператор возврата. С первым? Вы либо копируете код, либо вносите изменения, затрагивающие большую часть строк функции.
Это кажется мелочью, когда вы видите, что она выложена таким образом, но не всегда кажется простым, как выбраться из нее, когда она у вас есть. Надеюсь, вы теперь поняли, что такое нестифиритис, как распознать его на ранней стадии и как изменить код, чтобы его избежать.