Я делаю это с плагином NERDTree:
:NERDTreeFind
, затем нажмите m kbd>
. Чтобы переименовать, вы можете выбрать (m)ove the current node
и изменить имя файла. Также есть такие опции, как удаление, копирование, перемещение и т. Д.
Организуйте условия и поместите их в метод.
, например, замените это:
if( a& & n || c && ( ! d || e ) && f > 1 && ! e < xyz ) {
// good! planets are aligned.
buyLotteryTicket();
} else if( ..... oh my ... ) {
}
На это:
if( arePlanetsAligned() ) {
buyLotteryTicket();
} else if( otherMethodHere() ) {
somethingElse();
}
Таким образом, на самом деле не имеет значения, какой стиль вы используете (1, 2 или 3), потому что оператор if четко описывает, какое условие проверяется. Нет необходимости в дополнительных конструкциях.
Дело в том, чтобы сделать код более понятным и самодокументированным. Если вы используете язык программирования OO, вы можете использовать объект для хранения состояния (переменных) и избегать создания методов, принимающих 5-10 параметров.
Это похожие вопросы:
Лучший способ избавиться от вложенных ifs
Есть ли альтернатива этому гиперидентифицированному коду
Вторая ссылка показывает более полный и сложный способ трансформировать всех, кто сопровождает ужасное кошмар в самодокументирующийся код.
Здесь показано, как преобразовать это:
public String myFunc(SomeClass input)
{
Object output = null;
if(input != null)
{
SomeClass2 obj2 = input.getSomeClass2();
if(obj2 != null)
{
SomeClass3 obj3 = obj2.getSomeClass3();
if(obj3 != null && !BAD_OBJECT.equals(obj3.getSomeProperty()))
{
SomeClass4 = obj3.getSomeClass4();
if(obj4 != null)
{
int myVal = obj4.getSomeValue();
if(BAD_VALUE != myVal)
{
String message = this.getMessage(myVal);
if(MIN_VALUE <= message.length() &&
message.length() <= MAX_VALUE)
{
//now actually do stuff!
message = result_of_stuff_actually_done;
}
}
}
}
}
}
return output;
}
в следующее:
if ( isValidInput() &&
isRuleTwoReady() &&
isRuleTreeDifferentOf( BAD_OBJECT ) &&
isRuleFourDifferentOf( BAD_VALUE ) &&
isMessageLengthInRenge( MIN_VALUE , MAX_VALUE ) ) {
message = resultOfStuffActuallyDone();
}
Я предпочитаю первый вариант - быстро сбой чище, понятнее, легче читать и понимать.
Я понимаю, что это не сбой, а концепция по-прежнему применяется. Мне вообще не нравятся вложенные операторы if
.
Вы можете взглянуть на защитное программирование, чтобы гарантировать выполнение контракта на функциональность методов.
public void function(string value, string value2)
{
if (string.IsNullOrEmpty(value1)) throw new ArgumentNullException("value1", "value 1 was not set");
if (string.IsNullOrEmpty(value2)) throw new ArgumentNullException("value2", "value 2 was not set");
DoSomething();
}
Рефакторинг, который вставляется в его собственную функцию. Лучше читать описательное имя функции, чем набор логических выражений.
// leave complex conditional code out, so that we can focus on the larger problem in the function
public void function(string value, string value2)
{
if (MyDescriptiveTestName)
{
DoSomething();
}
}
// encapsulate complex conditional code so that we can focus solely on it.
private bool MyDescriptiveTestName(string value, string value2)
{
if (value != null && value2 == value)
{
return true;
}
return false;
}
Если у вас есть функция с большим количеством условий, я бы использовал оператор switch
, а не ifs. Я также могу разбить детали на несколько функций (или даже классов), если это возможно.
Связанные статьи о переполнении стека :
Могу я порекомендовать книгу Чистый код Роберта К. Мартина, которая предоставляет отличный набор эвристик для написания удобочитаемого и поддерживаемого кода.
Другой вариант - чтобы извлечь условное выражение в другую частную функцию и назвать его так, чтобы оно описывало ваше намерение. Он не очень хорошо работает с поставляемым кодом, поскольку является общим, но он будет выглядеть примерно так:
public void function(string value, string value2)
{
if (valuesAreValidAndEqual(value, value2))
{
DoSomething();
}
}
private void valuesAreValidAndEqual(string value, string value2)
{
return value != null && value2 == value;
}
Очевидно, это более полезно, если имена переменных и имена функций связаны с вашим доменом.
Мне нравится третий вариант, но это действительно зависит от языка. Вы предполагаете, что в третьем случае первая часть оператора завершится ошибкой и не выполнит вторую. Это зависит от языка. Я знаю, что большинство языков на основе C делают это, но, поскольку вы не указали один из них, это потенциальная проблема. Там может быть один, о котором я не знаю, не имеющий концепции короткого замыкания.
Тот факт, что у вас есть такое количество операторов в функции, является признаком того, что функцию следует разделить на более мелкие.
Нет ЛУЧШЕГО способа размещения операторов if, я думаю, ответы субъективны.
Тот факт, что вы заранее думаете о читабельности кода, - это полдела.
Что касается того, какой из ваших примеров наиболее читабелен, это довольно субъективно.
Мои мысли по поводу приведенных примеров:
Я предпочитаю второй вариант. Лично, когда я читаю подобный код, я имею в виду условия, при которых я бы перешел на каждый вложенный уровень. В первом примере я бы, вероятно, забыл, что первое условие (значение == null равно false) продолжает выполняться. Третий тоже неплохой, но я предпочитаю второй.
Ясность зачастую сложно оценить. То, что вам ясно, когда вы пишете кусок кода, может быть совершенно непонятным для кого-то другого - или даже для вас, когда пройдет достаточно времени.
Вот мои личные практические правила при создании функции с множеством условных проверок: