Вот очень упрощенный пример . Это не обязательно вопрос конкретного языка, и я прошу вас игнорировать многие другие способы написания функции и внесения в нее изменений. , Цвет уникального типа
string CanLeaveWithoutUmbrella()
{
if(sky.Color.Equals(Color.Blue))
{
return "Yes you can";
}
else
{
return "No you can't";
}
}
Многие люди, с которыми я встречался, ReSharper, и этот парень (чей комментарий напомнил мне, что я некоторое время просил об этом) рекомендуют рефакторинг кода, чтобы удалить else
блок, оставив этот:
(Я не могу вспомнить, что сказал большинство, иначе я бы не спросил)
string CanLeaveWithoutUmbrella()
{
if(sky.Color.Equals(Color.Blue))
{
return "Yes you can";
}
return "No you can't";
}
Вопрос: Есть ли увеличение сложности, вызванное отсутствием else
блока?
У меня сложилось впечатление, что else
более прямо заявляет о своем намерении, заявляя, что код в обоих блоках напрямую связан.
Кроме того, я обнаружил, что могу предотвратить незначительные ошибки в логике, особенно после внесения изменений в код позднее.
Возьмите этот вариант моего упрощенного примера (игнорируя тот факт, что or
оператор, поскольку это намеренно упрощенный пример):
bool CanLeaveWithoutUmbrella()
{
if(sky.Color != Color.Blue)
{
return false;
}
return true;
}
Кто-то может теперь добавить новый if
блок на основе условия после первого примера, не сразу правильно распознав, что первое условие накладывает ограничение на собственное условие.
Если бы else
блок присутствовал, то кто бы ни добавил новое условие, он будет вынужден переместить содержимое else
блока (и если каким-то образом они затенят его, эвристика покажет, что код недоступен, чего не происходит в случае, когда одно if
ограничивает другое) ,
Конечно, есть и другие способы определения конкретного примера, которые предотвращают эту ситуацию, но это всего лишь пример.
Длина приведенного мною примера может исказить визуальный аспект этого, поэтому предположим, что пространство, занятое в скобках, относительно незначительно для остальной части метода.
Я забыл упомянуть случай, в котором я согласен с пропуском блока else, и это при использовании if
блока для применения ограничения, которое должно быть логически выполнено для всего следующего кода, такого как нулевая проверка (или любые другие средства защиты) ,
источник
else
предложения (на мой вкус, он будет еще более читабельным, если оставить ненужные скобки. Но я думаю, что пример не очень хорошо выбран, потому что в в вышеприведенном случае я бы написалreturn sky.Color == Color.Blue
(без if / else). Пример с другим типом возврата, отличным от bool, вероятно, сделает это более понятнымОтветы:
На мой взгляд, явный блок else предпочтительнее. Когда я вижу это:
Я знаю, что имею дело с взаимоисключающими опциями. Мне не нужно читать, что внутри блоков if, чтобы иметь возможность сказать.
Когда я вижу это:
На первый взгляд кажется, что он возвращает false независимо, и имеет дополнительный побочный эффект, небо не голубое.
На мой взгляд, структура второго кода не отражает то, что код делает на самом деле. Плохо. Вместо этого выберите первый вариант, который отражает логическую структуру. Я не хочу проверять логику возврата / прерывания / продолжения в каждом блоке, чтобы узнать логический поток.
Почему кто-то предпочел бы другого, для меня загадка, надеюсь, кто-то займет противоположную позицию, просветит меня своим ответом.
Я бы сказал, что с охраной все в порядке, если ты ушел с счастливого пути. Произошла ошибка или сбой, которые не позволяют продолжить обычное выполнение. Когда это происходит, вы должны сгенерировать исключение, вернуть код ошибки или любой другой, соответствующий вашему языку.
Вскоре после первоначальной версии этого ответа в моем проекте был обнаружен подобный код:
Не помещая возврат внутрь elses, тот факт, что заявление о возвращении отсутствовало, упускалось из виду. Если бы еще был занят, код даже не скомпилирован. (Конечно, гораздо большее беспокойство у меня вызывает то, что тесты, написанные на этом коде, были довольно плохими, чтобы не обнаружить эту проблему.)
источник
else
блока (это может быть неприятно, когда я вынужден делать это просто для того, чтобы придерживаться соглашений для кодовой базы). Мне тоже интересно увидеть контрапункт здесь.} // else
где остальные обычно идут как компромисс между ними.Основная причина удаления
else
блока, который я обнаружил, заключается в избыточном отступе. Короткое замыканиеelse
блоков обеспечивает гораздо более плавную структуру кода.Многие
if
заявления по сути являются охранниками. Они предотвращают разыменование нулевых указателей и других «не делайте этого!» ошибки. И они приводят к быстрому прекращению текущей функции. Например:Теперь может показаться, что здесь
else
было бы очень разумно:И действительно, если это все, что вы делаете, это не намного больше отступ, чем в примере выше. Но это редко все, что вы делаете с реальными многоуровневыми структурами данных (условие, которое возникает постоянно при обработке распространенных форматов, таких как JSON, HTML и XML). Поэтому, если вы хотите изменить текст всех дочерних элементов данного узла HTML, скажите:
Охранники не увеличивают отступ кода. С
else
предложением вся фактическая работа начинает перемещаться вправо:Это начинает иметь значительное движение вправо, и это довольно тривиальный пример, только с двумя условиями охраны. Каждый дополнительный охранник добавляет еще один уровень отступа. Реальный код, который я написал, обрабатывая XML или потребляя подробные потоки JSON, может легко составлять 3, 4 или более сторожевых условий. Если вы всегда используете
else
, вы в конечном итоге с отступом 4, 5 или 6 уровней. Может быть, больше. И это определенно способствует ощущению сложности кода и увеличению времени, затрачиваемого на понимание того, что соответствует чему. Быстрый, плоский стиль раннего выхода устраняет некоторые из этих «лишних структур» и кажется более простым.Приложение Комментарии к этому ответу заставили меня понять, что, возможно, не было ясно, что обработка NULL / empty не единственная причина для условных выражений защиты. Не почти! Хотя этот простой пример фокусируется на обработке пустых / пустых значений и не содержит других причин, поиск глубоких структур, таких как XML и AST, например, для «релевантного» контента часто содержит длинный ряд специальных тестов для отсеивания нерелевантных узлов и неинтересных случаев. Серия тестов «если этот узел не релевантен, возврат» вызовет тот же тип правостороннего дрейфа, что и NULL / пустые охранники. И на практике последующие тесты релевантности часто сочетаются с NULL / пустыми защитными элементами для соответственно более глубоких искомых структур данных - двойной удар для смещения вправо.
источник
else
блок излишним, когда используюif
блок, чтобы применить ограничение, которое должно быть логически выполнено для всего следующего кода, такого как проверка на нуль (или любые другие средства защиты).then
предложении (например, последовательные защитные операторы), то не будет особого смысла избегать конкретногоelse
предложения. Действительно, это уменьшило бы ясность и потенциально могло бы быть опасным (из-за невозможности просто указать альтернативную структуру, которая есть / должна быть там).Когда я вижу это:
Я вижу общую идиому . Распространенный паттерн , который в моей голове звучит так:
Поскольку это очень распространенная идиома в программировании, программист, привыкший видеть такой код, имеет неявный «перевод» в своей голове всякий раз, когда он его видит, что «преобразует» его в надлежащий смысл.
Я не нуждаюсь в явном
else
, моя голова «помещает это туда» для меня, потому что он распознал образец в целом . Я понимаю значение всего распространенного паттерна, поэтому мне не нужны мелкие детали, чтобы прояснить его.Например, прочитайте следующий текст:
Вы читали это?
Если это так, вы не правы. Прочитай текст еще раз. Что на самом деле написано
В тексте есть два слова "the". Так почему ты пропустил один из двух?
Это потому, что ваш мозг увидел общий паттерн и немедленно перевел его в известное значение. Ему не нужно было читать всю деталь по деталям, чтобы выяснить смысл, потому что он уже распознал шаблон , увидев его. Вот почему он проигнорировал лишнее «то ».
То же самое с вышеупомянутой идиомой. Программисты , которые читали много кода привыкли видеть эту картину , из
if(something) {return x;} return y;
. Им не нужен опыт,else
чтобы понять его смысл, потому что их мозг «помещает это для них». Они распознают его как шаблон с известным значением: «то, что после закрывающей скобки будет работать только как неявноеelse
из предыдущегоif
».Так что, на мой взгляд, это
else
не нужно. Но просто используйте то, что кажется более читабельным.источник
Они добавляют визуальный беспорядок в коде, так что да, они могут добавить сложность.
Однако верно и обратное: чрезмерный рефакторинг для уменьшения длины кода также может добавить сложность (конечно, не в этом простом случае).
Я согласен с утверждением, что
else
блок заявляет о намерениях. Но мой вывод другой, потому что вы добавляете сложность в свой код для достижения этой цели.Я не согласен с вашим утверждением о том, что оно позволяет вам предотвратить тонкие ошибки в логике.
Давайте посмотрим на пример, теперь он должен возвращать true только в том случае, если небо синее, а влажность высокая, влажность не высокая или небо красное. Но тогда вы ошибаетесь в одной скобке и помещаете ее в неправильную
else
:Мы видели все подобные глупые ошибки в рабочем коде, и их может быть очень трудно обнаружить.
Я бы предложил следующее:
Я считаю, что это легче читать, потому что я сразу вижу, что по умолчанию
false
.Кроме того, идея принудительного перемещения содержимого блока для вставки нового предложения подвержена ошибкам. Это как-то связано с принципом открытия / закрытия (код должен быть открыт для расширения, но закрыт для модификации). Вы вынуждены изменить существующий код (например, кодер может ввести ошибку в балансировку фигурных скобок).
Наконец, вы заставляете людей отвечать заранее определенным образом, который, по вашему мнению, является правильным. Например, вы представляете очень простой пример, но после этого вы заявляете, что люди не должны принимать его во внимание. Однако простота примера влияет на весь вопрос:
Если случай такой же простой, как и представленный, мой ответ будет состоять в том, чтобы вообще пропустить любые
if else
пункты.возврат (sky.Color == Color.Blue);
Если дело немного сложнее, с различными предложениями, я бы ответил:
bool CanLeaveWithoutUmbrella () {
}
Если дело сложное и не все предложения возвращают true (может быть, они возвращают double), и я хочу ввести некоторую точку останова или команду loggin, я бы рассмотрел что-то вроде:
}
Если мы говорим не о методе, который возвращает что-то, а о блоке if-else, который устанавливает некоторую переменную или вызывает метод, тогда да, я бы включил последний
else
пункт.Поэтому простота примера также является фактором, который необходимо учитывать.
источник
Хотя описанный случай if-else имеет большую сложность, в большинстве (но не во всех) практических ситуациях он не имеет большого значения.
Несколько лет назад, когда я работал над программным обеспечением, которое использовалось для авиационной промышленности (оно должно было пройти процесс сертификации), у вас возник вопрос. Оказалось, что это утверждение «else» связано с финансовыми затратами, поскольку оно увеличивает сложность кода.
Вот почему
Присутствие «else» создало неявный 3-й случай, который должен был быть оценен - ни «if», ни «else» не были взяты. Вы можете думать (как я был в то время) WTF?
Объяснение пошло так ...
С логической точки зрения, есть только два варианта - «если» и «еще». Тем не менее, мы сертифицировали объектный файл, который генерировал компилятор. Поэтому, когда было «другое», необходимо было провести анализ, чтобы подтвердить, что сгенерированный код ветвления был правильным и что загадочный 3-й путь не появился.
Сравните это со случаем, когда есть только «если» и нет «еще». В этом случае есть только два варианта - путь «если» и путь «не если». Два случая для оценки менее сложны, чем три.
Надеюсь это поможет.
источник
Самая важная цель кода - быть понятным как зафиксированный (в отличие от простого рефакторинга, который полезен, но менее важен). Несколько более сложный пример Python может быть использован для иллюстрации этого:
Это довольно ясно - это эквивалент
case
поиска оператора или словаря, версия более высокого уровняreturn foo == bar
:Это более понятно, потому что, хотя количество токенов больше (32 против 24 для исходного кода с двумя парами ключ / значение), семантика функции теперь явная: это просто поиск.
(Это имеет последствия для рефакторинга - если вы хотите получить побочный эффект, если у
key == NIK
вас есть три варианта:if
/elif
/else
и вставьте одну строчку вkey == NIK
кейс.if
операторvalue
для особого случая перед возвратом.if
заявление в звонящего.Теперь мы понимаем, почему функция поиска является мощным упрощением: третий вариант, очевидно, является самым простым решением, поскольку помимо того, что он дает
value
меньшую разницу, чем первый, он единственный, который обеспечивает выполнение только одного действия. )Возвращаясь к коду OP, я думаю, что это может служить руководством для сложности
else
операторов: код с явнымelse
оператором объективно более сложен, но более важно то, делает ли он семантику кода ясной и простой. И на это нужно отвечать в каждом конкретном случае, поскольку каждый фрагмент кода имеет свое значение.источник
case
илиswitch
операторы) менее однородны. Несколько вариантов - это просто возврат значений, но один или два случая требуют дополнительной обработки. И когда вы обнаружите, что стратегия поиска не подходит, вам нужно переписать в совершенно иномif
elif
...else
синтаксисе.Я думаю, это зависит от того, какое
if
заявление вы используете. Некоторыеif
операторы можно рассматривать как выражения, а другие - только как операторы потока управления.Ваш пример выглядит как выражение для меня. В языках, подобных C, троичный оператор
?:
очень похож наif
оператор, но это выражение, и часть else не может быть пропущена. Имеет смысл, что ветвь else не может быть опущена в выражении, потому что выражение всегда должно иметь значение.Используя троичный оператор, ваш пример будет выглядеть так:
Так как это логическое выражение, оно действительно должно быть упрощено вплоть до
Включение явного предложения else делает ваши намерения более ясными. Охрана может иметь смысл в некоторых ситуациях, но при выборе между двумя возможными значениями, ни одно из которых не является исключительным или необычным, они не помогают.
источник
I ask that you ignore the many other ways the function can be written, and changes that can be made to it. (I know most people are itching to write return sky.Color == Color.Blue.)
Еще одна вещь, о которой следует подумать в этом аргументе, - это привычки, которые продвигает каждый подход.
if / else переопределяет образец кода в терминах ветвей. Как вы говорите, иногда это явно хорошо. На самом деле есть два возможных пути выполнения, и мы хотим это подчеркнуть.
В других случаях есть только один путь выполнения, а затем все те исключительные вещи, о которых должны беспокоиться программисты. Как вы упомянули, пункты охраны прекрасно подходят для этого.
Конечно, есть случай 3 или более (n), где мы обычно рекомендуем отказаться от цепочки if / else и использовать оператор case / switch или полиморфизм.
Руководящий принцип, который я имею в виду, заключается в том, что метод или функция должны иметь только одну цель. Любой код с оператором if / else или switch предназначен только для ветвления. Поэтому он должен быть абсурдно коротким (4 строки) и делегироваться только на правильный метод или давать очевидный результат (как в вашем примере). Когда ваш код такой короткий, трудно пропустить эти множественные возвраты :) Во многом как «goto считать вредным», любое утверждение ветвления может быть использовано неправильно, поэтому обычно стоит добавить некоторые критические соображения в операторы else. Как вы упомянули, просто наличие блока else обеспечивает место для скопления кода. Вы и ваша команда должны решить, как вы к этому относитесь.
На что инструмент действительно жалуется, так это тот факт, что у вас есть возврат / разрыв / бросок внутри блока if. Итак, что касается этого, вы написали пункт охраны, но облажались. Вы можете сделать инструмент счастливым или «развлечь» его предложение, не принимая его.
источник
else
семантике, инструменты анализа кода обычно ищут посторонние инструкции, потому что они часто подчеркивают неправильное понимание потока управления.else
Еще черезif
который возвращает впустую биты.if(1 == 1)
часто вызывает одно и то же предупреждение.Я думаю, что ответ зависит от этого. Ваш пример кода (как вы косвенно указываете) просто возвращает оценку условия и лучше всего представляется, как вы, очевидно, знаете, в виде одного выражения.
Чтобы определить, будет ли добавление условия else пояснять или затенять код, вам необходимо определить, что представляет IF / ELSE. Это (как в вашем примере) выражение? Если так, то это выражение должно быть извлечено и использовано. Это условие охраны? Если так, то ELSE является ненужным и вводящим в заблуждение, поскольку это делает две ветви кажущимися эквивалентными. Это пример процедурного полиморфизма? Извлеките это. Это предварительные условия? Тогда это может быть важно.
Прежде чем вы решите включить или исключить ELSE, решите, что он представляет, и вам сообщат, должен ли он присутствовать или нет.
источник
Ответ немного субъективен.
else
Блок может помочь читаемость, установив , что один блок кода выполняется исключительно к другому блоку кода, без необходимости , чтобы прочитать обоих блоков. Это может быть полезно, если, скажем, оба блока относительно длинные. Есть случаи, когда наличиеif
s безelse
s может быть более читабельным. Сравните следующий код с количествомif/else
блоков:с:
Второй блок кода превращает вложенные
if
операторы в охранные предложения. Это уменьшает отступы и делает некоторые условия возврата более понятными («еслиa != b
, тогда мы вернемся0
!»)В комментариях указывалось, что в моем примере могут быть некоторые дыры, поэтому я это уточню немного подробнее.
Мы могли бы написать первый блок кода вот так, чтобы сделать его более читабельным:
Этот код эквивалентен обоим вышеупомянутым блокам, но он представляет некоторые проблемы. Предложение
else
здесь соединяет эти операторы if вместе. В приведенной выше версии статьи об охране пункты охраны не зависят друг от друга. Добавление нового означает просто написание новогоif
между последнейif
и остальной логикой. Здесь это тоже можно сделать, лишь с небольшим увеличением когнитивной нагрузки. Разница, однако, заключается в том, что перед новым предложением защиты должна появиться некоторая дополнительная логика. Когда заявления были независимыми, мы могли сделать:С подключенным
if/else
цепью это сделать не так просто. На самом деле, самый простой путь - это разорвать цепочку, чтобы она выглядела скорее как версия предложения гвардии.Но на самом деле это имеет смысл. Использование
if/else
слабо подразумевает связь между частями. Мы могли бы предположить , чтоa != b
какое - то образом связаны сc > d
вif/else
цепи , версии. Это предположение будет вводить в заблуждение, как мы можем видеть из версии пункта охраны, что на самом деле они не связаны между собой. Это означает, что мы можем делать больше с независимыми предложениями, например, переупорядочивать их (возможно, для оптимизации производительности запросов или для улучшения логического потока). Мы также можем когнитивно игнорировать их, как только мы их пройдем. Вif/else
цепочке я менее уверен, что отношения эквивалентности междуa
иb
не всплывет позже.Отношения, подразумеваемые посредством
else
, также очевидны в глубоко вложенном примере кода, но по-другому. Операторыelse
отделены от условных, к которым они прикреплены, и они связаны в обратном порядке с условными (первоеelse
присоединено к последнемуif
, последнееelse
присоединено к первомуif
). Это создает когнитивный диссонанс, когда мы вынуждены возвращаться назад по коду, пытаясь выровнять отступы в нашем мозгу. Это все равно что пытаться сопоставить кучу скобок. Будет еще хуже, если отступ будет неправильным. Дополнительные скобки тоже не помогают.Это хорошая уступка, но она не лишает законной силы любой ответ. Я мог бы сказать, что в вашем примере кода:
правильная интерпретация для написания кода, подобного этому, может заключаться в том, что «мы должны уходить с зонтиком, только если небо не голубое». Здесь есть ограничение на то, что небо должно быть синим, чтобы следующий код был действительным. Я встретил определение вашей уступки.
Что делать, если я скажу, что если цвет неба черный, это ясная ночь, поэтому зонтик не нужен. (Есть более простые способы написать это, но есть более простые способы написать весь пример.)
Как и в более крупном примере, приведенном выше, я могу просто добавить новое предложение без особой необходимости. В
if/else
, я не могу быть уверен, что я ничего не испорчу, особенно если логика более сложная.Я также укажу, что ваш простой пример тоже не так прост. Тест для недвоичного значения не совпадает с обратным тесту с инвертированными результатами.
источник
else
блока важен для читабельности.Вы слишком упростили свой пример. Любая альтернатива может быть более читабельной, в зависимости от более широкой ситуации: в частности, это зависит от того, является ли одна из двух ветвей условия ненормальной . Позвольте мне показать вам: в случае, когда любая ветвь одинаково вероятна, ...
... более читабельно, чем ...
... потому что первый демонстрирует параллельную структуру, а второй нет. Но когда основная часть функции посвящена одной задаче, и вам просто нужно сначала проверить некоторые предварительные условия, ...
}
... более читабельно, чем ...
... потому что намеренно не устанавливая параллельную структуру дает подсказку будущему читателю, что получение ввода "действительно типа два" здесь ненормально . (В реальной жизни
ProcessInputDefinitelyOfTypeOne
не было бы отдельной функции, поэтому разница была бы еще более резкой.)источник
if
-> Делать исключение и оставить« в качестве стратегии возврата-досрочного возврата . Подумайте о коде, в котором по умолчанию включено больше проверок, и в первую очередь было бы быстрее обработать исключительный случай.when using an if block to apply a constraint that must be logically satisfied for all following code, such as a null-check (or any other guards)
. По логике, любая работаProcessInputOfTypeOne
зависит от того факта, что!InputIsReallyTypeTwo(input)
нам нужно уловить это за пределами нашей обычной обработки. ОбычноProcessInputOfTypeTwo(input);
это былоthrow ICan'tProccessThatException
бы так, что сходство стало бы более очевидным.u+
" обычно вводит токен "диапазон юникода", но если следующий символ не является шестнадцатеричной цифрой, тогда нужно сделать резервную копию и обработать 'u' вместо идентификатора. Таким образом, основной цикл сканера отправляет «сканировать токен диапазона Юникода» несколько неточно, и он начинается с «... если мы находимся в этом необычном особом случае, сделайте резервную копию, а затем вызовите подпрограмму сканирования идентификатора».ProcessInputOfTypeOne
неточную, но быструю проверку, которая иногда вместо этого ловит тип дваДа, сложность возрастает, поскольку предложение else является избыточным . Таким образом, лучше оставить этот код более скудным и подлым. Это соответствует тому же принципу, что и исключение избыточных
this
квалификаторов (Java, C ++, C #), исключение скобок вreturn
операторах и т. Д.Хороший программист думает "что я могу добавить?" в то время как великий программист думает «что я могу удалить?».
источник
else
блока, если оно объясняется в одной строке (что не часто), это часто с такого рода рассуждениями, поэтому +1 для представления аргумента «по умолчанию» я вижу, но я не посчитайте это достаточно сильным рассуждением.A good programmer things "what can I add?" while a great programmer things "what can I remove?".
Кажется, это обычная поговорка о том, что многие люди растягиваются без тщательного рассмотрения, и я лично считаю, что это один из таких случаев.Я заметил, передумал по этому делу.
Когда мне задали этот вопрос около года назад, я бы ответил примерно так:
»Должен быть только один
entry
и одинexit
метод« И с учетом этого я бы предложил изменить код на:С точки зрения коммуникации понятно , что нужно делать.
If
что-то имеет место, манипулируйте результатом одним способом ,else
манипулируйте им другим способом .Но это связано с ненужным
else
.else
Выражает по умолчанию случаю . Таким образом, на втором этапе я мог бы изменить егоТогда возникает вопрос: зачем вообще использовать временную переменную? Следующий шаг рефакторизации приводит к:
Так что это ясно в том, что он делает. Я бы даже пошел еще дальше:
Или для слабонервных :
Вы можете прочитать это так: »CanLeaveWithoutUmbrella возвращает bool . Если ничего особенного не происходит, возвращается false «Это первое чтение сверху вниз.
И затем вы «анализируете» условие »Если условие выполнено, оно возвращает true « Вы могли полностью пропустить условие и поняли, что эта функция делает в регистре по умолчанию . Вашему глазу и уму нужно только пролистать некоторые буквы слева, не читая часть справа.
Да, именно так. Но эта информация избыточна . У вас есть случай по умолчанию и одно «исключение», которое покрывается
if
-statement.Имея дело со сложными структурами, я бы выбрал другую стратегию, исключив
if
илиswitch
вообще уродливого брата .источник
So this is clear in what it does...
и расширить его? (Предыдущие случаи также имеют сомнительное значение). Я говорю это, потому что это то, что задает вопрос, мы исследуем. Вы изложили свою позицию, опуская блок else, и на самом деле эта позиция нуждается в дополнительном объяснении (и та, которая заставила меня задать этот вопрос). Из вопроса:I ask that you ignore the many other ways the function can be written, and changes that can be made to it. (I know most people are itching to write return sky.Color == Color.Blue.)
Короче говоря, в этом случае избавиться от
else
ключевого слова - это хорошая вещь. Здесь это полностью избыточно, и в зависимости от того, как вы форматируете свой код, оно добавит еще одну-три совершенно бесполезных строки в ваш код. Посмотрим, что вif
блоке:Следовательно, если
if
блок должен быть введен, вся остальная функция по определению не выполняется. Но если он не введен, поскольку дальнейшихif
операторов нет, вся остальная функция выполняется. Было бы совершенно иначе, если быreturn
оператор не находился вif
блоке, в этом случае наличие или отсутствиеelse
блока оказало бы влияние, но здесь это не оказало бы влияния.В своем вопросе, изменив свое
if
условие и пропустивelse
, вы заявили следующее:Они должны читать код немного более внимательно. Мы используем языки высокого уровня и четкую организацию кода, чтобы смягчить эти проблемы, но добавление полностью избыточного
else
блока добавляет «шум» и «беспорядок» в код, и нам также не нужно инвертировать или ревертировать нашиif
условия. Если они не могут понять разницу, то они не знают, что делают. Если они могут заметить разницу, то они всегда могут инвертировать исходныеif
условия сами.Это, по сути, то, что здесь происходит, хотя. Вы возвращаетесь из
if
блока, так чтоif
оценка условияfalse
является ограничением, которое должно быть логически выполнено для всего следующего кода.Нет, это приведет к уменьшению сложности вашего кода и даже к уменьшению скомпилированного кода в зависимости от того, будут или нет произойдут некоторые суперивиальные оптимизации.
источник
В приведенном вами конкретном примере это так.
Я думаю, что это не может быть проще, чем это:
источник
if
утверждение. На самом деле я явно не рекомендую дальнейшее упрощение, используя именно тот код, который вы использовали. Кроме того, цикломатическая сложность не увеличиваетсяelse
блоком.Я всегда стараюсь писать свой код так, чтобы намерение было как можно более ясным. В вашем примере не хватает контекста, поэтому я немного его модифицирую:
Наше намерение, кажется, что мы можем уйти без зонта, когда небо голубое. Однако это простое намерение теряется в море кода. Есть несколько способов облегчить понимание.
Во-первых, у вас есть вопрос о
else
филиале. Я не против в любом случае, но, как правило, опускаюelse
. Я понимаю аргумент о явной явности, но мое мнение таково, чтоif
операторы должны заключать в себе «необязательные» ветки, например,return true
одну. Я бы не назвалreturn false
ветку «необязательной», так как она действует по умолчанию. В любом случае, я считаю это очень незначительной проблемой, и гораздо менее важной, чем следующие:Гораздо более важный вопрос заключается в том , что ваши филиалы делают слишком много! Ветви, как и все, должны быть «максимально простыми, но не более». В этом случае вы использовали
if
оператор, который разветвляется между блоками кода (коллекциями операторов), когда все, что вам действительно нужно для разветвления, это выражения (значения). Это понятно, так как а) ваши блоки кода содержат только отдельные операторы и б) они являются одним и тем же оператором (return
). Мы можем использовать троичный оператор,?:
чтобы сузить ветвь только до той части, которая отличается:Теперь мы достигли очевидной избыточности, с которой наш результат идентичен
this.color == Color.Blue
. Я знаю, что ваш вопрос просит нас игнорировать это, но я думаю, что очень важно указать, что это процедурный образ мышления первого порядка: вы разбиваете входные значения и создаете некоторые выходные значения. Это хорошо, но, если возможно, гораздо эффективнее мыслить в терминах отношений или преобразований между входом и выходом. В этом случае отношения очевидно, что они одинаковы, но я часто вижу такой сложный процедурный код, который затемняет некоторые простые отношения. Давайте продолжим и сделаем это упрощение:Следующая вещь , которую я бы указать на то , что ваш API содержит двойной негатив: это возможно ,
CanLeaveWithoutUmbrella
чтобы бытьfalse
. Это, конечно, упрощаетNeedUmbrella
бытьtrue
, поэтому давайте сделаем это:Теперь мы можем начать думать о вашем стиле кодирования. Похоже, вы используете объектно-ориентированный язык, но, используя
if
операторы для перехода между блоками кода, вы в итоге написали процедурный код.В объектно-ориентированном коде все блоки кода являются методами, и все ветвления выполняются с помощью динамической диспетчеризации , например. используя классы или прототипы. Можно спорить, упрощает ли это вещи, но это должно сделать ваш код более совместимым с остальной частью языка:
Обратите внимание, что использование тернарных операторов для ветвления между выражениями распространено в функциональном программировании.
источник
I ask that you ignore the many other ways the function can be written, and changes that can be made to it. (I know most people are itching to write return sky.Color == Color.Blue.)
. На самом деле вы используете точную строку кода, которую я упоминаю. Кроме того, хотя эта часть вопроса не по теме, я бы сказал, что вы слишком далеко зашли в своем заключении. Вы радикально изменили код.return false;
vselse { return false; }
, не заботясь о полярности ветвей, динамической диспетчеризации, троичных и т. Д. Если вы пишете процедурный код на языке OO, радикальные изменения необходимы;)if/else
оператором и какова полярность ветвей.